PDA

View Full Version : PropBasic Counters & Servos



skynugget
10-25-2011, 03:24 AM
Hello All!

i am trying to emulate JonnyMacs neat way of driving multiple servos with the system counter (jm_servo8_adv.spin) in PropBasic. Here is what i came up with so far, and it "kind of" works, but there is no real tourqe on the servo turn, and it chatters like a mofo when it gets to the target location.

i suspect my math for the timing is off, does anything see anything wrong with this?

thanks in advance!

kuroneko
10-25-2011, 04:06 AM
Which version of the compiler are you using? With 1.14 stuff like 2500 * us001 gets mistranslated. BTW, us001 should be 80 not 5 for your setup. The code generated is (us001 == 80):

mov tmp,_2500 ' tmp = 2500 * us001
shl tmp,#4

This basically messes up your timing.

skynugget
10-25-2011, 04:19 AM
thanks for the heads up kuroneko, ill try that when i get back to the the compiler. im using v1.25

kuroneko
10-25-2011, 04:25 AM
Do you have a link for 1.25?

skynugget
10-25-2011, 04:38 AM
http://forums.parallax.com/attachment.php?attachmentid=85885&d=1318421129

from this post:
http://forums.parallax.com/showthread.php?135098-PropBasic-Bug

kuroneko
10-25-2011, 04:57 AM
Thanks, but that doesn't generate any output for me (1.14 generates 2 SPIN files). I tried two different machines (XP and Vista, JPN) and both come up empty. Anyway, if you can find a way to inspect the generated code have a look at the 2500 * us001 line.

skynugget
10-25-2011, 05:18 AM
odd, are you using bst? i don't think this version will work as it doesn't have the hooks, its straight from Bean. ive been using viewport and cedit to compile with this version.

kuroneko
10-25-2011, 05:23 AM
odd, are you using bst?
Initially I used it from the command line (which works for the 1.14 release). Then I tried bst and it died (as expected). Maybe it's tied to viewport in a way and requires a specific environment. Beats me.

So in order to check if the same bug is still present you could multiply by 80 manually (*5*16):

tmp = pos << 2 ' *4
tmp = tmp + pos ' *5
tmp = tmp << 4 ' *80

And the other location could just load 200000 (2500*80) directly.

skynugget
10-25-2011, 05:39 AM
ha i just realized i based all my math on 5mhz instead of 80, i guess i just had the crystal value stuck in my head! still playing around so far.
here is what is generated:



mov tmp,_2500 ' tmp = 2500 * us001
mov __temp1,tmp
shl tmp,#4

kuroneko
10-25-2011, 06:24 AM
Just remembered something re: multiply with constants (outstanding bug). When you move us001 into a variable first then it should generate proper multiply code, e.g.

tmp = us001
tmp = pos * tmp

skynugget
10-25-2011, 08:28 PM
got the task timing all the servos now! il post up the rest once i have time to get the subs done, thanks!



' ----- TASK Variables (LONG only) ------------------------------------
us001 con 80 '5 '80_000_000 / 1_000_000 tick per microsecond
so con 18 'servo offset start at pin 18

idx var long
outpin var long

slot var long
pos var long
tgt var long
dlt var long
tmp VAR long

' ----- SUB and FUNC Definitions ---------------------------------------
'(2^32)/clkfreq = 4294967296/80_000_000 = 53.6870912
'clkfreq=80_000_000 53.6870912 * 65536 = 3518437.2088832

SrvStart:
OUTPUT servos
frqa = 1 'preset for counter
phsa = 0
slot = cnt

SrvMain:
for idx = 0 to 7
rdlong position(idx), pos 'get chanel position value
rdlong target(idx), tgt 'get channel target value
rdlong delta(idx), dlt 'get speed value

outpin = idx + so 'set servo pin via offset
COUNTERA 32,outpin 'start counter
tmp = pos * us001
phsa = -tmp

if pos < tgt then 'is pos less the taget pos?
pos = pos + dlt
pos = pos max tgt
elseif pos > tgt then
pos = pos - dlt
pos = pos min tgt
endif

tmp = 2500 * us001 'slot timing
slot = slot + tmp
WAITCNT slot 'wait for slot to finish

ctra = 0
wrlong position(idx), pos 'put channel poition value
next
goto srvmain 'loop

ENDTASK

skynugget
11-12-2011, 06:29 PM
here is what i ended up with. it seems to work rather well except for one bug i can't seem to figure out.

if you the first set_servo you use has a speed other then 0, the servo will swing all the way to the srvmin pos at full speed, then will turn to the requested position at the requested speed. i got around it by just initiating all the servos with no speed control when i start the program.

special thanks to bean, jonnymac, and parallax.

if ya make it better please share!