Remote data collection

If you have more than one micro:bit you can setup one of them to receive data sent by radio from other micro:bits. Remote micro:bits can take measurements and send them to a board that’s connected by USB to a computer. The micro:bit connected to the computer is the data recorder and writes the received data to the serial port.

Remote micro:bit sending

Receiver micro:bit

Connect the micro:bit to a computer with a USB cable. The data received over radio is sent to the computer with this connection using writes to the serial port. You can view the received data with the Data Viewer in the MakeCode editor (you can also receive and view data with the Windows 10 MakeCode app). Otherwise, you need a serial terminal app or some other program that can read from the computer’s serial port.

The receiving micro:bit sets a radio group number on which to listen for incoming messages.

radio.setGroup(99)

The receiver then waits to receive a packet (radio message) from the sender which contains the data to record. This happens inside an ||radio:on received number|| block. If the sending micro:bit is measuring temperature at a remote location (somewhere else in the room maybe), the receiver will write the value received as a temperature measurement to the serial port.

radio.setGroup(99)
radio.onReceivedNumber(function (receivedNumber) {
    basic.showNumber(receivedNumber)
    serial.writeValue("TempCelsius", receivedNumber)
})

Remote sender micro:bit

A remote micro:bit reads its measurement values and sends them to the same radio group as the receiver.

radio.setGroup(99)

A typical measurement program might read a sensor value continuously. Depending on how much the values change, the measurement program could contain the read operation in a loop with a delay interval. In the example here, the delay is one minute between each read of a temperature value. The value is sent on the current radio group with ||radio:radio send number||.

let temperature = 0
radio.setGroup(99)
basic.forever(() => {
    temperature = input.temperature()
    basic.showNumber(temperature)
    radio.sendNumber(temperature)
    basic.pause(60000)
})

Sending multiple values

The remote micro:bit in the previous example sent a single value which was temperature. The receiver understands that the incoming value is a temperature measurement. If you want the remote to also send the current amount of light measured, the receiver won’t know that this other value isn’t a temperature reading.

The sender code is modified to use a value packet instead of just a number message. Here’s the sender program sending both temperature and light values with ||radio:radio send value||.

let temperature = 0
let lightLevel = 0
radio.setGroup(99)
basic.forever(() => {
    temperature = input.temperature()
    radio.sendValue("temperature", temperature)
    lightLevel = input.lightLevel()
    radio.sendValue("light", lightLevel)
    basic.pause(60000)
})

Here’s the program for the receiver to record both temperature and light:

radio.setGroup(99)
radio.onReceivedValue(function (name: string, value: number) {
    basic.showString(name + ":")
    basic.showNumber(value)
    serial.writeValue(name, value)
})

The receiver program uses just one ||radio:on received number|| event to record the values. The name and the value are parameters for the event block so both temperature and light values are received here.

Multiple remote stations

For more complex data recording situations, you might need to measure sensor values from multiple locations at the same time. This means that there is more than one remote micro:bit (station) measuring data.

Separate radio groups

You could add another receiver micro:bit and set it to a different radio group. This way you can copy the same programs to each sender and receiver and just change the radio group number for the matched boards. This solution, though, means you need an extra receiver board and another computer to record the data from the second station.

Station identifiers

A different solution from using more than one radio group is to still have just one receiver on one group but make the different stations send identifiers with their values.

This is done with ||radio:radio set transmit serial number|| which tells the radio to add the board’s serial number to the packet it sends. The serial number is included with the name and value so the receiver can know what station it comes from.

radio.setTransmitSerialNumber(true)

The sender’s program with the identifier added:

let temperature = 0
radio.setGroup(99)
radio.setTransmitSerialNumber(true)
basic.forever(() => {
    temperature = input.temperature()
    basic.showNumber(temperature)
    radio.sendValue("temperature", temperature)
    basic.pause(60000)
})

The program on the receiver board can use the serial number to make a name value pair that the Data Viewer can recognize:

let id = 0;
radio.setGroup(99)
radio.onReceivedValue(function (name: string, value: number) {
    id = radio.receivedPacket(RadioPacketProperty.SerialNumber)
    basic.showString(name + ":")
    basic.showNumber(value)
    serial.writeValue(id + "_" + name, value)
})

The serial number, id, is used as a prefix for the name to identify which station the value came from.

Extended data recording

If you’re recording data to save on a computer for analysis or other uses outside of the MakeCode editor, you can create your own custom recording data format to log reported data. One way to do this is by forming a JSON string with the information related to the data sample.

Data samples

A data sample is a snapshot of some input value at a particular moment in time. A sample usually contains several pieces of information such as the value recorded, the time it was recorded, and a name to identify what the value is for.

As an example, if you know that the remote station is sending you a name-value pair for temperature data, you can report that data in a JSON string like this:

radio.onReceivedValue(function (name, value) {
    serial.writeString("{")
    serial.writeString("\"t\":" + radio.receivedPacket(RadioPacketProperty.Time) + ",")
    serial.writeString("\"s\":" + radio.receivedPacket(RadioPacketProperty.SerialNumber) + ",")
    serial.writeString("\"n\":\"" + name + "\",")
    serial.writeString("\"v\":" + value)
    serial.writeLine("}")
})

The output to the serial port is a line of text with these name-value pairs:

  • t - time: the time when the packet was sent
  • s - serial: the serial number of the board that sent the packet (if enabled)
  • n - name: the name for the data value sent in the packet
  • v - value: the data value for the number sent in the packet

The JSON formatted in the received event is sent in this format to the serial port:

{"t":3504,"s":1951284846,"n":"temperature","v":19} 
{"t":3823,"s":1951284846,"n":"temperature","v":20} 
{"t":4143,"s":1951284846,"n":"temperature","v":20} 
{"t":4463,"s":1951284846,"n":"temperature","v":18} 
{"t":4781,"s":1951284846,"n":"temperature","v":21} 
{"t":5102,"s":1951284846,"n":"temperature","v":17} 

See also

radio, serial write value

radio