Jump to content

As of July 17, 2015, the LabJack forums here at forums.labjack.com are shut down. New registrations, topics, and replies are disabled. All forums are in a read-only state for archive purposes.

Please visit our current forums at labjack.com/forums to view and make new posts. To post on the current forums, use your labjack.com login account. Your old LabJack forums login credentials have been retired. There are no longer separate logins for labjack.com and LabJack forums.


Photo

Interruptions whit the timers


  • Please log in to reply
16 replies to this topic

#1 Sujaira

Sujaira
  • Members
  • 13 posts

Posted 21 January 2013 - 03:10 PM

Hello, I'm working whit a Servo motor that needs a PWM to work, I used the PWM16 that the Labjack provides. But I'm having a problem when I try to implent the controler. I need to send a diferent PWM every 100 miliseconds. but when I do this the PWM signal started moving like crazy, the Servo dosen't move correctly, I don't know if there it's a way to program this directly into the LabJAck and not in the Code where I have the rest of the program. So how can I control the interruption of one PWM to send other one. I try these before ussing a diferent time loop, whit 1 second to change the signal and worked fine. Could it be that I'm changing the PWM to quick. Plase if anyone can help me. I'm ussing Visual Studio C# whit threadings. Thanks.

#2 LabJack Support

LabJack Support
  • Admin
  • 8677 posts

Posted 21 January 2013 - 03:27 PM

What PWM frequency are you using? Do you know what the resulting signal looks like? What is wrong with it? Perhaps if you have another U3, you could use LJStreamUD to capture a data set with the signals so we can see what they are doing. Post a little code snippet that shows where you update the PWM duty-cycle every 100ms. Perhaps we will see something there.

#3 Sujaira

Sujaira
  • Members
  • 13 posts

Posted 21 January 2013 - 08:20 PM

What PWM frequency are you using?


I'm using a frecuency of 52 Hz.

Do you know what the resulting signal looks like? What is wrong with it? Perhaps if you have another U3, you could use LJStreamUD to capture a data set with the signals so we can see what they are doing.

I don't have another U3 how ever I could go to the lab in my faculty in use the osciloscope.

Post a little code snippet that shows where you update the PWM duty-cycle every 100ms. Perhaps we will see something there.


In the code a program a little funtion that allows to change the duty-cycle named Servomotor, the funtion gets and the angle and move the rotor of the Servo. In another funtion I call this funtion every 100ms. code it's this ones.

public void Medicion()
		{
		 while (true){
			E = (Ref * 3.1416 / 180) - (angulo * 3.1416 / 180);
			U = ((Kp + (To * Ki)) * E) - (Kp * Eant) + Uant;
			Eant = E;
			if (U > 3.1416)
			{
				 U = 3.1416;
			}
			if (U < 0)
			{
				  U = 0;
			}
			Uant = U;
			Servomotor(Ref); //This it's the funtion that change the duty cicle.
			double dblDriverVersion;
			LJUD.IO ioType = 0;
			LJUD.CHANNEL channel = 0;
			double dblValue = 0;
			int dummyInt = 0;
			double dummyDouble = 0;

			dblDriverVersion = LJUD.GetDriverVersion();
			try
			{
				//Request a single-ended reading from AIN0.
				LJUD.AddRequest(u3.ljhandle, LJUD.IO.GET_AIN, 0, 0, 0, 0);

			}
			catch (LabJackUDException a)
			{
				showErrorMessage(e);
			}
			try
			{
				//Execute the requests.
				LJUD.GoOne(u3.ljhandle);
				LJUD.GetFirstResult(u3.ljhandle, ref ioType, ref channel, ref dblValue, ref dummyInt, ref dummyDouble);
			}
			catch (LabJackUDException a)
			{
				showErrorMessage(e);
			}


			try { LJUD.GetNextResult(u3.ljhandle, ref ioType, ref channel, ref dblValue, ref dummyInt, ref dummyDouble); }

			catch (LabJackUDException a)
			{
				showErrorMessage(e);
			}
			angulo = dblValue * 46.59 - 10.16;
			AIN0 = (int)angulo;
			this.SetText(AIN0.ToString()); 

			tiempo = tiempo + To;
			this.SetChart(chart1);

			Thread.Sleep(100);
	  }
}

and this it's the code of the funtion Servomotor. what I do it's calculate the ns that I'll send to the PWM16 funtion for the angle I get. I tested that funtion before and it worked fine, but if you see and error please let me know.

public void Servomotor(double angulo)
		{
			LJUD.IO ioType = 0;
			LJUD.CHANNEL channel = 0;
			double dblValue = 0;

			// Variables to satisfy certain method signatures
			int dummyInt = 0;
			double dummyDouble = 0;
			double[] dummyDoubleArray = { 0 };
			double ns, tao,grad;
			grad = angulo * 180 / 3.1416;
			tao = (0.00001 * grad + 0.000565);
			ns = (0.01911 - tao) * (65536 / 0.01911);

			try
			{

				//First requests to configure the timer and counter.  These will be
				//done with and add/go/get block.

				//Set the timer/counter pin offset to 4, which will put the first
				//timer/counter on FIO4.
				LJUD.AddRequest(u3.ljhandle, LJUD.IO.PUT_CONFIG, LJUD.CHANNEL.TIMER_COUNTER_PIN_OFFSET, 4, 0, 0);

				//Use the 48 MHz timer clock base with divider.  Since we are using clock with divisor
				//support, Counter0 is not available.
				LJUD.AddRequest(u3.ljhandle, LJUD.IO.PUT_CONFIG, LJUD.CHANNEL.TIMER_CLOCK_BASE, (double)LJUD.TIMERCLOCKS.MHZ48_DIV, 0, 0);
				//LJUD.AddRequest(u3.ljhandle, LJUD.IO.PUT_CONFIG, LJUD.CHANNEL.TIMER_CLOCK_BASE, LJUD.TIMERCLOCKS.MHZ24_DIV, 0, 0);  //Use this line instead for hardware rev 1.20.

				//Set the divisor to 48 so the actual timer clock is 1 MHz.
				LJUD.AddRequest(u3.ljhandle, LJUD.IO.PUT_CONFIG, LJUD.CHANNEL.TIMER_CLOCK_DIVISOR, 14, 0, 0);
				//LJUD.AddRequest(u3.ljhandle, LJUD.IO.PUT_CONFIG, LJUD.CHANNEL.TIMER_CLOCK_DIVISOR, 24, 0, 0);  //Use this line instead for hardware rev 1.20.

				//Enable 1 timer.  It will use FIO4.
				LJUD.AddRequest(u3.ljhandle, LJUD.IO.PUT_CONFIG, LJUD.CHANNEL.NUMBER_TIMERS_ENABLED, 1, 0, 0);

				//Configure Timer0 as 16-bit PWM.  Frequency will be 1M/256 = 3906 Hz.
				LJUD.AddRequest(u3.ljhandle, LJUD.IO.PUT_TIMER_MODE, 0, (double)LJUD.TIMERMODE.PWM16, 0, 0);

				//Set the PWM duty cycle
				LJUD.AddRequest(u3.ljhandle, LJUD.IO.PUT_TIMER_VALUE, 0, ns, 0, 0);

				//Execute the requests.
				LJUD.GoOne(u3.ljhandle);
			}
			catch (LabJackUDException e)
			{
				showErrorMessage(e);
			}

			//Get all the results just to check for errors.
			try { LJUD.GetFirstResult(u3.ljhandle, ref ioType, ref channel, ref dblValue, ref dummyInt, ref dummyDouble); }
			catch (LabJackUDException e) { showErrorMessage(e); }
			bool finished = false;
			while (!finished)
			{
				try { LJUD.GetNextResult(u3.ljhandle, ref ioType, ref channel, ref dblValue, ref dummyInt, ref dummyDouble); }
				catch (LabJackUDException e)
				{
					// If we get an error, report it.  If the error is NO_MORE_DATA_AVAILABLE we are done
					if (e.LJUDError == UE9.LJUDERROR.NO_MORE_DATA_AVAILABLE)
						finished = true;
					else
						showErrorMessage(e);
				}
			}

		}


#4 LabJack Support

LabJack Support
  • Admin
  • 8677 posts

Posted 22 January 2013 - 09:25 AM

First thing I would try is to add a new function that just updates the Value (duty-cycle) of Timer0. So, rename you current Servomotor() function to ServomotorConfig(), and make a new function called ServomotorDutyCycleUpdate(). In this new function, just do something like: LJUD.ePut(u3.ljhandle, LJUD.IO.PUT_TIMER_VALUE, 0, ns, 0); ... with nothing else. When you do the full timer configuration it resets the timer each time, which could be causing you a problem that you can see in the motor. When you just use ePut to update the timer Value, you are changing the duty-cycle without a full reset of the timer. This can still have glitching depending on the exact timing of where the PWM is at when the duty-cycle update comes in, but should be smoother than what you have now.

#5 LabJack Support

LabJack Support
  • Admin
  • 8677 posts

Posted 22 January 2013 - 05:33 PM

The glitching I describe is when you get a cycle with totally different PWM than you have specified. For example, you want to change from 25% to 75%, but get 1 cycle of 50% in-between. In 16-bit PWM, firmware looks at the current state of the cycle to try and make the change without a glitch, but it is not foolproof. In 8-bit PWM, there are actually 2 separate registers, so 8-bit does not glitch. Try using 8-bit if you think such a glitch might be your problem.

#6 Sujaira

Sujaira
  • Members
  • 13 posts

Posted 23 January 2013 - 08:41 AM

First thing I would try is to add a new function that just updates the Value (duty-cycle) of Timer0. So, rename you current Servomotor() function to ServomotorConfig(), and make a new function called ServomotorDutyCycleUpdate(). In this new function, just do something like:

LJUD.ePut(u3.ljhandle, LJUD.IO.PUT_TIMER_VALUE, 0, ns, 0);

... with nothing else.

When you do the full timer configuration it resets the timer each time, which could be causing you a problem that you can see in the motor. When you just use ePut to update the timer Value, you are changing the duty-cycle without a full reset of the timer. This can still have glitching depending on the exact timing of where the PWM is at when the duty-cycle update comes in, but should be smoother than what you have now.


I try this but I still have the same problem. Lets see if it works whit the PWM8...

#7 Sujaira

Sujaira
  • Members
  • 13 posts

Posted 23 January 2013 - 09:03 AM

The glitching I describe is when you get a cycle with totally different PWM than you have specified. For example, you want to change from 25% to 75%, but get 1 cycle of 50% in-between.

In 16-bit PWM, firmware looks at the current state of the cycle to try and make the change without a glitch, but it is not foolproof.

In 8-bit PWM, there are actually 2 separate registers, so 8-bit does not glitch. Try using 8-bit if you think such a glitch might be your problem.


I try the PWM8 and I still had the same problem. I don't know what else to do. I did a lot of testing and I realize the problem started when I use the angle I'm getting from the sensor, I meassure this value whit the labjack and then whit the controler send the signal. So it's there any way the problem could that I'm sending a signal that comes from the AIN0??

#8 LabJack Support

LabJack Support
  • Admin
  • 8677 posts

Posted 23 January 2013 - 09:11 AM

First I would make a log of the "ns" values you are sending to the ePut PUT_TIMER_VALUE call. Record a few seconds of values when the servo is not behaving as expected and post these values here. Then, if those values look good to you, you will need to acquire the PWM signal using a scope or similar to see if the signal agrees with the values you are commanding.

#9 Sujaira

Sujaira
  • Members
  • 13 posts

Posted 23 January 2013 - 05:36 PM

First I would make a log of the "ns" values you are sending to the ePut PUT_TIMER_VALUE call. Record a few seconds of values when the servo is not behaving as expected and post these values here.

Then, if those values look good to you, you will need to acquire the PWM signal using a scope or similar to see if the signal agrees with the values you are commanding.


I chec the ns and also try sending a different PWM signal every 100ms, I used a Ref and every 100 ms a incresed the Ref, the motor work just fine. the code goes like this.

while (true){
Ref = Ref + 5;
Servomotor(Ref);
Thread.Sleep(100);
}

So I try ussing the value from the AIN0 and send it, it's the same thing I did in the previos code but know ussing the value token from the LabJack, it goes like this

while (true){
Medicion();
//now I have the current angle
Servomotor(AIN0+5);
Thread.Sleep(100);
}

this should at lest move the motor until the 180 which it's the limit. but just keep moving like crazy. any ideas I can try. I think the function Servomotor it's working fine but somenthing happen when I interact whit the value reading from the LabJack and used to send a new signal to the servomotor.

#10 LabJack Support

LabJack Support
  • Admin
  • 8677 posts

Posted 23 January 2013 - 09:53 PM

What type of servo is this? Typically an R/C servo wants a ~50Hz signal with a pulse-width that varies from 1 ms to 2 ms.

Say you use 16-bit PWM with TimerClockBase = 48 MHz/div and TimerClockDivisor = 14. That results in a PWM8 frequency of 52.3 Hz:

http://labjack.com/s...s-guide/2.9.1.1

That is a period of 19.115 ms, so to get a pulse-width of 1-2 ms you need a duty cycle of about 5.2% to 10.4%. That means you want the time low to be 94.8% to 89.6%, which means you need to pass a Timer Value that varies from 62128 to 58720.

In the code you sent, you say you are passing a Timer Value of AIN0+5. If your AIN0 reading varies from 0-5V, that means you are passing a Timer Value of 5 to 10, which will not get you a 1-2 ms pulse.

#11 Sujaira

Sujaira
  • Members
  • 13 posts

Posted 24 January 2013 - 05:18 AM

What type of servo is this? Typically an R/C servo wants a ~50Hz signal with a pulse-width that varies from 1 ms to 2 ms.

Say you use 16-bit PWM with TimerClockBase = 48 MHz/div and TimerClockDivisor = 14. That results in a PWM8 frequency of 52.3 Hz:

http://labjack.com/s...s-guide/2.9.1.1

That is a period of 19.115 ms, so to get a pulse-width of 1-2 ms you need a duty cycle of about 5.2% to 10.4%. That means you want the time low to be 94.8% to 89.6%, which means you need to pass a Timer Value that varies from 62128 to 58720.

In the code you sent, you say you are passing a Timer Value of AIN0+5. If your AIN0 reading varies from 0-5V, that means you are passing a Timer Value of 5 to 10, which will not get you a 1-2 ms pulse.

No the funtion Servomotor it's one that I program my self, I used a ecuation to transfor the Angle of the Potenciometer to the tao, which it's the representation of duty cycle in miliseconds and previosly I obtain, the ns that that it's a value between 63000 and 57500 the. I'm ussing an standar ServoMotor the Hitec HS-311. it goes like this. the servomotor I'm ussing gets a pulse-width from 0.5 to 2.3 ms.

public void Servomotor(double angulo)
		{
			LJUD.IO ioType = 0;
			LJUD.CHANNEL channel = 0;
			double dblValue = 0;

			// Variables to satisfy certain method signatures
			int dummyInt = 0;
			double dummyDouble = 0;
			double[] dummyDoubleArray = { 0 };
			double ns, tao,grad;
			grad = angulo * 180 / 3.1416;
			tao = (0.00001 * grad + 0.000565);
			ns = (0.01911 - tao) * (65536 / 0.01911);

This are the firts line of the funtion Servomotor. so I get the angle. an the obtain the ns and that the value I send to the timer. but the AIN0 it's not a value betwen 5 or 0 I have the ecuation that translate the voltage of the potenciometer to the angle in degrees.

angulo = dblValue * 46.59 - 10.16;
AIN0 = (int)angulo;

dblValue it's the value that comes directly from the potenciometre through the Labjack, and then I obtain the angle.

#12 LabJack Support

LabJack Support
  • Admin
  • 8677 posts

Posted 24 January 2013 - 09:21 AM

Try a loop with much simpler code to see what happens. Something like:

while (true)
{
	eGet(handle, LJ_ioGET_AIN, 0, &volts, 0);	
	DutyCycle = (5500*(volts/5.0)) + 57500;  //assuming AIN0 reading is 0-5V
	printf(DutyCycle);
	ePut(handle, LJ_ioPUT_TIMER_VALUE, 0, DutyCycle, 0);
	wait(100);	
}

Connect AIN0 to a fixed steady voltage between 0 and 5V for this test.

#13 LabJack Support

LabJack Support
  • Admin
  • 8677 posts

Posted 24 January 2013 - 11:39 AM

And if that still has problems try an even simpler loop:

while (true)
{
	eGet(handle, LJ_ioGET_AIN, 0, &volts, 0);	
	ePut(handle, LJ_ioPUT_TIMER_VALUE, 0, 60000, 0);
	wait(100);	
}


#14 Sujaira

Sujaira
  • Members
  • 13 posts

Posted 27 January 2013 - 08:34 PM

And if that still has problems try an even simpler loop:

while (true)
{
	eGet(handle, LJ_ioGET_AIN, 0, &volts, 0);	
	ePut(handle, LJ_ioPUT_TIMER_VALUE, 0, 60000, 0);
	wait(100);	
}


Nothing, I still have the same problem I have try everything and I don't know what else can I do. I really need to fix this problem. How can I control the interruptions of the LabJack??

#15 LabJack Support

LabJack Support
  • Admin
  • 8677 posts

Posted 28 January 2013 - 11:05 AM

But if you get rid of the AIN read the problem goes away?

while (true)
{
	ePut(handle, LJ_ioPUT_TIMER_VALUE, 0, 60000, 0);
	wait(100);	
}

Have you been able to use a scope to look at the PWM signal in both cases?

#16 LabJack Support

LabJack Support
  • Admin
  • 8677 posts

Posted 28 January 2013 - 11:43 AM

I just did a test in LabVIEW. I have UD driver V3.32 and U3 firmware V1.45. I configured 1 timer on FIO4 as 16-bit PWM with TimerClockBase = 48 MHz/div and TimerClockDivisor = 14. I then had the basic test loop:

while (true)
{
	eGet(handle, LJ_ioGET_AIN, 0, &volts, 0);	
	ePut(handle, LJ_ioPUT_TIMER_VALUE, 0, 60000, 0);
	wait(100);	
}

With or without the LJ_ioGET_AIN in the loop made no difference. Either way I got a solid 52 Hz signal with ~8% duty-cycle. Don't see anything unusual.

#17 Sujaira

Sujaira
  • Members
  • 13 posts

Posted 29 January 2013 - 04:09 PM

I just did a test in LabVIEW. I have UD driver V3.32 and U3 firmware V1.45. I configured 1 timer on FIO4 as 16-bit PWM with TimerClockBase = 48 MHz/div and TimerClockDivisor = 14. I then had the basic test loop:

while (true)
{
	eGet(handle, LJ_ioGET_AIN, 0, &volts, 0);	
	ePut(handle, LJ_ioPUT_TIMER_VALUE, 0, 60000, 0);
	wait(100);	
}

With or without the LJ_ioGET_AIN in the loop made no difference. Either way I got a solid 52 Hz signal with ~8% duty-cycle. Don't see anything unusual.


I fix the problem, Thanks for the help.


0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users