Spin Code Help
[b]pub forward
' forward movement
PulsOut(0, 1_600)
PulsOut(23, 1_600) [/b]
pub right_turn
PulsOut(0, 1_300)
PulsOut(23, 1_620)
pub left_turn
PulsOut(0, 1_620)
PulsOut(23, 1_300)
pub stop
PulsOut(23, 1_475)
PulsOut(0, 1_500)
pri Pause(duration)
'This function pauses program execution for approximately [noparse][[/noparse]duration] micro seconds
'so 1_000_000 would be approximately one second. Doesnt account for instruction
'execution time overhead.
if duration < 381
duration := 381 'lower bound limit. anything lower than this, we
'have to wait until the counter comes back around,
'which is MUCH longer than [noparse][[/noparse]duration].
waitcnt(((clkfreq / 1_000_000) * duration) + cnt)
[b]pri PulsOut(pin, duration)
'similar to the BS2 command. This function pulses the [noparse][[/noparse]pin] for [noparse][[/noparse]duration].
'This is extremely useful for controlling servos and speed controllers.
dira[noparse][[/noparse]pin]~~ 'make pin an output
outa[noparse][[/noparse]pin]~~ 'make pin go high
waitcnt(((clkfreq / 1_000_000) * duration) + cnt) 'pause execution
outa[noparse][[/noparse]pin]~ 'make pin go low
[/b]
pri pulsin(pin) : time | cnt1, cnt2
dira[noparse][[/noparse]Pin]~ ' Make I/O Pin Input
waitpne(0, |< Pin, 0) ' Wait For Pin To Go HIGH
cnt1 := cnt ' Store Current Counter Value
waitpeq(0, |< Pin, 0) ' Wait For Pin To Go LOW
cnt2 := cnt
time := (||(cnt1 - cnt2) / (clkfreq / 1_000_000))
im using this for movement using the msr1 and the 2 hb 25's connected to two motors, although as another user mentioned to me my pulsout method gets stuck in a counter rollover.
I have used these variations of the pulsout method,
pub pulsout(pin, duration) duration := (duration * (clkfreq / 1_000_000)) #> 381 dira[noparse][[/noparse]pin]~~ !outa[noparse][[/noparse]pin] waitcnt(duration) !outa[noparse][[/noparse]pin]
pub pulsout(pin, us)
if (pin => 0) and (pin =< 31) and (us > 0)
us := (clkfreq / 1_000_000 * us) #> 381
outa[noparse][[/noparse]pin]~~
!dira[noparse][[/noparse]pin]
waitcnt(us + cnt)
!dira[noparse][[/noparse]pin]
with little success. The 2nd pulsout however, executes all the code I have set up it just doesnt actually move the wheels. The other versions tend to get stuck the first time I call forward and never continue.
Post Edited (p00ndawg) : 6/21/2010 5:21:27 PM GMT

Comments
In the first, you've got WAITCNT(duration). That can't work because WAITCNT doesn't use a duration, it uses an absolute time (system clock value). You'd have to use WAITCNT(cnt + duration).
In the second, you're toggling the I/O pin between high (1) and input. That would work if the I/O pin had a pulldown resistor, but I don't think that's the way things are set up.
pub pulsout(pin, us) if (pin => 0) and (pin =< 31) and (us > 0) us := (clkfreq / 1_000_000 * us) #> 381 dira[noparse][[/noparse]pin]~~ 'make pin an output outa[noparse][[/noparse]pin]~~ 'make pin go high waitcnt(us + cnt) 'pause execution outa[noparse][[/noparse]pin]~same result as others.
Post Edited (p00ndawg) : 6/21/2010 5:09:54 PM GMT
tried this as well, was sure it would work and it didnt. Still getting a massive stall in execution when waiting for the system counter.
best regards
Stefan
I just pulled this quote from the propellor manual. is the manual wrong?
PUB start servo.start cognew(sensor_scan, @stack) cognew(movement_class,@stack1) pub movement_class ' will scan and turn away else it will move forward with pulsout 1600 forward repeat if inch1 < distance inches := inch1 right_turn pause(758_333) else PulsOut(0, 1_600) PulsOut(23, 1_600) if inch2 < distance inches := inch2 right_turn pause(379_166) else PulsOut(0, 1_600) PulsOut(23, 1_600) if inch3 < distance inches := inch3 left_turn pause(2_275_000) else PulsOut(0, 1_600) PulsOut(23, 1_600) if inch4 < distance inches := inch4 left_turn pause(379_166) else PulsOut(0, 1_600) PulsOut(23, 1_600) if inch5 < distance inches := inch5 left_turn pause(758_333) else PulsOut(0, 1_600) PulsOut(23, 1_600) if inch6 < distance_back inches := inch6 left_turn pause(1_516_666) else PulsOut(0, 1_600) PulsOut(23, 1_600) if inch7 < distance_back inches := inch7 left_turn pause(1_895_833) else PulsOut(0, 1_600) PulsOut(23, 1_600) if inch8 < distance_back inches := inch8 left_turn pause(2_275_000) else PulsOut(0, 1_600) PulsOut(23, 1_600) if inch9 < distance_back inches := inch9 right_turn pause(1_516_666) else PulsOut(0, 1_600) PulsOut(23, 1_600) if inch10 < distance_back inches := inch10 right_turn pause(1_895_833) else PulsOut(0, 1_600) PulsOut(23, 1_600) pub forward 'pin 0 = left wheel pin 23 = right wheel pause(10_000) PulsOut(0, 1_600) pause(10_000) PulsOut(23, 1_600) pub right_turn pause(10_000) PulsOut(0, 1_300) pause(10_000) PulsOut(23, 1_620) pub left_turn pause(10_000) PulsOut(0, 1_620) pause(10_000) PulsOut(23, 1_300) pub stop pause(10_000) PulsOut(23, 1_475) pause(10_000) PulsOut(0, 1_500) PUB sensor_scan 'scanning of ping sensors repeat inch1 := ping.Inches(pin1) 'change time to distance in inches inch2 := ping.Inches(pin2) inch3 := ping.Inches(pin3) 'change time to distance in inches inch4 := ping.Inches(pin4) inch5 := ping.Inches(pin5) 'change time to distance in inches inch6 := ping.Inches(pin6) inch7 := ping.Inches(pin7) 'change time to distance in inches inch8 := ping.Inches(pin8) inch9 := ping.Inches(pin9) 'change time to distance in inches inch10 := ping.Inches(pin10) pri Pause(duration) 'This function pauses program execution for approximately [noparse][[/noparse]duration] micro seconds 'so 1_000_000 would be approximately one second. Doesnt account for instruction 'execution time overhead. if duration < 381 duration := 381 'lower bound limit. anything lower than this, we 'have to wait until the counter comes back around, 'which is MUCH longer than [noparse][[/noparse]duration]. waitcnt(((clkfreq / 1_000_000) * duration) + cnt) pri PulsOut(pin, duration) 'similar to the BS2 command. This function pulses the [noparse][[/noparse]pin] for [noparse][[/noparse]duration]. 'This is extremely useful for controlling servos and speed controllers. 'To constantly make a servo move, you have to constantly be calling this 'function (I.E. you cant set a value and have the servo stay at that value) pri pulsout(pin, us) if (pin => 0) and (pin =< 31) and (us > 0) us := (clkfreq / 1_000_000 * us) #> 381 dira[noparse][[/noparse]pin]~~ 'make pin an output outa[noparse][[/noparse]pin]~~ 'make pin go high waitcnt(us + cnt) 'pause execution outa[noparse][[/noparse]pin]~ok now im getting a little annoyed.
Here is my full code. Another one of my group members here came and loaded up his code which provided similar functionality to mine, using the pulsout and pause methods provided, and he got no code stalling.
is there something that anyone can quickly see that I am not?
Post Edited (p00ndawg) : 6/21/2010 10:25:29 PM GMT
CON _clkmode = xtal1 + pll16x ' Crystal feedback & PLL multiplier _xinfreq = 5_000_000 CON pin1 = 1 ' All the ping pins pin2 = 2 pin3 = 3 ' All the ping pins pin4 = 4 pin5 = 5 ' All the ping pins pin6 = 6 pin7 = 7 ' All the ping pins pin8 = 8 pin9 = 9 ' All the ping pins pin10 = 10 distance = 18 VAR ' Global Variables: long inch1 long inch2 long inch3 long inch4 long inch5 long inch6 long inch7 long inch8 long inch9 long inch10 long stack[noparse][[/noparse]20] long stack1[noparse][[/noparse]20] long inches OBJ ping: "Ping" servo : "servo32v5" PUB start servo.start cognew(sensor_scan, @stack) cognew(movement_class,@stack1) pub movement_class ' will scan and turn away else it will move forward with pulsout 1600 forward repeat if inch1 < distance inches := inch1 right_turn pause(758_333) else PulsOut(0, 1_600) PulsOut(23, 1_600) if inch2 < distance inches := inch2 right_turn pause(379_166) else PulsOut(0, 1_600) PulsOut(23, 1_600) if inch3 < distance inches := inch3 left_turn pause(2_275_000) else PulsOut(0, 1_600) PulsOut(23, 1_600) if inch4 < distance inches := inch4 left_turn pause(379_166) else PulsOut(0, 1_600) PulsOut(23, 1_600) if inch5 < distance inches := inch5 left_turn pause(758_333) else PulsOut(0, 1_600) PulsOut(23, 1_600) if inch6 < distance_back inches := inch6 left_turn pause(1_516_666) else PulsOut(0, 1_600) PulsOut(23, 1_600) if inch7 < distance_back inches := inch7 left_turn pause(1_895_833) else PulsOut(0, 1_600) PulsOut(23, 1_600) if inch8 < distance_back inches := inch8 left_turn pause(2_275_000) else PulsOut(0, 1_600) PulsOut(23, 1_600) if inch9 < distance_back inches := inch9 right_turn pause(1_516_666) else PulsOut(0, 1_600) PulsOut(23, 1_600) if inch10 < distance_back inches := inch10 right_turn pause(1_895_833) else PulsOut(0, 1_600) PulsOut(23, 1_600) pub forward 'pin 0 = left wheel pin 23 = right wheel pause(10_000) PulsOut(0, 1_600) pause(10_000) PulsOut(23, 1_600) pub right_turn pause(10_000) PulsOut(0, 1_300) pause(10_000) PulsOut(23, 1_620) pub left_turn pause(10_000) PulsOut(0, 1_620) pause(10_000) PulsOut(23, 1_300) pub stop pause(10_000) PulsOut(23, 1_475) pause(10_000) PulsOut(0, 1_500) PUB sensor_scan 'scanning of ping sensors repeat inch1 := ping.Inches(pin1) 'change time to distance in inches inch2 := ping.Inches(pin2) inch3 := ping.Inches(pin3) 'change time to distance in inches inch4 := ping.Inches(pin4) inch5 := ping.Inches(pin5) 'change time to distance in inches inch6 := ping.Inches(pin6) inch7 := ping.Inches(pin7) 'change time to distance in inches inch8 := ping.Inches(pin8) inch9 := ping.Inches(pin9) 'change time to distance in inches inch10 := ping.Inches(pin10) pri Pause(duration) 'This function pauses program execution for approximately [noparse][[/noparse]duration] micro seconds 'so 1_000_000 would be approximately one second. Doesnt account for instruction 'execution time overhead. if duration < 381 duration := 381 'lower bound limit. anything lower than this, we 'have to wait until the counter comes back around, 'which is MUCH longer than [noparse][[/noparse]duration]. waitcnt(((clkfreq / 1_000_000) * duration) + cnt) pri PulsOut(pin, duration) 'similar to the BS2 command. This function pulses the [noparse][[/noparse]pin] for [noparse][[/noparse]duration]. 'This is extremely useful for controlling servos and speed controllers. 'To constantly make a servo move, you have to constantly be calling this 'function (I.E. you cant set a value and have the servo stay at that value) pri pulsout(pin, us) if (pin => 0) and (pin =< 31) and (us > 0) us := (clkfreq / 1_000_000 * us) #> 381 dira[noparse][[/noparse]pin]~~ 'make pin an output outa[noparse][[/noparse]pin]~~ 'make pin go high waitcnt(us + cnt) 'pause execution outa[noparse][[/noparse]pin]~this is all of it sorry
Sometimes those other objects are changed by mistake, and render your program unusable. It would help to diagnose the problem.
Also, when posting code on the forum page, the forum software will sometimes corrupt the code when using the· "code tags".
Jim
Post Edited (hover1) : 6/22/2010 12:54:16 AM GMT
Thanks for the tip.
There is a hold-off time of 5 ms where the HB-25 will ignore incoming pulses. As a result, the unit should
not be refreshed more frequently than about 5.25 ms + pulse time. Pulse time can be anywhere from
0.8 ms to 2.2 ms. If the HB-25 receives a pulse outside of this range, it will temporarily shut off the
motor until it receives a valid pulse.
We still don't have all of you code. distance_back is not defined. If all the ping distances are greater than distance/distance_back you will send pulses too fast to the HB-25s. Instead of the PulsOuts in the else sections, call Forward I would change Forward to
pub forward
'pin 0 = left wheel pin 23 = right wheel
PulsOut(0, 1_600)
PulsOut(23, 1_600)
pause(10_000)
John Abshier
Make the minimum pulse width or minimum pause = 400. Servos won't respond to anything less than 500us anyway.
In what you've posted you have two declarations for pulsout since Spin ignores case. I don't know why the compiler didn't flag it.
Jim
Darn Mike, I was going to mention the stack, but I got distracted.
Post Edited (hover1) : 6/22/2010 1:13:26 AM GMT
I also replaced all the pulses with proper functions for right, left, and forward.
pub movement_class repeat if inch1 < distance inches := inch1 pause(10_000) right_turn 'right pause(758_333) else forward if inch2 < distance inches := inch2 pause(10_000) right_turn pause(379_166) else forward if inch3 < distance inches := inch3 pause(10_000) left_turn 'left pause(2_275_000) else forward if inch4 < distance inches := inch4 pause(10_000) left_turn 'left pause(379_166) else forward if inch5 < distance inches := inch5 pause(10_000) left_turn 'left pause(758_333) else forward if inch6 < distance_back inches := inch6 pause(10_000) left_turn 'left pause(1_516_666) else forward if inch7 < distance_back inches := inch7 pause(10_000) left_turn 'left pause(1_895_833) else forward if inch8 < distance_back inches := inch8 pause(10_000) left_turn 'left pause(2_275_000) else forward if inch9 < distance_back inches := inch9 pause(10_000) right_turn 'right pause(1_516_666) else forward if inch10 < distance_back inches := inch10 pause(10_000) right_turn 'right pause(1_895_833) else forward PUB sensor_scan repeat inch1 := ping.Inches(pin1) 'change time to distance in inches inch2 := ping.Inches(pin2) inch3 := ping.Inches(pin3) 'change time to distance in inches inch4 := ping.Inches(pin4) inch5 := ping.Inches(pin5) 'change time to distance in inches inch6 := ping.Inches(pin6) inch7 := ping.Inches(pin7) 'change time to distance in inches inch8 := ping.Inches(pin8) inch9 := ping.Inches(pin9) 'change time to distance in inches inch10 := ping.Inches(pin10) pub forward 'pin 0 = left wheel pin 23 = right wheel pause(10_000) PulsOut(0, 1_600) PulsOut(23, 1_600) pause(10_000) pub right_turn pause(10_000) PulsOut(0, 1_300) PulsOut(23, 1_620) pause(10_000) pub left_turn pause(10_000) PulsOut(0, 1_620) PulsOut(23, 1_300) pause(10_000) pub stop pause(10_000) PulsOut(23, 1_475) PulsOut(0, 1_500) pause(10_000)repeat
I couldn't find in in the manual but I found in a PE Lab that the other cogs continue running.
Making people finde part of the code in the zip file and another part of the code in the post is not conductive to getting help.
However, the logic of you program probably doesn't work as you thing. Assume that inch1 is > distance and inch2 is < distance. I think you want to turn right. But what you will do is go forward then turn right. I think what you want is (summarized pseudo code)
if inches1 < distance
right_turn
elseif inches2 < distance
right_turn
...
elseif inches10 < distance_back
right_turn
else
forward
John Abshier
Post Edited (John Abshier) : 6/22/2010 7:55:34 PM GMT
Ive reset it a few times and it seems to always get stuck in forward motion and all the ping sensors turn off.
Post Edited (p00ndawg) : 6/22/2010 8:27:46 PM GMT
John Abshier
It would seem to me however that the sensor_scan cog is stopping, because they all go blank and it just goes forward.
PUB sensor_scan dira[noparse][[/noparse]15]~~ 'toggle led repeat inch1 := ping.Inches(pin1) 'change time to distance in inches inch2 := ping.Inches(pin2) inch3 := ping.Inches(pin3) 'change time to distance in inches inch4 := ping.Inches(pin4) inch5 := ping.Inches(pin5) 'change time to distance in inches inch6 := ping.Inches(pin6) inch7 := ping.Inches(pin7) 'change time to distance in inches inch8 := ping.Inches(pin8) inch9 := ping.Inches(pin9) 'change time to distance in inches inch10 := ping.Inches(pin10) !outa[noparse][[/noparse]15]'toggle led waitcnt(3_000_000 + cnt) 'toggle ledIm not sure if this is helpful because I dont have any 3 prong led's for the msr1 so I used the led's on the tsl230 color sensor lol, but it got stuck in forward motion and the led's turned off.
Next I ran this for the movement class:
pub movement_class dira[noparse][[/noparse]15]~~ 'toggle led repeat !outa[noparse][[/noparse]15] 'toggle led waitcnt(3_000_000 + cnt) 'toggle led if inch1 < distance right_turn 'right pause(758_333) elseif inch2 < distance right_turn pause(379_166) elseif inch3 < distance left_turn 'left pause(2_275_000) elseif inch4 < distance left_turn 'left pause(379_166) elseif inch5 < distance left_turn 'left pause(758_333) elseif inch6 < distance_back left_turn 'left pause(1_516_666) elseif inch7 < distance_back left_turn 'left pause(1_895_833) elseif inch8 < distance_back left_turn 'left pause(2_275_000) elseif inch9 < distance_back right_turn 'right pause(1_516_666) elseif inch10 < distance_back right_turn 'right pause(1_895_833) else pause(10_000) forward pause(10_000)and when it got stuck the led kept blinking.
Post Edited (p00ndawg) : 6/23/2010 5:26:41 PM GMT
I found the bug!
Thanks for all the help guys. Really appreciated!
John Abshier
you live and you learn I guess.