A simple SPIN servo driver
Copper
Posts: 48
So, I started fooling around with the propeller just a couple months ago. It's not only my first micro-controller, but also my first real programming experience---excluding the lego mindstorms stuff. It's been challenging, but incredibly enlightening and mostly quite enjoyable.
Currently I'm working on a simple SPIN servo driver (loosely based on the 32servo driver by Beau Schwabe). Unfortunately I've hit a small road block.
After adding my 'Ramp Servo block of code, the 'begin sending signal repeat loop stopped repeating.
I tried replacing my "if statements" with an "if-else statement", and a "case statement". Then I tried writing all three approaches into their own methods but got the same results. All attempts seem to fail after executing the "condition check"
My serial terminal output looks like:
if statement test above
case statement test below
I'm not sure why my "case statement" doesn't at least report Ramp UP or Ramp Down.
Or why the "if statement" wouldn't work.
If my repeat loop was just too busy, and thus sending signals at the wrong times, I would still expect to see multiple loops in the serial terminal output.
PS: Before adding the ramping code, and all the serial terminal stuff, it worked exactly as expected.
Also, of course I could use Beau Schwabe's driver, but more than I need a functional servo driver, I'm looking to learn more about servos and programming
Thanks for your time
Currently I'm working on a simple SPIN servo driver (loosely based on the 32servo driver by Beau Schwabe). Unfortunately I've hit a small road block.
After adding my 'Ramp Servo block of code, the 'begin sending signal repeat loop stopped repeating.
{{Basic Servo Stuff}}CON _clkmode = xtal1 + pll16x _xinfreq = 5_000_000 Pulse_Inc = 620 #0, For4, For3, For2, For1, stop, Rev1, Rev2, Rev3, Rev4 OBJ pst : "Parallax Serial Terminal" PUB Main Run_Servo(12, For3, 1000) Run_Servo(12, For1, 1000) Run_Servo(12, Rev4, 1000) Run_Servo(12, For3, 1000) PUB Run_Servo(servoPin, speed, duration) | Pulse_Res, Pulse_Delay, Pulse_Width, time, Duration_Res, run_time, i pst.Start(57600) waitcnt(clkfreq+cnt) 'configure counterA ctra := (100 << 26 | servoPin) 'Counter A to NCO & Apin to servoPin frqa := 1 'increment phsa by 1 dira[servoPin]~~ 'set servoPin to output 'configure pwm signal Pulse_Res := clkfreq/1_000_000 'set Pulse_Res == 1 microsecond Pulse_Res == PulseWidth Resolution Pulse_Delay := Pulse_Res * 20_000 'determine pulse delay Pulse_Width := Pulse_Res * Speeds[speed] 'determine pulse width time := cnt 'mark counter time 'report PWM config values pst.str(string(13, "****Config' PWM****")) pst.str(string(13, "Pulse_Res==", 13)) pst.bin(Pulse_Res, 32) pst.str(string(13, "Pulse_Delay==", 13)) pst.bin(Pulse_Delay, 32) pst.str(string(13, "Pulse_Width==", 13)) pst.bin(Pulse_Width, 32) 'detirmine runtime Duration_Res := clkfreq/1000 'set Duration_Res == 1millisecond Duration_Res == Duration Resolution run_time:=((duration*Duration_Res)+time) 'set run_time 'report runtime calculation values pst.str(string(13, 13, 13, "****Determine Runtime****")) pst.str(string(13, "Duration_Res==", 13)) pst.bin(Duration_Res, 32) pst.str(string(13, "run_time==", 13)) pst.bin(run_time, 32) pst.str(string(13)) i:=0 'begin sending signal repeat until time==run_time 'start PWM signal i++ pst.str(string(13, 13, "****Pulse#")) pst.dec(i) pst.str(string("****")) 'Ramp servo if Pulse_Width > PULSE[servoPin] PULSE[servoPin]+=Pulse_Inc pst.str(string(13, "Ramp UP")) if Pulse_Width < PULSE[servoPin] PULSE[servoPin]-=Pulse_Inc pst.str(string(13, "Ramp Down")) pst.str(string(13, "PULSE==")) pst.bin(PULSE, 32) phsa := -PULSE[servoPin] 'send pulse for Pulse_Width seconds time += Pulse_Delay 'calculate end of cycle waitcnt(time) 'wait for next cycle DAT 'For4, For3, For2, For1, stop, Rev1, Rev2, Rev3, Rev4 Speeds long 1000, 1200, 1450, 1500, 1515, 1530, 1580, 1830, 2000 PULSE long 0[32]
I tried replacing my "if statements" with an "if-else statement", and a "case statement". Then I tried writing all three approaches into their own methods but got the same results. All attempts seem to fail after executing the "condition check"
My serial terminal output looks like:
if statement test above
case statement test below
I'm not sure why my "case statement" doesn't at least report Ramp UP or Ramp Down.
Or why the "if statement" wouldn't work.
If my repeat loop was just too busy, and thus sending signals at the wrong times, I would still expect to see multiple loops in the serial terminal output.
PS: Before adding the ramping code, and all the serial terminal stuff, it worked exactly as expected.
Also, of course I could use Beau Schwabe's driver, but more than I need a functional servo driver, I'm looking to learn more about servos and programming
Thanks for your time
Comments
-- http://obex.parallax.com/objects/445/
It will control up to 8 servos (by using the second counter you could go to 16) and it does these things:
* one servo pulse at a time
* leading-edge to leading-edge on all channels is 20ms
* ramping is understandable: it is in microseconds (servo movement) per second of real time
* 100% Spin -- no assembly required
You may find some useful code in the object. For features I was trying to mimic the SSC-32 which is a very popular servo controller.
On what you're doing: Even though the serial driver is in its own cog, putting debug statements in your object method is consuming time that may be affecting performance. You have a lot of local variables so you may want to write the address of the first to a global pointer that can be used by another cog for transmitting the values. This is a little advanced, but well worth learning how to do.
Update: I started a thread on how to spy on your Spin cogs without affecting their performance through the insertion of serial statements:
-- http://forums.parallax.com/showthread.php?142041-For-Newcomers-Spying-on-Your-Own-Code-(without-special-tools)
PS: The driver stops after the first loop with and without the serial terminal commands. To me, It really appears to be something with my 'ramp servo's condition check (the If/case statement if "condition check" is a made up term).
Also, the last pst.bin should probably output PULSE[servoPin] rather than just PULSE[0].