Jump to content
oxxyfx

Servo stracher

Recommended Posts

Hello,

I wrote a code to strech the servo pulses so it will make the servo move 170 - 175 degrees - given by the physical limitations inside of the servo.

Tested, works, however from time to time I see a little jitter - I guess this is a result of the matematical expansion of the pulses, in some position of the stick it may come out with higher or lower values. I confirmed this on the scope, if I put the mark in the middle, the pulse moves from one side to the other.

The incoming pulse is steady, so it has to be the mathematics. I am writing the code in C, does anybody has any idea how can I stabilize this jitter?

Thanks, Ox.

Share this post


Link to post
Share on other sites

Hi, Oxy

The only way is to have a high input resolution ...

as you multiply the input by a factor of ~ 2 ... and you MUST have less than 5-6 µS output resolution ...

The input resolution has to be 2-3 µS as a maximum .... :rolleyes:

Double precision is required here !!! ... and a 9+ bits coder ... if digital !!!

Alain ... PbP user :P

Edited by Acetronics

Share this post


Link to post
Share on other sites

Hello, thanks for the reply. I think the input is set on high resolution, also the timer I am counting the pulse leght with is set at the beginning of the code to 0.2µs.

at least I think that's what the:

setup_timer_1(T1_INTERNAL|RTCC_DIV_1);

means.

However it seems that the counter brings back the pulse lenght value in µs. If in the middle of the stick, the pulse lenght is always between 1400 and 1600µs.

I checked that with the scope. Normally I would assume that this resolution is high enough, isn't it?

From here I make my calculations for the outgoing pulse length, and that's where the little jitter comes in.

Since I am delaying about 3ms after the pulse and only then I am sending out mine, there is a delay command, as:

Delay_us(3000-pulse length);

and then:

servo = on;

Here I shoudl have a:

delay_us(new_pulse_length);

and then

servo off;

however, the PIC does not execute that second delay - only if it s fixed value. (Don't ask me why, I still hope somebody will be able to tell me why....) so I have to trick it and send it to a

for(i = 0; i<pulselength/16; i++){

delay_us(1);

}

cicle, which will finally give me the correct pulse length - but I guess because of the division the jitter comes in here and there.

Ox.

Share this post


Link to post
Share on other sites
I think the input is set on high resolution, also the timer I am counting the pulse leght with is set at the beginning of the code to 0.2µs.

at least I think that's what the: setup_timer_1(T1_INTERNAL|RTCC_DIV_1);

I understand you are using a 20Mhz xtal and a 16-bit timer. With a divide-by-1 T1 prescaler, you should not see any jitter, even after pulse stretching. You have a problem somewhere. Could be hardware, could be software.

however, the PIC does not execute that second delay - only if it s fixed value. (Don't ask me why, I still hope somebody will be able to tell me why....)

With the CCS C compiler, variable params on the delay_us() and delay_ms() functions must be 8-bit values (your 16-bit timing param is being truncated to lower 8-bits). Only hard coded params can be 16-bits with the timing functions.

I am curious, which PIC are you using?

Share this post


Link to post
Share on other sites

For development is the 16F627. This is I've been developing my code on.

There is no external xtal, I am using the internal oscillator of the PIC - and the

#use delay(clock = 4000000)

Once the code is woorking properly I plan to translate it to 12C672 or 12C509 - I am not sure which one yet.

This is interesting about the timer, because the previous delay instruction:

delay_us(3000-pulse) executes correctly - and the result of that in all the time bigger than 8 bit. For ex. at low stickposition it would be 3000-1000 = 2000 and I can verify on the scope that the pulses are coming exactly at the same interval.

The circuit is very simple, there is a decoupler capacitor between the Vcc and ground of a 0.1µF value, there is a 1k resistor between the incoming signal line and the pin I am inputing the signal on, and there is a 4.7k resistor from Vcc to the MCLR pin. The signal out pin is directly connected to the servo, however I tried different resistors there, and it doesn't make much difference. The whole circuit is powered by a 7.4V 2 cell lipo.

For the outgoing pulse length calculation I first calculate the percentage of the stick on the input, compared to the theoretical 1000µs - 2000µs, and then I apply this percentage to the outgoing theoretical range of 500-2500µs.

This way I think I get the most accurate position for the outgoing pulse.

Is there a better way to create the delay than the one I already described with the for cyle?

Thx,

Ox.

Share this post


Link to post
Share on other sites
For development is the 16F627. This is I've been developing my code on.

There is no external xtal, I am using the internal oscillator of the PIC - and the

#use delay(clock = 4000000)

The previous timing information you provided indicated that a 20Mhz osc was being used. With the 4Mhz source, timer resolution is 1uS with a divide-by-1 prescale, not 0.2uS. Still not bad, but harder to minimize jitter unless extreme care is taken in your software.

delay_us(3000-pulse) executes correctly - and the result of that in all the time bigger than 8 bit. For ex. at low stickposition it would be 3000-1000 = 2000 and I can verify on the scope that the pulses are coming exactly at the same interval.

Sorry about that, my info was outdated. In the past, the CCS delay_() functions ignored the upper 8-bits in a 16-bit variable param. But, I just looked at a recent manual I have and they do indeed now support 16-bit params. It looks like it was added in 2006 and snuck past me. However, there may be a bug in the improved function since your delay_us(new_pulse_length) function is not working.

there is a 1k resistor between the incoming signal line and the pin I am inputting the signal on, and there is a 4.7k resistor from Vcc to the MCLR pin.

What pin are you using for the PPM in? The input characteristics can vary, depending on the pin choice. Also, the 4.7K on MCLR is not needed if the MCLR fuse has disabled external resets. Some hobby quality PIC programmer/burners need the resistor to help them during programming, but that is in special cases.

The whole circuit is powered by a 7.4V 2 cell lipo.

I assume you mean you have a Voltage regulator to power the PIC16F627, which cannot tolerate >6.5V. An unregulated 2-S Lipo's voltage may stress it. Furthermore, the timer calibration is based on a fixed 5V source (not always a concern, but good to note in case it matters). A Vreg will stabilize noisy voltages (servo ripple, for example), which will maintain timer stability. BTW, when your switch to other PICs the max voltage limit may change, so be sure to consult the data sheet.

Share this post


Link to post
Share on other sites

Thank you all this is excellent info.

The previous timing information you provided indicated that a 20Mhz osc was being used. With the 4Mhz source, timer resolution is 1uS with a divide-by-1 prescale, not 0.2uS. Still not bad, but harder to minimize jitter unless extreme care is taken in your software.

The original PIC wizzard sets the osc to 20Mhz, which I overriden in my code - I guess in order to get the integer 1uS timer resolution. I understand wnat you mean here, I will have to recalculate a few values to use the 20Mhz osc.

Sorry about that, my info was outdated. In the past, the CCS delay_() functions ignored the upper 8-bits in a 16-bit variable param. But, I just looked at a recent manual I have and they do indeed now support 16-bit params. It looks like it was added in 2006 and snuck past me. However, there may be a bug in the improved function since your delay_us(new_pulse_length) function is not working.

I am using an older compiler, so you are right, it is possible that that's why it is not working correctly.

What pin are you using for the PPM in? The input characteristics can vary, depending on the pin choice. Also, the 4.7K on MCLR is not needed if the MCLR fuse has disabled external resets. Some hobby quality PIC programmer/burners need the resistor to help them during programming, but that is in special cases.

The PPM is comin gonto the RB.0 pin. I tried to bring it in on the RA.0 but I had extremly hard time to turn the comparator off, and use it as a digital input. I've never got that to work, so I decided on swithcing ports and use RB as input and RA as output. The PIC is programmed in a programmer, then I take it out and I put it in my test circuit. I tried the circuit without the 4.7k resistor, it is simply not working even with the NOMCLR fuse set. By the way here are the fuses I am using:

#fuses NOWDT,INTRC, INTRC_IO, NOPUT, NOPROTECT, NOMCLR, NOLVP, NOCPD

I assume you mean you have a Voltage regulator to power the PIC16F627, which cannot tolerate >6.5V. An unregulated 2-S Lipo's voltage may stress it. Furthermore, the timer calibration is based on a fixed 5V source (not always a concern, but good to note in case it matters). A Vreg will stabilize noisy voltages (servo ripple, for example), which will maintain timer stability. BTW, when your switch to other PICs the max voltage limit may change, so be sure to consult the data sheet.

I have a regulated power supply and I was using that. However when I connected the servo to the testboard, every few seconds the PIC rebooted - I am not sure why, the voltage even on thatone was over 5 but less than 6.5. Then I switched to the lipo which seem to give stable results - however good thing you've noticed, I'll put a regulator on tonight.

Thx, Ox

Share this post


Link to post
Share on other sites
I will have to recalculate a few values to use the 20Mhz osc.

There is often a significant EMI/RFI reduction when using the internal osc (good advantage for circuits that connect to a R/C Rx). So, I highly recommend using it if you can. Keep in mind that there are low pin count PIC's with 8Mhz internal osc's, which work very well for low jitter R/C servo apps.

I am using an older compiler, so you are right, it is possible that that's why it is not working correctly.

It is important to determine if your compiler version correctly supports 16-bit params on the delay_() functions. Otherwise, your use of the delay_us(3000-pulse length) may be affected (and maybe explains your "jitter"). I suggest that you take a hard look at the assy code that is produced for the delay functions to see what is going on.

The PPM is coming onto the RB.0 pin.

That is a fine input pin to use as long as the external interrupt feature is not involved. If you are using it only with the input() function then you are good to go. Otherwise, the interrrupt's schmitt input characteristics will cause compatibility issues with some rx's (due to signal level).

The PIC is programmed in a programmer, then I take it out and I put it in my test circuit. I tried the circuit without the 4.7k resistor, it is simply not working even with the NOMCLR fuse set.

With the CCS NOMCLR fuse directive, the MCLR input is configured as a standard input. Since it seems to still be acting like MCLR, I would say your programmer is not correctly burning the fuses. When you read the programmed part, do the correct fuses appear? If the fuses are correctly programmed, then something unexplained and evil is present.

By the way here are the fuses I am using:
#fuses NOWDT,INTRC, INTRC_IO, NOPUT, NOPROTECT, NOMCLR, NOLVP, NOCPD[/code]

Those settings will eventually result in poor power-up reset. You need to use this instead:

#fuses NOWDT,INTRC_IO, PUT, BROWNOUT, NOPROTECT, NOMCLR, NOLVP, NOCPD

Share this post


Link to post
Share on other sites

Thank you Mr. Rc-Cam.

I've replaced my old flaky compiler with a new one, the delay function complies well now.

I am not sure about the fuses, but you are probably right, I have to check if my other programmer does a better job - however that one always want to override the factory precalibrated osc value, so that's why I have not been using it. But I willt try it with that.

To all my best efforts I can still see some jitter. I measured it with the scope, and it looks like it is a +/- 25µs signal variance in some cases. If I just touch the stick in this case, it disappears.

I would like to PM you the source code - since you've been so helpful - so you can look over it and comment on it.

Since I started programming PIC about 3 weeks ago and C around the same time - I am probably missing some things - which obviously I am not aware of.

Please let me know if I can PM you with the source code.

Thanks, Ox.

Share this post


Link to post
Share on other sites
I measured it with the scope, and it looks like it is a +/- 25µs signal variance in some cases.

That is a large variance. There is something very wrong.

I would like to PM you the source code - since you've been so helpful - so you can look over it and comment on it.

You should post it on the forum. That way others can help and learn. If the code is proprietary, and for privileged eyes only, then even I don't want to have access to it.

Share this post


Link to post
Share on other sites

I think I've got it:

I've been using:

#use fast_io (a)

where I should have used both:

#use fast_io (a)

#use fast_io (B)

Thank you, the scope shows I am right.

Ox.

Edited by oxxyfx

Share this post


Link to post
Share on other sites
To all my best efforts I can still see some jitter. I measured it with the scope, and it looks like it is a +/- 25µs signal variance in some cases. If I just touch the stick in this case, it disappears.

Maybe it is a hardware problem in your transmitter. Maybe transmitter pots are worn out near center position and hence the jitter.

I have Optic 6 and it' seems to be quite noisy (I saw it first when I connected it to PC to use it with FMS - the channel preview bars in the config dialog box were quite jittery).

I've been also doing some tests recently with Atmels and measuring PPM pulses and with 1 timer tick per 1 us resolution measured pulse lenght values had visible noise on the last digit. I didn't pay much attention to this, since my application didn't require high precision.

One thing has just come to my mind. I was reading some docs on OSD and TV signal generation with microcontrollers (AVR) and I read that if you don't make your microcontroller sleep before the interrupt on which some kind of pulse measurement is to start, you will get jitter. If you instead go to sleep mode to wait for an external interrput, then the interrupt as it occurs will not have to wait until an instruction being executed is completed (which may consume several clock cycles). If you run on slow clock speeds maybe that's the reason. I dunno. Just an idea. Anyway if this is the case, let me know.

Share this post


Link to post
Share on other sites
I think I've got it

That is good to hear. I'm not sure how the fast_io directive cured the +/-25uS jitter, but you can't argue with success. :) You should be able to achieve <5uS jitter with the 4Mhz osc.

Share this post


Link to post
Share on other sites

Mieczotronix,

I don't think that was the case, I measured the signal coming out from the receiver and it is rock steady.

Thanks, Ox.

Share this post


Link to post
Share on other sites

ok, thanks,

I am sorry if this is too much OT, but since you appear to have precise measuring equipment - could you tell me what kind of precission you re getting with reading servo pulses right now? i.e. what's the range of values you're gettting and how high is noise and at what timer clock?

I am asking this since i've been thinking recently about encoding 8-bit values in PPM to be sent to my plane to control some stuff. In the plane a circut would be connected to receiver which will measure ppm pulses and convert their lenght to 8-bit values. Since recently I've had no time to test it, and the whole concept is still only in my head, I've been wondering whether encoding 8-bit values in PPM pulses would be feasible. I initially assumed the whole tx/rx path will be too nosiy and I will have to encode 4-bit values and send two frames to get one byte transmitted, but from what you've been saying it now seems to me that maybe 8-bit would work stright away. What do you guys think?

Edited by mieczotronix

Share this post


Link to post
Share on other sites

Since I am using a 40Mhz scope, the measuring precision can go as low as 1-2µs. I looked at the signal coming out from the receiver, and scaled down to 5µs scale, and it was quite steady.

This receiver is an E-sky single conversion receiver (sounds like no-name to me) - so some of my jitter problems may come from the fact that is single conversion, even though the transmitter was right beside it - however with collapsed antena. (Mr. Rc-Cam - would probably say that - most likely that is the main problem of my jitter - and he most likely would be right. - I think I'll test this tonight...)

I haven't had a chance yet to measure a dual conversion or a PCM receiver, I cannot talk about those.

Share this post


Link to post
Share on other sites

Just on a note, E-Sky are new but not no-name. They make the little Lama coaxial helicopters and such small things. Starting to get alot more products out now, all are quite good quality.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×