Changing PLL multiplier causes servo to be not centered
W9GFO
Posts: 4,010
Ok, I've made up a five cell NiMH battery pack for my Protoboard BoeBot. I can now reliably control the servos with my simple testservo.spin program.
Using trial and error I found 1460 to be the magic number for centering the servos. Since I take this number and multiply it by (clkfreq/1_000_000) I assume it to be 1.46 ms.
If I change PLL16x to PLL8x, the servos no longer center. I have to adjust the center number for each different PLL multiplier. It ranges from 1460 @ 16x to 880 @ 1x.
What am I missing here? I expected the use of (clkfreq/1_000_000) * width to equal the same value at any PLL multiplier.
Using trial and error I found 1460 to be the magic number for centering the servos. Since I take this number and multiply it by (clkfreq/1_000_000) I assume it to be 1.46 ms.
If I change PLL16x to PLL8x, the servos no longer center. I have to adjust the center number for each different PLL multiplier. It ranges from 1460 @ 16x to 880 @ 1x.
What am I missing here? I expected the use of (clkfreq/1_000_000) * width to equal the same value at any PLL multiplier.
CON _clkmode = xtal1 + pll16x _xinfreq = 5_000_000 center = 1460 ' 1460 @ 16x, 1425 @8x, 1345 @ 4x, 1190 @ 2x, 880 @ 1x Servo1 = 5 MotorR = 6 MotorL = 7 LED1 = 12 LED2 = 13 LED3 = 14 LED4 = 15 PUB Main repeat PWM(motorL, center) PWM(motorR, center) PWM(servo1, center) waitcnt((clkfreq/1_000) * 20 + cnt) PUB PWM(pin, width) dira[noparse][[/noparse]pin]~~ outa[noparse][[/noparse]pin]~~ waitcnt((clkfreq/1_000_000)* width + cnt) outa[noparse][[/noparse]pin]~
spin
803B
Comments
1us at 80Mhz
2us at 40Mhz
4us at 20Mhz
8us at 10Mhz
16us at 5Mhz
all of these are 80 clocks, just as an example of how it doesn't scale with the clock speed, not actual spin numbers,
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Parallax Forums - If you're ready to learn, we're ready to help.
Graham
I am having to adjust my center number by .58 ms between PLL16x and PLL1x. Isn't that 580 us? I think 580 us is about 3,000 clock cycles @ 5 mhz.
ms = .001 second
us = .000001 second
I would not be surprised at all if there are errors in my math...
This code assumes 'us' is the number of clock cycles in one micro-second. It also limits the pulse duration using the constants Min_uS and Max_uS
This code keeps the pulse length identical as clock frequency changes because the delay due to spin overhead has the exact same effect on the start and end of the pulse. (I.e. same code is used)
Marty
P.S. I just estimated how many clocks of overhead you were seeing, 2,800 clocks. That's a LOT of clocks to add to a delay. Quite reasonable once you dig down into what your short snippet of code brakes down into. (i.e. just the simple OUTA[noparse][[/noparse]pin]~~ probably generates 5-10 spin byte-codes, each code taking 200-300 clocks to execute)
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Lunch cures all problems! have you had lunch?
Post Edited (Lawson) : 8/7/2007 3:52:20 PM GMT
But back to the topic: It is generally ignored that a typical SIMPLE SPIN instruction takes around 10 mys @ 80 MHz (note the upper case letters; it is also mA... The international standards require a capitalization of all units derived from person's names as Andr
I made slight modifications
Is it possible for SyncCnt to reach SyncCNT += 1000 before reaching waitcnt(SyncCnt)? Maybe if it has too much math to do?
Perhaps that is why the conversion to "us" is made at the top of the method, unlike what I am doing here.
don't know! I just chose 1000 as a number small enough not to waste too much time, but large enough to prevent missing the targeted time. I calculated "us" in an Init method because that's how it was done in the BS2_functions library that I based this code on. It worked the first time so I just left it alone [noparse]:)[/noparse]
Marty
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Lunch cures all problems! have you had lunch?