Radio Controlled Boe-Bot Application
Figure 3 - Tilt Controlled RF Boe-Bot (S-curves not shown)
To keep the message rate in the 40 ms range, all the pauses and DEBUG commands in TestTiltTransmitter.bs2 have been removed, and the modified program was saved as RfTiltTransmitter.bs2. This program sends x and y coordinates every 40.6 ms, which will keep the Boe-Bot's servos going at a reasonable rate. RfTiltControlledBoeBot.bs2 receives and stores the x and y-axis values sent by the transmitter. Then, it uses these values to decide what pulses to send to the servos.
Example Program – RfTiltTransmitter.bs2
- Connect the RF tilt controller to your programming cable.
- Enter, save, and run RfTiltTransmitter.bs2
- Disconnect the programming cable from the tilt controller.
' RfTiltTransmitter.bs2 ' Transmit tilt data every 41 ms. '{$STAMP BS2} '{$PBASIC 2.5} x VAR Word ' Left/right tilt y VAR Word ' Forward/backward tilt HIGH 11 ' T/R Line High - Transmit DEBUG "Program running..." ' Test piezospeaker FREQOUT 4, 2000, 3000 DO ' Begin main routine PULSIN 6, 1, x ' Get X-axis tilt PULSIN 7, 1, y ' Get Y-axis tilt ' Send tilt at 2400 bps, non-inverted. PULSOUT 10, 1200 ' Sync pulse for the receiver SEROUT 10, 16780, [ "!", ' Start character x.HIGHBYTE, x.LOWBYTE, ' X-axis word y.HIGHBYTE, y.LOWBYTE] ' Y-axis word ' DO NOT Display x AND y tilt measurements; DO NOT pause. LOOP ' Repeat main routine
Example Program – RfTiltControlledBoeBot.bs2
- Connect your radio controlled Boe-Bot to the programming cable.
- Enter, save, and run RfTiltControlledBoeBot.bs2.
- Disconnect the radio controlled Boe-Bot from the programming cable.
- Take your Boe-Bot for a test drive using your RF tilt controller to guide it.
' -----[ Title ]-------------------------------------------------------------- ' RfTiltControlledBoeBot.bs2 ' Boe-Bot navigates based on signals from an RF tilt controller. The ' tilt controller should be running RfTiltTransmitter.bs2 '{$STAMP BS2} '{$PBASIC 2.5} ' -----[ Constants ]---------------------------------------------------------- Negative CON 1 ' Left/right tilt ' -----[ Variables ]---------------------------------------------------------- x VAR Word ' Left/right tilt y VAR Word ' Uphill/downhill tilt ySign VAR y.BIT15 ' Sign bit for y pulseLeft VAR Word ' Current left pulse value pulseLeftOld VAR Word ' Previous left pulse value pulseRight VAR Word ' Current right pulse value pulseRightOld VAR Word ' Previous right pulse value ' -----[ Initialization ]----------------------------------------------------- LOW 11 ' T/R Line low - receive FREQOUT 4, 2000, 3000 ' Beep to signify program start pulseLeft = 750 ' Start with all pulses centered pulseRight = 750 pulseLeftOld = 750 pulseRightOld = 750 ' -----[ Main Routine ]------------------------------------------------------- DO ' Begin main routine. ' This SERIN command gets the x and y-axis values SERIN 10, 16780, [WAIT("!"), x.HIGHBYTE, x.LOWBYTE, y.HIGHBYTE, y.LOWBYTE] ' Scale to -62 to 62 with 0 -> level. x = 62 - ((x MIN 1875 MAX 3125) - 1875 / 10) y = 62 - ((y MIN 1875 MAX 3125) - 1875 / 10) ' Navigation decisions IF (ABS(x) > 12) OR (ABS(y) > 12) THEN ' Is it tilted enough? pulseLeft = 750 - y ' Forward/backward pulses pulseRight = 750 + y IF (ySign = Negative) OR (ABS(y) < 12) THEN ' Turning for forward. pulseLeft = pulseLeft - x pulseRight = pulseRight - x ELSE ' Turning for backward. pulseLeft = pulseLeft + x pulseRight = pulseRight + x ENDIF ELSE ' Stay still pulseLeft = 750 pulseRight = 750 ENDIF ' Increment/decrement routine only adjusts pulse durations by 8 at a time. IF pulseLeft > (pulseLeftOld + 6) THEN pulseleft = pulseLeftOld + 6 IF pulseLeft < (pulseLeftOld - 6) THEN pulseLeft = pulseLeftOld - 6 IF pulseRight > (pulseRightOld + 6) THEN pulseRight = pulseRightOld + 6 IF pulseRight < (pulseRightOld - 6) THEN pulseRight = pulseRightOld - 6 pulseLeft = pulseLeft MIN 650 MAX 850 ' Keep 650 <= durations <= 850 pulseRight = pulseRight MIN 650 MAX 850 pulseLeftOld = pulseLeft ' Remember old values pulseRightOld = pulseRight PULSOUT 13, pulseLeft ' Send control pulses to servos PULSOUT 12, pulseRight LOOP ' Repeat main routine.
How RfTiltControlledBoeBot.bs2 Works
This is a modified version of the program UphillBoeBot.bs2 from Boe-Bot Robot Navigation with Accelerometer Incline Sensing. If you have not already done so, it would be a good idea to try out this activity and familiarize yourself with the coding techniques.
Instead of two PULSIN commands to get the x and y-axis tilt values, this program uses a SERIN command to get the x and y-axis tilt values that are relayed by the RF receiver. The SERIN command waits to receive the "!" character, then stores the next four bytes to reconstruct the x and y-axis word variable values. After this SERIN command, the x and y variables store the raw accelerometer measurements. This makes the rest of the program easier because it can be written as though the accelerometer is on-board.
SERIN 11, 16780, [WAIT("!"), x.HIGHBYTE, x.LOWBYTE, y.HIGHBYTE, y.LOWBYTE]
These scaling and offset commands differ from UphillBoeBot.bs2. The narrower range of values makes the RF tilt controller friendlier in terms of fine motor control with a range of -62 to + 62 instead of -625 to + 625. The statements now convert the highest measurement into the lowest result, and vice versa. They do so by subtracting the scaled accelerometer measurements from 62 instead of subtracting 62 from the scaled accelerometer measurements. This change converts a hill climbing Boe-Bot into a hill descending Boe-Bot.
x = 62 - ((x MIN 1875 MAX 3125) - 1875 / 10) y = 62 - ((y MIN 1875 MAX 3125) - 1875 / 10)
The navigation decisions are also slightly different from UphillBoeBot.bs2. They have been modified to make driving your Boe-Bot with a tilt controller easier and more intuitive. The statement IF (ABS(x) > 12) OR (ABS(y) > 12) THEN creates a deadband so that the Boe-Bot doesn't immediately react as soon as you just barely tilt the RF tilt controller. When both x and y are in this range, the ELSE statement at the bottom of the code block makes the Boe-Bot hold still. Once you tilt the controller far enough to make x or y greater than 12 or less than -12, y is subtracted from pulseLeft and added to pulseRight. When y is negative, it makes the Boe-Bot go backwards, if it's positive, the Boe-Bot goes forwards. After the forward pulse values have been determined, the turn can be mixed in. For forward motion, the x tilt values have to be subtracted from both pulseLeft and pulseRight to get that natural forward turning control. When the Boe-Bot is backing up, the turn directions have to be reversed to keep the control intuitive, so instead of subtracting x from pulseLeft and pulseRight, x is added to these variables.
IF (ABS(x) > 12) OR (ABS(y) > 12) THEN pulseLeft = 750 - y pulseRight = 750 + y IF (ySign = Negative) OR (ABS(y) < 12) THEN pulseLeft = pulseLeft - x pulseRight = pulseRight - x ELSE pulseLeft = pulseLeft + x pulseRight = pulseRight + x ENDIF ELSE pulseLeft = 750 pulseRight = 750 ENDIF
The remainder of the program, especially the ramping routine, is introduced and explained in more detail in Boe-Bot Robot Navigation with Accelerometer Incline Sensing.
Your Turn – Making Time for Sensors
There are many ways to make time for other sensors. The easiest is to check RF messages and read the sensors between alternate servo pulses.
- Add the declaration operation VAR Bit to the variables section.
- Add this command operation = ~ operation at the beginning of the main routine, on the line just below DO.
- Using a SELECT...CASE statement evaluates the operation variable that executes the existing main routine for when CASE is 0, and a new routine (add PAUSE 40 for now) when CASE is 1. That's enough time to check a lot of sensors.
- Try your modified code out and decide whether or not the change in performance is acceptable.