AttoPilot,
Thanks for the suggestion on servo32.spin. This is one of my hobbies, along with RC model airplanes. I am prone to want to do everything on my own from scratch for the fun of it, but in this case I may have to break ny own rules. What is frustrating is that my BS2 bot really did great things, like obstacle avoidance and using sensors for navigation, but I didn't like having to do everything in sequence due to the single processor, so the Propeller was the obvious upgrade. I am not getting discouraged, the Prop is so far and above the BS2, it has just been a little frustrating thats all.
Richard
Yiiikes! my troubles with this chip are never ending.
Here's the latest:
Servo speeds change based on the number of repeats in a loop. No kidding! Both servos are running forward under a repeat direction command when the number of repeats is less than 28. When the number of repeats goes above 28 they change directions. Not only that, I can change servo speeds with the repeat number!
The order in which I initiate a cog process seems to matter. If I initiate the blinking LED cog process before the servo command process, it works fine. Put it after the servo command process and it wont run.
The "if ina[noparse][[/noparse]pin]"·and·"if not ina[noparse][[/noparse]pin]" directives are erratic. Sometimes they work, sometimes they don't.
All the while the LED keeps blinking at 1 Hz supposedly indicting the clocks are working okay.
I am obviously frustrated. Either I have a bad chip or I am really dumb. I am hoping for the bad chip. I will talk to Parallax and get a new chip to try. I will let you know how this works out. Thanks for all of the inputs.
I'd bump the stack from 20 to 50 to be safe (probably not an issue though).
Also note that each servo is only being updated at 25 times a second because you are doing the
right and left alternating. (You are only using a single cog for both servos and you are sending
one pulse to one, waiting 1/50th of a second, then sending a pulse to the other one, and again
waiting 1/50th of a second.) You might want to use /100 to get updates at 50hz to each
server, alternating pulses. An update rate of only 25hz will definitely cause the servos to
act more "jerky" than they normally do.
Note that there will assuredly be at least some small influence from servo to servo because of
this (a longer pulse width on the right will also slow the update rate on both, so the same value
for the left pulse will have different behavior depending on the pulse width for the right.)
What I would do here is either use FullDuplexSerial or else TV to send output back, and add
in some debugging printfs. I suspect your ldir/rdir variables are not holding the values you
think they are.
Note that the initiated cog will probably not start running until some time after the initiation
command returns. (It takes some time for a cog to start up, during which the cog that
started it continues to run.) And this time is affected by the clock rate.
I still don't understand what is going wrong, however; none of these observations here
really explain the behavior you are seeing. Your comments on "repeat" don't make sense
with respect to the earlier code; as always, please attach full code whenever reporting new
observations.
When you say "initiate the blinking LED cog process after the server process and it wont
run" I'm not sure what you mean; what do you observe, and how does that differ from
what you expect?
Post your latest complete code and I'll download it to my boebot (after changing the
servo pin numbers) and let you know what it does on my bot.
I got up this morning after a good nights sleep, cleared my mind, and rewired my board and rewrote my program from the beginning, testing each part as added. Attached is the most basic·two_wheeled robot control program which allows you to enter a single robot direction. It works perfectly! The next step is to add a command/direction sequence using variable addresses (pointers) so the servo directions can be changed·on the fly. I wanted everyone to see what I have at this point and the fact that it is working at Pll16x.·However, the problem of changing clock frequency causing a change in "waitcnt" still exists. If I do nothing more than change clkfreq to pll1x the timeing is completely·different and I have to rewrite the "case" satement with new timing values to get the same servo diection results. By the way, all jittering is gone. This doesn't effect my project because I don't need to change clock frequency at run-time, but something is still wrong and I would like to know what it is. When I get the run-time servo direction changes going I will post that.
Thanks,
Richard
By scaling the way you do you ensure that the target for the waitcnt is correct. However the time between the outa[noparse][[/noparse]18]~~ and the waitcnt beginning to wait will vary depending on the clock frequency of the processor because the time taken to evaluate the division will vary.
Either do all the calculation of the argument for the waitcnt outside of the loop or do:
repeat
outa[noparse][[/noparse]18]~~
c:= cnt
waitcnt(clkfreq/direct + c)
outa[noparse][[/noparse]18]~
c:= cnt
waitcnt(clkfreq/50 + c)
This way you have taken a note of cnt and it can continue ticking away while you work out the target.
This may not work for slower clock frequencies (if the calculation takes too long) and you will need to tweak your values a little to begin with.
I failed to mention that when I rewired my breadboard this morning I kept all leads as short as possible (wires layed flat and direct). The fact that the jittering has gone away, as well as some other wierd behavior I was observing, indicates possible radio frequency interference being fed back into the chip. This may explain why 80MHZ would not work before and now it does. Also, no jittering points to the same thing. The servo motors are brushed and probably sparking. With long length looping wires running from point to point on the breadbooard it is possible RF was being fed through the servo leads into adjacent wiring. I would like to hear what Parallax thinks about this possibility.
...You can save yourself the headache of having to re-calculate your current 'case' statements at different PLL frequencies. (pllx settings 1,2,4,8,16)
"The servo motors are brushed and probably sparking. With long length looping wires running from point to point on the breadbooard it is possible RF was being fed through the servo leads into adjacent wiring." · Yes these can all cause a servo to·jitter. · Do you have a current limiting resistor between the Propeller I/O and the servo?· Since you are using a Propeller (3.3V system) with a Servo (> 3.3V system) a resistor is required to prevent I/O damage to the Propeller.· Also, the resistor is two-fold, it acts as a shunt to suppress or dampen any voltage spikes that could be generated from a noisy servo. · With long leads from the Propeller I/O, and power·to the servo, it is suggested that you use a 1000uF capacitor as close as possible to the servo power connector.· · ·····
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ Beau Schwabe
IC Layout Engineer
Parallax, Inc.
Post Edited (Beau Schwabe (Parallax)) : 6/7/2007 6:01:27 PM GMT
Well, I am glad to announce I now have my bot running smoothly on the Propeller chip and it works great. I am attaching the automonous roving program with whisker obstacle avoidance. Any suggestions would be most welcome and thanks for all of the help. I will be working on better ways for timing the pulses to the servos, putting in rampup and rampdown methods, as well as navigation sensors.
The short simple answer... It's easier to read the actual uS that you want to delay rather than the inverse of the delay, and you get slightly better resolution.
Take for example the first value he has for 'direct' to keep the left servo centered... 662
Example1:
using the formula...
ClockCounts = clkfreq * 1/direct
ClockCounts = 80_000_000 / 662
ClockCounts = 120845
To confirm this, multiply 'ClockCounts' by 12.5nS and you get 1510uS (typical servo center is 1500uS)
Example2:
using the same formula now we'll use 663
ClockCounts = clkfreq * 1/direct
ClockCounts = 80_000_000 / 663
ClockCounts = 120663
To confirm this, multiply 'ClockCounts' by 12.5nS and you get 1508uS
Example3:
using the same formula now we'll use 661
ClockCounts = clkfreq * 1/direct
ClockCounts = 80_000_000 / 661
ClockCounts = 121028
To confirm this, multiply 'ClockCounts' by 12.5nS and you get 1512uS
Example4:
using the formula...
ClockCounts = (clkfreq/1_000_000)*direct
ClockCounts = (80_000_000 / 1_000_000)*1510
ClockCounts = 120800
To confirm this, multiply 'ClockCounts' by 12.5nS and you get 1510uS
Example5:
using the same formula now we'll use 1511uS
ClockCounts = (clkfreq/1_000_000)*direct
ClockCounts = (80_000_000 / 1_000_000)*1511
ClockCounts = 120880
To confirm this, multiply 'ClockCounts' by 12.5nS and you get 1511uS
Example6:
using the same formula now we'll use 1509uS
ClockCounts = (clkfreq/1_000_000)*direct
ClockCounts = (80_000_000 / 1_000_000)*1509
ClockCounts = 120720
To confirm this, multiply 'ClockCounts' by 12.5nS and you get 1509uS
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ Beau Schwabe
IC Layout Engineer
Parallax, Inc.
That's what I thought but even with his way or writing it the pulse widths should have shifted with pll multilier to provide roughly the same pulse width:
Which is what made me suggest taking a note of cnt while the argument of the waitcnt was calculated, I could not see a reason why it would not work as it was.
Comments
Thanks for the suggestion on servo32.spin. This is one of my hobbies, along with RC model airplanes. I am prone to want to do everything on my own from scratch for the fun of it, but in this case I may have to break ny own rules. What is frustrating is that my BS2 bot really did great things, like obstacle avoidance and using sensors for navigation, but I didn't like having to do everything in sequence due to the single processor, so the Propeller was the obvious upgrade. I am not getting discouraged, the Prop is so far and above the BS2, it has just been a little frustrating thats all.
Richard
I wonder if it is just a bad connection, might be worth checking resistances leg to leg between components etc.
Graham
Here's the latest:
Servo speeds change based on the number of repeats in a loop. No kidding! Both servos are running forward under a repeat direction command when the number of repeats is less than 28. When the number of repeats goes above 28 they change directions. Not only that, I can change servo speeds with the repeat number!
The order in which I initiate a cog process seems to matter. If I initiate the blinking LED cog process before the servo command process, it works fine. Put it after the servo command process and it wont run.
The "if ina[noparse][[/noparse]pin]"·and·"if not ina[noparse][[/noparse]pin]" directives are erratic. Sometimes they work, sometimes they don't.
All the while the LED keeps blinking at 1 Hz supposedly indicting the clocks are working okay.
I am obviously frustrated. Either I have a bad chip or I am really dumb. I am hoping for the bad chip. I will talk to Parallax and get a new chip to try. I will let you know how this works out. Thanks for all of the inputs.
Richard
Also note that each servo is only being updated at 25 times a second because you are doing the
right and left alternating. (You are only using a single cog for both servos and you are sending
one pulse to one, waiting 1/50th of a second, then sending a pulse to the other one, and again
waiting 1/50th of a second.) You might want to use /100 to get updates at 50hz to each
server, alternating pulses. An update rate of only 25hz will definitely cause the servos to
act more "jerky" than they normally do.
Note that there will assuredly be at least some small influence from servo to servo because of
this (a longer pulse width on the right will also slow the update rate on both, so the same value
for the left pulse will have different behavior depending on the pulse width for the right.)
What I would do here is either use FullDuplexSerial or else TV to send output back, and add
in some debugging printfs. I suspect your ldir/rdir variables are not holding the values you
think they are.
Note that the initiated cog will probably not start running until some time after the initiation
command returns. (It takes some time for a cog to start up, during which the cog that
started it continues to run.) And this time is affected by the clock rate.
I still don't understand what is going wrong, however; none of these observations here
really explain the behavior you are seeing. Your comments on "repeat" don't make sense
with respect to the earlier code; as always, please attach full code whenever reporting new
observations.
When you say "initiate the blinking LED cog process after the server process and it wont
run" I'm not sure what you mean; what do you observe, and how does that differ from
what you expect?
Post your latest complete code and I'll download it to my boebot (after changing the
servo pin numbers) and let you know what it does on my bot.
May I suggest that you post as a file the most representative program you have run.
Also post a picture of your set up.
And try servo32 just as a test.
Graham
Thanks,
Richard
Post Edited (RichardF) : 6/7/2007 1:05:40 PM GMT
Either do all the calculation of the argument for the waitcnt outside of the loop or do:
This way you have taken a note of cnt and it can continue ticking away while you work out the target.
This may not work for slower clock frequencies (if the calculation takes too long) and you will need to tweak your values a little to begin with.
Graham
[noparse]/noparse]edit: the matlab code won't help [noparse]:)[/noparse
If you change the scaling factor of the code below....
...So that it reads...
...and you change your case statements so that they read...
...You can save yourself the headache of having to re-calculate your current 'case' statements at different PLL frequencies. (pllx settings 1,2,4,8,16)
"The servo motors are brushed and probably sparking. With long length looping wires running from point to point on the breadbooard it is possible RF was being fed through the servo leads into adjacent wiring."
·
Yes these can all cause a servo to·jitter.
·
Do you have a current limiting resistor between the Propeller I/O and the servo?· Since you are using a Propeller (3.3V system) with a Servo (> 3.3V system) a resistor is required to prevent I/O damage to the Propeller.· Also, the resistor is two-fold, it acts as a shunt to suppress or dampen any voltage spikes that could be generated from a noisy servo.
·
With long leads from the Propeller I/O, and power·to the servo, it is suggested that you use a 1000uF capacitor as close as possible to the servo power connector.·
·
·····
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Beau Schwabe
IC Layout Engineer
Parallax, Inc.
Post Edited (Beau Schwabe (Parallax)) : 6/7/2007 6:01:27 PM GMT
Thanks again,
Richard
Post Edited (RichardF) : 6/7/2007 7:12:29 PM GMT
I didn't see your post until right now. I will incorporate your recommended changes and test it out at different clock frequencies.
Richard
Why should it make a difference?
(clkfreq/1_000_000)*direct is basically:
clkfreq * (direct/1_000_000)
Where as what he was doing was:
clkfreq * 1/direct
Both (direct/1_000_000) and (1/direct) are constants independant of the PLL.
I'm just a bit confused now.
The short simple answer... It's easier to read the actual uS that you want to delay rather than the inverse of the delay, and you get slightly better resolution.
Take for example the first value he has for 'direct' to keep the left servo centered... 662
Example1:
using the formula...
ClockCounts = clkfreq * 1/direct
ClockCounts = 80_000_000 / 662
ClockCounts = 120845
To confirm this, multiply 'ClockCounts' by 12.5nS and you get 1510uS (typical servo center is 1500uS)
Example2:
using the same formula now we'll use 663
ClockCounts = clkfreq * 1/direct
ClockCounts = 80_000_000 / 663
ClockCounts = 120663
To confirm this, multiply 'ClockCounts' by 12.5nS and you get 1508uS
Example3:
using the same formula now we'll use 661
ClockCounts = clkfreq * 1/direct
ClockCounts = 80_000_000 / 661
ClockCounts = 121028
To confirm this, multiply 'ClockCounts' by 12.5nS and you get 1512uS
Example4:
using the formula...
ClockCounts = (clkfreq/1_000_000)*direct
ClockCounts = (80_000_000 / 1_000_000)*1510
ClockCounts = 120800
To confirm this, multiply 'ClockCounts' by 12.5nS and you get 1510uS
Example5:
using the same formula now we'll use 1511uS
ClockCounts = (clkfreq/1_000_000)*direct
ClockCounts = (80_000_000 / 1_000_000)*1511
ClockCounts = 120880
To confirm this, multiply 'ClockCounts' by 12.5nS and you get 1511uS
Example6:
using the same formula now we'll use 1509uS
ClockCounts = (clkfreq/1_000_000)*direct
ClockCounts = (80_000_000 / 1_000_000)*1509
ClockCounts = 120720
To confirm this, multiply 'ClockCounts' by 12.5nS and you get 1509uS
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Beau Schwabe
IC Layout Engineer
Parallax, Inc.
@ 80Mhz
ClockCounts = clkfreq * 1/direct
ClockCounts = 80_000_000 / 662
ClockCounts = 120845 = 1510uS
@ 40Mhz
ClockCounts = clkfreq * 1/direct
ClockCounts = 40_000_000 / 662
ClockCounts = 60422 * 25ns = 1510uS
Which is what made me suggest taking a note of cnt while the argument of the waitcnt was calculated, I could not see a reason why it would not work as it was.
Graham