Radio Control
In this example, we'll utilize the micro:bits' abilities to communicate with one another, as well as the built-in buttons to control our RVR+/RVR wirelessly! We'll give the RVR+/RVR its own micro:bit and use a second micro:bit as a controller to cut the physical ties between the RVR+/RVR and that which is controlling it.
This example should take about 45 min to go through before you are ready to hit the road!
If you haven't already set up your micro:bit and favorite editor, it's probably best to take care of that before jumping in here. Feel free to check out our Getting Started docs on:
Hardware Setup (Parts List)
If you want to build your own Radio Control RVR+/RVR, you will need the following parts (most of them are included in this nifty "inventor's" kit from SparkFun):
2 BBC micro:bits (if you have two colors, it might help avoid confusion with which is being used for your controller and which is being used for your RVR 😉)
Data-Enabled Micro B USB cable
Batteries (check what kind are required for your Battery Holder)
Software Setup
The code is divided into two folders: transmitter and receiver. Let's explore the code a bit and then we'll walk through how to flash the code to the respective micro:bits.
The Code
Transmitter
Let's get started with our imports. One of the coolest things about micro:bit is that it has (A and B) buttons built in, so you don't need additional components to be able to give it inputs. This allows us to use the micro:bit, itself, as our "transmitter".
We'll import the buttons, so that we can use them for our code and will also be using the display on the micro:bit, so we'll import display and image, too:
import radio
from microbit import button_a
from microbit import button_b
from microbit import display
from microbit import Image
We start by configuring the radio (so the micro:bits can talk to each other):
radio.config(group=1)
radio.on()
And initiating that neither button is being pressed at the start of the program:
a_pressed = False
b_pressed = False
The control code is simple. We start by setting the values of the variables we initiated earlier (a_pressed and b_pressed) to functions that trigger when a button on the micro:bit is pressed (is_pressed).
If only A is pressed, we will display an arrow for the direction the RVR+/RVR will head in ('W' or left) on the micro:bit and will send a string of 'a_pressed' to the receiver (we'll address how the receiver interprets that string in the next section).
In the next bit of logic (if the previous was untrue), if only B is pressed, we will display an arrow for the direction the RVR+/RVR will head in ('E' or right) on the micro:bit and will send a string of 'b_pressed' to the receiver.
If neither of those pieces of logic were true, we check if both A and B are pressed then we display an arrow for the direction the RVR+/RVR will head in ('N' or forward) and send a string of 'ab_pressed' to the receiver.
Our final condition is for the case in which all buttons have been released, in which case, the micro:bit displays a downward arrow (signified by the letter 'S') and a string of 'not_pressed' is sent to the receiver:
while True:
a_pressed = button_a.is_pressed()
b_pressed = button_b.is_pressed()
if a_pressed and not b_pressed:
display.show(Image.ARROW_W)
radio.send('a_pressed')
elif not a_pressed and b_pressed:
display.show(Image.ARROW_E)
radio.send('b_pressed')
elif a_pressed and b_pressed:
radio.send('ab_pressed')
display.show(Image.ARROW_N)
else:
radio.send('not_pressed')
display.show(Image.ARROW_S)
Now that we've gotten that sorted out, let's dive in to the receiver code...
Receiver
Let's get started with our imports. We'll be using the display on the micro:bit, so we'll import display and image and this is where we'll actually make the RVR+/RVR drive, so we also import RVRDrive from sphero:
import radio
from microbit import display
from microbit import Image
from microbit import sleep
from sphero import RVRDrive
Once again, we'll configure the radio (so the micro:bits can talk to each other), and we'll also set the RVR's "compass" so it's current direction is "forward":
radio.config(group=1)
radio.on()
RVRDrive.reset_yaw()
We'll initialize all our parameters, stating that the RVR+/RVR is not moving and is facing forward. We'll also set the rates for how fast the RVR+/RVR turns, how fast it accelerates and how quickly it decelerates:
speed = 0
heading = 0
turn_rate = 5
accel_rate = 10
decel_rate = 20
Now for the meat of the code! One of the very first things we do is prepare to receive the strings sent by the transmitter and store them in a variable called data. In our logic, we check the string sent by the transmitter and adjust the speed and heading accordingly:
In our next logic block, we ensure that the speed does not dip below 0 or go above 225.
In our final logic block, we also keep the heading between the bounds of 0 and 359 (because 360 is the same as 0).
Once all of the data has been collected, we have the RVR+/RVR drive in the heading we landed on at the speed we landed on:
while True:
data = radio.receive()
if data != None and data == 'a_pressed':
display.show(Image.ARROW_W)
heading -= turn_rate
speed -= turn_rate
elif data != None and data == 'b_pressed':
display.show(Image.ARROW_E)
heading += turn_rate
speed -= turn_rate
elif data != None and data == 'ab_pressed':
display.show(Image.ARROW_N)
speed += accel_rate
else:
display.show(Image.ARROW_S)
speed -= decel_rate
if speed < 0:
speed = 0
elif speed > 255:
speed = 255
if heading > 359:
heading = heading - 359
elif heading < 0:
heading = 359 - heading
sleep(25)
RVRDrive.drive(speed, heading)
Let's get flashy with it!
Flashing the Code
While we did just walk through the two code files specific to this project in detail, it may be helpful to use the ones we have stored in our GitHub, since you'll also need our more generic sphero.py program to make the receiver work correctly. As you might have guessed, the code contained within each (transmitter or receiver) folder gets loaded onto the micro:bit you want to act as the either transmitter or receiver.
There are a couple of ways to compile and load code onto a micro:bit. We recommend using the micro:bit Python Editor to flash Python code onto your micro:bit. See detailed instructions on our micro:bit Python Setup page.
Hardware Setup (Plugging Everything In)
We have two assemblies to complete, one for the RVR+/RVR and one for the controller...
The RVR+/RVR
To complete the RVR+/RVR setup, you need only connect your receiver micro:bit to your RVR+/RVR using the Data-Enabled Micro B USB cable:
The Controller
For the controller (transmitter), just pop your batteries into your battery pack and plug it in to the JST connection port on your micro:bit:
You Did It!!
Once both micro:bits are powered, they will both display an arrow pointing down; this means you are ready to roll!
Driving Controls:
Pressing the A button will rotate RVR+/RVR counter clock-wise.
Pressing the B button will rotate RVR+/RVR clock-wise.
Pressing both A and B will drive rover forward.
Pressing no buttons will slow RVR+/RVR down. (ie bring it to a screeching halt...)
Now What?
Try to improve your Radio Controlled RVR+/RVR! Here are some ideas to get you started:
Add a camera so the RVR+/RVR can show you spaces you couldn't fit in yourself.
Add some code to use the light or color sensors to help you set boundaries and help the RVR+/RVR protect itself from your bad driving 😜.
Add some code to use the light sensors to change the speed of the bot based on how dark the area it is in is.