Shop OBEX P1 Docs P2 Docs Learn Events
Re-work of Parallax Penguin move code. — Parallax Forums

Re-work of Parallax Penguin move code.

InteractInteract Posts: 79
edited 2007-09-01 20:17 in Robotics
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

Comments

  • HumanoidoHumanoido Posts: 5,770
    edited 2007-08-31 02:29
    This is a remarkable rework, Interact. Great job!

    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
  • InteractInteract Posts: 79
    edited 2007-08-31 16:50
    Yes it adds one additional "speed" step for the division remainder. Under normal walk speeds, speed equals 15, so 16 is no big deal. Just put in speed = 14 and you have the same thing. So speed works the same all the way down to speed = 1. Only problem is, at speed = 1 you can't use a speed 0. in this case there is the routine in all the parallax example code named "Jump:" to move the servos at full speed if you really need speed. For most of us I think speeds under 8 are asking for a tip-over, but hey, those are the risks you take when learning to dance. The "Jump:" routine can be improved as well, saving yet a few more bytes as seen in the example below.



    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
  • HumanoidoHumanoido Posts: 5,770
    edited 2007-09-01 02:50
    Yes, the original author did an amazing job with this program. You're right about the speed. Can't go less than a speed of 1, so the code will be well suited for applications other than VR Servos. If you put the motion in a loop at high speed, like vibrate, a small difference in speed value (1) is noticeable. To keep Penguin from falling over, use small motion ranges. The mod on the Jump subroutine is very interesting. In my programs, I can drop in the first revised code with no problem, and the EEPROM memory savings is a real bonus! In the early 70's, programming was entirely with 256 bytes of memory RAM on most hobby microcomputers. It was enough to program Beethoven, Bach and Mozart. That was a lot of memory back then.

    humanoido
  • InteractInteract Posts: 79
    edited 2007-09-01 20:17
    ·Yes you are right the second simplification of "Jump:" is no-good.
    I edited it out of the post .



    Post Edited (Interact) : 9/1/2007 8:24:00 PM GMT
Sign In or Register to comment.