Файл: Advanced Robotics with the Toddler (Paralax, student guide, v1.3, 2004).pdf
ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 12.06.2025
Просмотров: 1934
Скачиваний: 0
Chapter #7: Staying on the Table · Page 157 |
|
OUTPUT right_pin |
|
FREQOUT 2,500,3000 |
' Beep at startup. |
GOSUB ResetCC |
|
'----- Main Routine -------------- |
|
main: |
' Main routine |
GOSUB check_sensors |
' Distance values for each sensor |
'debug "l",dec l_values,"r", dec r_values,cr
BRANCH l_values,[left0,left1,left2,left3,left4,left5]
left0:
LOOKUP r_values,[l0r0,l0r1,l0r2,l0r3,l0r4,l0r5],Mx GOTO main_movement
left1:
LOOKUP r_values,[l1r0,l1r1,l1r2,l1r3,l1r4,l1r5],Mx GOTO main_movement
left2:
LOOKUP r_values,[l2r0,l2r1,l2r2,l2r3,l2r4,l2r5],Mx GOTO main_movement
left3:
LOOKUP r_values,[l3r0,l3r1,l3r2,l3r3,l3r4,l3r5],Mx GOTO main_movement
left4:
LOOKUP r_values,[l4r0,l4r1,l4r2,l4r3,l4r4,l4r5],Mx GOTO main_movement
left5:
LOOKUP r_values,[l5r0,l5r1,l5r2,l5r3,l5r4,l5r5],Mx
main_movement: |
||
GOSUB Movement |
||
GOTO main |
' Infinite loop. |
|
'----- Subroutine(s) ------------- |
||
check_sensors: |
||
l_values |
= 0 |
' Set distances to 0. |
r_values |
= 0 |
|
' Take 5 |
measurements for distance at each IR pair. If you fine tuned |
|
Page 158 · Advanced Robotics with the Toddler
' frequencies in Activity #2, insert them in the lookup tables.
FOR counter = 0 TO 4 check_left_sensors:
LOOKUP counter,[37500,38250,39500,40500,41000],l_IR_freq FREQOUT left_pin,1,l_IR_freq
l_values.LOWBIT(counter) = ~left_in
check_right_sensors:
LOOKUP counter,[37500,38250,39500,40500,41000],r_IR_freq FREQOUT right_pin,1,r_IR_freq
r_values.LOWBIT(counter) = ~right_in
NEXT |
|
l_values = NCD l_values |
' Value for distance depends on MSB |
r_values = NCD r_values |
|
RETURN |
'----- Movement: Move feet using DATA table referenced by Mx -----
'Input: Mx = movement table index, table ends in xx
'or
'Mx = submovement table index, table ends in xx
'
' Note: All submovment tables come after the movment tables in this file.
Movement:
IF Mx < BasicMovements THEN SetupMovement
MxCurrent = Mx |
' setup to use submovement table |
|
MoveLoopLimit = 1 |
||
GOTO StartMovement |
||
SetupMovement: |
||
READ Mx, MoveLoopLimit |
' read movement table repeat count |
|
MxCurrent = Mx + |
1 |
|
StartMovement: |
||
FOR MoveLoop = 1 |
TO MoveLoopLimit |
|
Mx = MxCurrent |
' Mx = start of movement table |
|
'debug hex Mx, " Movement ", dec MoveLoop, " of ", dec MoveLoopLimit,cr
IF Mx < BasicMovements THEN MovementLoop
' skip if movement table |
||
SxCurrent = Mx |
' |
SxCurrent = submovement index |
GOTO StartSubMovement |
' |
enter middle of loop |
MovementLoop:
Chapter #7: Staying on the Table · Page 159 |
||||
READ Mx, SxCurrent |
' |
read next submovment byte |
||
Mx = Mx + 1 |
||||
IF SxCurrent = xx THEN MovementDone |
||||
' |
skip if end of list |
|||
'debug |
" ", hex SxCurrent, " movement",cr |
|||
LOOKUP SxCurrent,[Finish,Forward,Backward,LeftTurn,RightTurn, |
||||
PivotLeft,PivotRight],SxCurrent |
||||
' |
lookup submovement table index |
|||
StartSubMovement: |
' |
start executing submovement table |
||
READ SxCurrent, SubMoveLoopLmt |
||||
' |
read submovement table repeat count |
|||
SxCurrent = SxCurrent + 1 |
||||
FOR |
SubMoveLoop = 1 TO SubMoveLoopLmt |
|||
Sx = SxCurrent |
||||
'debug |
" |
", hex Sx, " submovement ", |
dec SubMoveLoop, " of " |
|
'debug |
dec SubMoveLoopLmt,cr |
|||
SubMovementLoop: |
||||
READ Sx, Dx |
' |
read next submovent action |
||
Sx = Sx + 1 |
||||
IF Dx = xx THEN SubMovementDone |
||||
' |
skip if end of list |
|||
GOSUB DoMovement |
' |
execute movement |
||
GOTO SubMovementLoop |
||||
SubMovementDone: NEXT
IF Mx < BasicMovements THEN MovementLoop
' exit if submovement table
MovementDone: NEXT
RETURN
DoMovement:
'debug " ", dec Dx, " action",cr
BRANCH Dx,[TiltLeft,TiltCenter,TiltRight,StrideLeft, StrideCenter,StrideRight]
' will fall through if invalid index
RETURN
' ---- Movement routines can be called directly ----
TiltLeft:
NewValue = LeftTilt
GOTO MovementTilt
TiltCenter:
NewValue = CenterTilt
GOTO MovementTilt
Page 160 · Advanced Robotics with the Toddler
TiltRight:
NewValue = RightTilt
MovementTilt:
FOR Pulses = CurrentTilt TO NewValue STEP TiltStep
PULSOUT TiltServo, Pulses
PULSOUT StrideServo, CurrentStride
PAUSE MoveDelay
NEXT
CurrentTilt = NewValue
RETURN
StrideLeft:
NewValue = LeftStride
GOTO MovementStride
StrideCenter:
NewValue = CenterStride
GOTO MovementStride
StrideRight:
NewValue = RightStride
MovementStride:
FOR Pulses = CurrentStride TO NewValue STEP StrideStep
PULSOUT TiltServo, CurrentTilt
PULSOUT StrideServo, Pulses
PAUSE MoveDelay
NEXT
CurrentStride = NewValue
RETURN
' ----- Move feet to initial center position -----
ResetCC:
CurrentTilt = CenterTilt
CurrentStride = CenterStride
FOR Pulses = 1 TO 100 STEP StrideStep
PULSOUT TiltServo, CenterTilt
PULSOUT StrideServo, CenterStride
PAUSE MoveDelay
NEXT
DoReturn:
RETURN
Chapter #7: Staying on the Table · Page 161
How the Shadow Walker Program Works
The first thing the main routine does is call the check_sensors subroutine. After the check_sensors subroutine is finished, l_values and r_values each contain a number corresponding to the zone in which an object was detected for both the left and right IR pairs.
main:
GOSUB check_sensors
The next line of code jumps to one of many LOOKUP statements. The BRANCH statement uses the status of the left IR sensor while the LOOKUP statements use the status of the right IR sensor. These set the Mx variable with the table index for the movement to be performed by the Movement routine.
Branch l_values,[left0,left1,left2,left3,left4,left5]
left0:
LOOKUP r_values,[l0r0,l0r1,l0r2,l0r3,l0r4,l0r5],Mx GOTO main_movement
left1:
LOOKUP r_values,[l1r0,l1r1,l1r2,l1r3,l1r4,l1r5],Mx GOTO main_movement
left2:
LOOKUP r_values,[l2r0,l2r1,l2r2,l2r3,l2r4,l2r5],Mx GOTO main_movement
left3:
LOOKUP r_values,[l3r0,l3r1,l3r2,l3r3,l3r4,l3r5],Mx GOTO main_movement
left4:
LOOKUP r_values,[l4r0,l4r1,l4r2,l4r3,l4r4,l4r5],Mx GOTO main_movement
left5:
LOOKUP r_values,[l5r0,l5r1,l5r2,l5r3,l5r4,l5r5],Mx
main_movement: GOSUB Movement
The values used in the LOOKUP statement are defined near the start of the program using CON constant definitions. While it is possible to put these values in the LOOKUP statement,
Page 162 · Advanced Robotics with the Toddler
this makes the statements long. It also makes it difficult to see what action is performed in a particular state. The constant definitions provide a way to do this. It is now easy to correlate a particular state such as l3r3 with a particular movement, in this case a nop or no movement. Likewise, l5r5 indicates that the Toddler is immediately in front of an obstacle and l0r0 indicates the Toddler has not located an obstacle within its range.
Program control is returned to the main: label after the movement has been performed, and the loop repeats itself.
Chapter #7: Staying on the Table · Page 163
CHALLENGES
Figure 7-5: One Toddler Follows Another Toddler
Figure 7.5 shows a lead Toddler followed by a shadow Toddler. The lead Toddler could run any of the prior programs provided the speed is slower (increase the PAUSE values or decrease the STEP values) and the shadow Toddler is running Program Listing 7.3: Shadow Walker. Proportional control makes the shadow Toddler a very faithful follower. One lead Toddler can string along a chain of 2 or 3 Toddlers. Just add a 4” x 4” paper to the lead Toddler’s backside.
√If you are part of a class, mount paper panel on the back of the lead Toddler as shown in Figure 7.5.
√If you are not part of a class (and only have one Toddler) the shadow Toddler will follow a piece of paper or your hand just as well as it follows a lead Toddler.
Page 164 · Advanced Robotics with the Toddler
√The Shadow Toddler should be running Program Listing 7.3 without any modifications.
√With both Toddlers running their respective programs, place the shadow Toddler behind the lead Toddler. The shadow Toddler follows at a fixed distance, so long as it is not distracted by another object such as a hand or a nearby wall.
Chapter #8: Real-Time Programming with Bumpers and Infrared · Page 165
Chapter #8: Real-Time Programming with Bumpers and Infrared
Note to reader: This chapter requires the Toddler Toes Kit (#27312) from Parallax.
WHAT IS MEANT BY REAL TIME?
Real time programming is one of those terms that can mean different things at the same time. In plain language, it is code that allows the computer system to keep up with what is happening in the world around it – WHILE it is happening. Like in everything else, there are degrees of “real time”. Programming a system to respond to events happening quickly is more difficult than if they happen more slowly. Programming events to happen at a very precise time can also be challenging – even if they don’t happen at high speed.
Let’s look at a simple example.
You want to flash 5 LEDs. You can determine if they need to be on or off by testing switch inputs. It’s an easy task.
1.Turn off all the LEDs to start
2.Test each switch input and turn on the LED if the switch requires it.
3.Pause for ½ second – or however long you want the LEDs on.
4.Turn off all the LEDs
5.Pause for ½ second – or however long you want the LEDs off.
6.Go to to #2 and start over.
You probably ignored how long it takes to test the inputs in step #2 before running the PAUSE in step #3. What if the program were required to flash the LEDs at precisely a 1 second rate (+- 0.001%)? Ignoring the calculation times can lead to disaster in that case. Not only would you have to measure or calculate the instruction times to correct the duration of the PAUSE but also you’d have to make sure that all possible cases of switch inputs take the same amount of time to compute.
Now, what if the switches only make contact for 20 milliseconds? Your code would have to constantly be scanning to see if the switch was making contact and remember it. The scanning has to happen while still keeping track of the flashing LEDs. If you had a loop to check the switches, you’d have to complete that loop more than once every 20