Re-work of Parallax Penguin move code.
Ok, here is a re-work on the Paralax Move: routine in the example software. It saves 102 bytes of· EEPROM space, and eliminates 4 , word length variables. This is about one third the size. ·No there is no down side to this, walking is still just as hilarious as it always was. Basically instead of trying to integrate the remainder of signed division slowly into the move., It just adds one smaller pulse at the end of the step or tilt, making for a possible improvement of a softer landing, depending stride distance etc.
This is a drop-in to the sample code. If you use the move routine as-is in your own programs it will copy-paste in with no problems.
·
Variables eliminated:
StrideModulo· ··VAR···· Word_0··············· ' Move
TiltModulo···· ··VAR···· Word_1··············· ' Move
StrideModAcc·· VAR···· Word_4··············· ' Move
TiltModAcc··· ···VAR···· Word_5··············· ' Move
·
Move subroutine, Also attached· ( AutonomousNavigation_2.bpx ) file using it:
'
[noparse][[/noparse] Subroutine - Move both servos to new positions (NewStrideValue and NewTiltValue).· ]--
'
[noparse][[/noparse] If you don't want one of the servos to move make it's new value = it's old value before entering this routine. ] --
'
[noparse][[/noparse] This routine divides the distance to move the servos into a number of smaller steps (pulses) to control the speed. ]--
'
[noparse][[/noparse] This version of Move: takes the remainder of distance/speed and uses it as a smaller last step. ]--
Move:
····· ' Perform signed division, note that integer division won't work with negative numbers
····· ' thus this seemingly cumbersome workaround
· StrideSpeed = ABS(NewStrideValue - OldStrideValue) / Speed
· IF NewStrideValue < OldStrideValue THEN StrideSpeed = -StrideSpeed
····· ' Repeat for tilt servo
· TiltSpeed = ABS(NewTiltValue - OldTiltValue) / Speed
· IF NewTiltValue < OldTiltValue THEN TiltSpeed = -TiltSpeed
· FOR i = 1 TO Speed·····································'· ·'Speed' = number of pulses
··· OldStrideValue = OldStrideValue + StrideSpeed
··· OldTiltValue = OldTiltValue + TiltSpeed
··· PULSOUT StrideServo, OldStrideValue····· ' Send newly calculated
··· PULSOUT TiltServo, OldTiltValue············ ' pulses to both servos
··· PAUSE delay········································' Keep adequate low pulse time
· NEXT
· OldStrideValue = NewStrideValue··············' Send one more pulse with the remainder
· OldTiltValue = NewTiltValue····················'·· needed to get the full stride.
· PULSOUT StrideServo, OldStrideValue····· ' Send newly calculated
· PULSOUT TiltServo, OldTiltValue············· ' pulses to both servos
· PAUSE delay········································' Keep adequate low pulse time
RETURN
This is a drop-in to the sample code. If you use the move routine as-is in your own programs it will copy-paste in with no problems.
·
Variables eliminated:
StrideModulo· ··VAR···· Word_0··············· ' Move
TiltModulo···· ··VAR···· Word_1··············· ' Move
StrideModAcc·· VAR···· Word_4··············· ' Move
TiltModAcc··· ···VAR···· Word_5··············· ' Move
·
Move subroutine, Also attached· ( AutonomousNavigation_2.bpx ) file using it:
'
[noparse][[/noparse] Subroutine - Move both servos to new positions (NewStrideValue and NewTiltValue).· ]--
'
[noparse][[/noparse] If you don't want one of the servos to move make it's new value = it's old value before entering this routine. ] --
'
[noparse][[/noparse] This routine divides the distance to move the servos into a number of smaller steps (pulses) to control the speed. ]--
'
[noparse][[/noparse] This version of Move: takes the remainder of distance/speed and uses it as a smaller last step. ]--
Move:
····· ' Perform signed division, note that integer division won't work with negative numbers
····· ' thus this seemingly cumbersome workaround
· StrideSpeed = ABS(NewStrideValue - OldStrideValue) / Speed
· IF NewStrideValue < OldStrideValue THEN StrideSpeed = -StrideSpeed
····· ' Repeat for tilt servo
· TiltSpeed = ABS(NewTiltValue - OldTiltValue) / Speed
· IF NewTiltValue < OldTiltValue THEN TiltSpeed = -TiltSpeed
· FOR i = 1 TO Speed·····································'· ·'Speed' = number of pulses
··· OldStrideValue = OldStrideValue + StrideSpeed
··· OldTiltValue = OldTiltValue + TiltSpeed
··· PULSOUT StrideServo, OldStrideValue····· ' Send newly calculated
··· PULSOUT TiltServo, OldTiltValue············ ' pulses to both servos
··· PAUSE delay········································' Keep adequate low pulse time
· NEXT
· OldStrideValue = NewStrideValue··············' Send one more pulse with the remainder
· OldTiltValue = NewTiltValue····················'·· needed to get the full stride.
· PULSOUT StrideServo, OldStrideValue····· ' Send newly calculated
· PULSOUT TiltServo, OldTiltValue············· ' pulses to both servos
· PAUSE delay········································' Keep adequate low pulse time
RETURN
Comments
I tested this on the Happy Feet program and it
saves a good amount of EEPROM space, enough
so that several more commands could be added
to the program! This is remarkable, and you did
a very good job on this! Congratulations!
I removed the modulo var group but there was no
savings in Word storage, as these are already
aliases. It was drop in, exactly as you specified
and impressive as it worked right away with
no debugging whatsoever.
One difference I can see, and I'm testing
at some very high speed movements, is that
the new code is somewhat slower. A good test
for this is the Shiver subroutine, as it runs at
speed = 2 within VR Servo range. However,
Penguin-AutonomousNavigation
deals with walking only, with Speed and WalkSpeed
set initialized to 15, hence any significant differences
in speed go unnoticed. Thanks again for creating
this wonderful, useful, and unique new revised
motion engine.
humanoido
This is the Parallax "Jump:" subroutine-
[noparse][[/noparse] Subroutine - Move the servos at full speed ]
Jump:················································· · ' 'Speed' determines how long
· DO···················································· ·' the position is held
··· PULSOUT StrideServo, NewStrideValue····· ' Output the new values to
··· PULSOUT TiltServo, NewTiltValue········· ' both servos
··· PAUSE Delay···································· ' Keep adequate low pulse time
··· Speed = Speed - 1··························· ·' Repeat as long as indicated
· LOOP WHILE Speed·······························' by 'Speed'
· OldStrideValue = NewStrideValue··········· ' Set old values in case the
· OldTiltValue = NewTiltValue··················· ' 'Move' routine is used next
RETURN
You·could simplify it to -
·'
[noparse][[/noparse] Subroutine - Move the servos at full speed ]
··· Jump:·······································································································
······· PULSOUT StrideServo, NewStrideValue····· ' Output the new values to
···· ·· PULSOUT TiltServo, NewTiltValue········· ' both servos
······ ·PAUSE Delay···································· ' Keep adequate low pulse time
······ OldStrideValue = NewStrideValue··········· ' Set old values in case the
····· ·OldTiltValue = NewTiltValue··················· ' 'Move' routine is used next
··· RETURN
·edit- I originally had a futher siplification listed here as a third example, but have removed·it after seeing the light.
I think that the original author of this code wasn't sure how long it would take for the servos to get where
they were going, and left that "speed = speed-1" loop in there for breathing room. If breathing room is needed just
change the "Delay" to a constant that barley allows the servos to get to their destination. The delay is long enough
·for mine, but its a hard thing to see at full speed.
Thanks for the kind words, I haven't programmed since the early 80's so cramming code into a small amount of memory was all we could do back then.
Post Edited (Interact) : 9/1/2007 8:25:51 PM GMT
humanoido
I edited it out of the post .
Post Edited (Interact) : 9/1/2007 8:24:00 PM GMT