The next step toward a radio tilt controlled cyber:bot is to radio-transmit those measurements to a receiver.
Before adding tilt control statements, it’s important to just make sure all the data is correctly received and processed. So, in this activity, one micro:bit (or cyber:bot) will measure tilt, and display it with both its terminal and LEDs. It will also radio-transmit its x, y, and needle measurements to a cyber:bot.
The cyber:bot will display the measurements it receives in another terminal. It will also mirror the transmitting LED display with its own.
The radio_tilt_transmit_test script is a modified version of display_tilt_down_with_leds with packetizing and transmitting from Cybersecurity: Radio Data’s Send and Receive [1] packets activity. The packet it sends contains x, y, and needle key-value pairs that the receiver will be able to parse and use.
# radio_tilt_transmit_test from microbit import * import math import radio radio.on() radio.config(channel=7, queue=1, length=64) sleep(1000) while True: x = accelerometer.get_x() y = accelerometer.get_y() angle = round( math.degrees( math.atan2(y, x) ) ) needle = ( angle + 90 + 15 ) // 30 print("Send:") print("x =", x, ", y =", y, ", needle =", needle) print() display.show(Image.ALL_CLOCKS[needle]) dictionary = { } dictionary['x'] = x dictionary['y'] = y dictionary['needle'] = needle packet = str(dictionary) radio.send(packet) sleep(500)
The radio_tilt_receive_test script is a modified version of countdown_receiver from the Cybersecurity: Radio Data’s Send and Receive Packets [1] activity. To receive and display tilt, it is adjusted to parse x, y, and needle values from the packet it receives, and then use statements from display_tilt_down_with_leds to display the tilt with its LEDs and in the terminal.
For best results:
# radio_tilt_receive_test from microbit import * import radio radio.on() radio.config(channel=7, queue=1, length=64) sleep(1000) while True: packet = radio.receive() if packet: dictionary = eval(packet) x = dictionary.get('x') y = dictionary.get('y') needle = dictionary.get('needle') print("Receive:") print("x =", x, ", y =", y, ", needle =", needle) print() display.show(Image.ALL_CLOCKS[needle]) sleep(500)
The goal is to be able to tilt the transmitting micro:bit, and verify matching data in the receive terminal, and on the receiver micro:bit’s LEDs. So, you will be tilting the transmitter while monitoring the receiver.
The script starts with importing modules. Since this script only measures tilt and transmits, it does not need to import the cyberbot module, just the microbit module. It also needs the math module for calculating math.atan2, and the radio module for radio.send.
# radio_tilt_transmit_test from microbit import * import math import radio
After enabling the radio, the script uses radio.config to set the channel, message queue, and message length. As explained in the Cybersecurity: Radio Basics [2] tutorial, the channel defaults to 7, but can be adjusted to an integer from 0 to 83. Classrooms typically assign pairs of students to different channels to avoid crosstalk. The sender and receiver have to be on the same channel for communication to work.
radio.on() radio.config(channel=7, queue=1, length=64)
The queue is the number of messages the micro:bit can buffer. The default is 3, but reducing it to 1 can save memory. The message length defaults to 32, but it’s better to keep it at 64 to make enough room for longer dictionary strings. By reducing queue from 3 to 1, it saves 128 bytes of memory.
Next, sleep(1000) gives the editor time to establish the serial connection with the micro:bit before it has to display text from the micro:bit.
sleep(1000)
The main loop starts with statements from display_tilt_direction_with_leds that take the accelerometer x and y measurements and calculate/display the LED tilt direction needle. There are extra print statements for "Send:" and an empty line. Since the LEDs display the direction of the tilt like a compass needle, the hour variable’s name is changed to needle here.
while True: x = accelerometer.get_x() y = accelerometer.get_y() angle = round( math.degrees( math.atan2(y, x) ) ) needle = ( angle + 90 + 15 ) // 30 print("Send:") print("x =", x, ", y =", y, ", needle =", needle) print() display.show(Image.ALL_CLOCKS[needle]) Next, the x, y, and needle values are added to a dictionary named dictionary. This step is important because it reduces the work the receiver has to do. The receiver can just get the values that correspond to the 'x', 'y', and 'needle' keys.
dictionary = { } dictionary['x'] = x dictionary['y'] = y dictionary['needle'] = needle
After dictionary is populated, all that remains is to convert it to a string, send it through the radio, and delay 0.5 s before repeating the while True loop.
packet = str(dictionary) radio.send(packet) sleep(500)
The script starts in much the same way as the radio_transmit_tilt_test. The main difference is that it does not import the math module since it will receive a pre-calculated needle value from the transmitter.
# radio_tilt_receive_test
from microbit import *
import radio
radio.on()
radio.config(channel=7, queue=1, length=64)
sleep(1000)
The main loop starts by copying any data the radio might have received to a variable named packet. When radio.receive() returns none, the script skips everything in the if packet… statement and repeats the while True loop. When radio.receive() returns a string from the transmitter micro:bit, all the statements in the if packet… statement get executed. First, eval(packet) converts the string that was received back to a dictionary. Then dictionary.get calls set the x, y, and needle variables using the 'x', 'y', and 'needle' keys.
while True: packet = radio.receive() if packet: dictionary = eval(packet) x = dictionary.get('x') y = dictionary.get('y') needle = dictionary.get('needle')
Now, that the receiver has variables with the transmitter micro:bit’s measurements, it can display them in the terminal and with the LEDs. As with the transmitter, these statements are similar to what’s in display_tilt_direction_with_leds with extra print statements for "Receive:" and an empty line, the variable for displaying the tilt direction is needle instead of hour.
print("Receive:") print("x =", x, ", y =", y, ", needle =", needle) print() display.show(Image.ALL_CLOCKS[needle]) sleep(500)
Links
[1] https://learn.parallax.com/tutorials/robot/cyberbot/cybersecurity-radio-data/send-and-receive-packets
[2] https://learn.parallax.com/tutorials/robot/cyberbot/cybersecurity-radio-basics