XBee MicroPython Examples
Introduction
Simple programs can make a big difference! An XBee running small amounts of code can perform some pretty important tasks. Cryptic readings can be transformed into useful data, excess transmissions can be intelligently filtered out, modern sensors and actuators can be employed directly, operational logic can glue inputs and outputs together in an intelligent way.
Here are some useful MicroPython examples that should run within 12KB of RAM, useful even in a small sandboxed implementation. Required parts and a method for simulating limited RAM are noted below.
Examples
Send “Hello World”
This example shows how to send some text data via an XBee in transparent mode.
- SETUP: Connect the XBee (configured to factory defaults) as shown in the diagram below:
- PROGRAM: Load the code sample into your pyboard’s main.py file1234# main.py -- Send Text Example v1.0 - XBee MicroPythonfrom pyb import UART # load UART resourcesuart = UART(4, baudrate=9600) # create UART object on X1, X2uart.write('hello world!') # write data
- RESULTS: Connect a second XBee, also configured to factory defaults, to your computer. Then use a terminal program like XCTU or CoolTerm to receive the text data. Each time you reset the pyboard, it sends “hello world!” one time to your computer. The results will look like this:
Read, Transform and Send Value
This example shows how to read a sensor, transform that data into correct units, then send via an XBee in transparent mode.
- SETUP: Connect the XBee (configured to factory defaults) and a TMP36 temperature sensor as shown in the diagram below. You can use the XBee pyboard skin to easily connect the radio module, and a small breadboard connected with jumper wires for the TMP36.
- PROGRAM: Load the code sample into your pyboard’s main.py file123456789# main.py -- Read Transform Send v1.0 - XBee MicroPythonfrom pyb import Pin, ADC, UART # load resourcesuart = UART(4, baudrate=9600) # create UART object on X1, X2pin = ADC(Pin('Y12')) # configure Y12 for ADCwhile True: # loop continuouslytemp = (int((pin.read() * (3300/4096)) - 500) / 10) # read analog TMP36 and transformuart.write(str(temp)) # write datauart.write(' Celsius\n') # write text labelpyb.delay(2000) # wait two seconds
- RESULTS: Connect a second XBee, also configured to factory defaults, to your computer. Then use a terminal program like XCTU or CoolTerm to receive the sensor data. The results will look like this:
Read, Transform and Send Only High Sensor Values
This example shows how to read a sensor, filter out low values, then send via an XBee in transparent mode.
- SETUP: Use the basic sensing setup.
- PROGRAM: Load the code sample into your pyboard’s main.py file12345678910# main.py -- Read Transform Send High Values v1.0 - XBee MicroPythonfrom pyb import Pin, ADC, UART # load resourcesuart = UART(4, baudrate=9600) # create UART object on X1, X2pin = ADC(Pin('Y12')) # configure Y12 for ADCwhile True: # loop continuouslytemp = (int((pin.read() * (3300/4096)) - 500) / 10) # read analog TMP36 and transformif (temp > 30): # only send high readingsuart.write(str(temp)) # write datauart.write(' Celsius\n') # write text labelpyb.delay(2000) # wait two seconds
- RESULTS: Connect a second XBee, also configured to factory defaults, to your computer. Then use a terminal program like XCTU or CoolTerm to receive the sensor data. The results will show ONLY readings above the limit of 30 Celsius, no other data will be displayed:
Read, Transform and Send Only High or Low Values
This example shows how to read a sensor, filter out mid-range values, then send any high or low values via an XBee in transparent mode.
- SETUP: Use the basic sensing setup.
- PROGRAM: Load the code sample into your pyboard’s main.py file12345678910# main.py -- Read Transform Send High or Low v1.0 - XBee MicroPythonfrom pyb import Pin, ADC, UART # load resourcesuart = UART(4, baudrate=9600) # create UART object on X1, X2pin = ADC(Pin('Y12')) # configure Y12 for ADCwhile True: # loop continuouslytemp = (int((pin.read() * (3300/4096)) - 500) / 10) # read analog TMP36 and transformif (temp > 30 or temp < 28): # only send high or low readingsuart.write(str(temp)) # write datauart.write(' Celsius\n') # write text labelpyb.delay(2000) # wait two seconds
- RESULTS: Connect a second XBee, also configured to factory defaults, to your computer. Then use a terminal program like XCTU or CoolTerm to receive the sensor data. The results will show ONLY readings below 28 Celsius or above 30 Celsius, no other data will be displayed:
Send “Heartbeat” Sensor Data
This example shows how to send periodic “heartbeat” data values via an XBee in transparent mode. Used with filters or alarms to confirm normal operation.
- SETUP: Use the basic sensing setup.
- PROGRAM: Load the code sample into your pyboard’s main.py file1234567891011# main.py -- Send Heartbeat Data v1.0 - XBee MicroPythonfrom pyb import Pin, ADC, UART # load resourcesuart = UART(4, baudrate=9600) # create UART object on X1, X2pin = ADC(Pin('Y12')) # configure Y12 for ADClast_reading = 0 # take first reading right awaywhile True: # loop continuouslytemp = (int((pin.read() * (3300/4096)) - 500) / 10) # read analog TMP36 and transformif (pyb.millis() > last_reading): # only send data periodicallylast_reading = pyb.millis() + 60000 # schedule next reading for one minute lateruart.write(str(temp)) # write datauart.write(' Celsius\n') # write text label
- RESULTS: Connect a second XBee, also configured to factory defaults, to your computer. Then use a terminal program like XCTU or CoolTerm to receive the sensor data. The results will show data readings once per minute, though in typical use it might be set to daily or even weekly.
Send “Heartbeat” with Min and Max
This example shows how to send periodic “heartbeat” data values with min and max for the period, via an XBee in transparent mode.
- SETUP: Use the basic sensing setup.
- PROGRAM: Load the code sample into your pyboard’s main.py file123456789101112131415161718192021# main.py -- Send Heartbeat with Min and Max v1.0 - XBee MicroPythonfrom pyb import Pin, ADC, UART # load resourcesuart = UART(4, baudrate=9600) # create UART object on X1, X2pin = ADC(Pin('Y12')) # configure Y12 for ADClast_reading = 0 # take first reading right awaywhile True: # loop continuouslytemp = (int((pin.read() * (3300/4096)) - 500) / 10) # read analog TMP36 and transformtry:if (max_temp <= temp): max_temp = temp # keep max up-to-dateif (min_temp >= temp): min_temp = temp # keep min up-to-dateexcept NameError: # if variables don't exist...max_temp = min_temp = temp # ...reset min and maxif (pyb.millis() > last_reading): # only send data periodicallylast_reading = pyb.millis() + 60000 # schedule next reading for one minute lateruart.write(str(temp)) # write datauart.write(' Celsius now\n') # write text labeluart.write(str(min_temp)) # write min datauart.write(' Celsius min\n') # write text labeluart.write(str(max_temp)) # write max datauart.write(' Celsius max\n') # write text labeldel max_temp, min_temp # delete min and max for next run
- RESULTS: Connect a second XBee, also configured to factory defaults, to your computer. Then use a terminal program like XCTU or CoolTerm to receive the sensor data. The results will show data readings once per minute, with the minimum and maximum values during that period.
Aggregate 10 Samples Then Send Batch
This example shows how to aggregate data before sending in a batch, via an XBee in transparent mode.
- SETUP: Use the basic sensing setup.
- PROGRAM: Load the code sample into your pyboard’s main.py file12345678910111213141516# main.py -- Aggregate Then Send 10 Values v1.0 - XBee MicroPythonfrom pyb import Pin, ADC, UART # load resourcesuart = UART(4, baudrate=9600) # create UART object on X1, X2pin = ADC(Pin('Y12')) # configure Y12 for ADCperiod = 60000 # length between sendssamples = 10 # number of samples in a sendwhile True: # loop continuouslyreadings=[] # create a list to store readingsfor i in range(samples): # sample the right number of timestemp = (int((pin.read() * (3300/4096)) - 500) / 10) # read analog TMP36 and transformreadings.append(temp) # put the sample in the listpyb.delay(int(period/samples)) # wait until the next samplefor value in readings: # iterate through the listuart.write(str(value)) # write datauart.write(' Celsius\n') # write text labeldel(readings) # delete list to prepare for next run
- RESULTS: Connect a second XBee, also configured to factory defaults, to your computer. Then use a terminal program like XCTU or CoolTerm to receive the sensor data. The results will show nothing for a minute, then you should see 10 data readings, sent all at once.
Aggregate Values Then Send Average
This example shows how to aggregate data before sending an average of the data, via an XBee in transparent mode.
- SETUP: Use the basic sensing setup.
- PROGRAM: Load the code sample into your pyboard’s main.py file123456789101112131415# main.py -- Aggregate Then Send Average v1.0 - XBee MicroPythonfrom pyb import Pin, ADC, UART # load resourcesuart = UART(4, baudrate=9600) # create UART object on X1, X2pin = ADC(Pin('Y12')) # configure Y12 for ADCperiod = 60000 # length between sendssamples = 10 # number of samples in a sendwhile True: # loop continuouslyreadings=[] # create a list to store readingsfor i in range(samples): # sample the right number of timestemp = (int((pin.read() * (3300/4096)) - 500) / 10) # read analog TMP36 and transformreadings.append(temp) # put the sample in the listpyb.delay(int(period/samples)) # wait until the next sampleuart.write(str(sum(readings)/samples)) # write averaged datauart.write(' Celsius avg.\n') # write text labeldel(readings) # delete list to prepare for next run
- RESULTS: Connect a second XBee, also configured to factory defaults, to your computer. Then use a terminal program like XCTU or CoolTerm to receive the sensor data. The results will show nothing for a minute, then you should see an average of 10 samples.
Suppress Duplicate Data
This example shows how to suppress sending too many duplicate readings, via an XBee in transparent mode.
- SETUP: Use the basic sensing setup.
- PROGRAM: Load the code sample into your pyboard’s main.py file123456789101112131415161718192021# main.py -- Suppress Duplicate Data v1.0 - XBee MicroPythonfrom pyb import Pin, ADC, UART # load resourcesuart = UART(4, baudrate=9600) # create UART object on X1, X2pin = ADC(Pin('Y12')) # configure Y12 for ADCperiod = 60000 # length between mandatory sendspercent_dif = 10 # percent change that triggers immediate sendlast_temp = 0 # stores last sent sensor valuestart_time = pyb.millis() # mark initial start timewhile True: # loop continuouslytemp = (int((pin.read() * (3300/4096)) - 500) / 10) # read analog TMP36 and transformif pyb.millis() - start_time > period: # when it's madatory send time...start_time = pyb.millis() # update start timeuart.write(str(temp)) # write datauart.write(' Celsius\n') # write text labellast_temp = temp # update last sensor valueif abs(last_temp - temp) > last_temp * percent_dif/100: # significant changes trigger immediate sendstart_time = pyb.millis() # update start timeuart.write(str(temp)) # write datauart.write(' Celsius\n') # write text labellast_temp = temp # update last sensor valuepyb.delay(1000) # wait between samples
- RESULTS: Connect a second XBee, also configured to factory defaults, to your computer. Then use a terminal program like XCTU or CoolTerm to receive the sensor data. The results will show readings every minute, with changes greater than 10% triggering an immediate reading.
Local Control
This example shows how to turn local input into local actions, with alert messages about important events delivered remotely.
- SETUP: Connect the XBee (configured to factory defaults), an LED and a sensor switch as shown below. You can use the XBee pyboard skin to easily connect the radio module, and a small breadboard connected with jumper wires for the LED, the switch and their resistors.
- PROGRAM: Load the code sample into your pyboard’s main.py file12345678910111213141516# main.py -- Local Control v1.0 - XBee MicroPythonfrom pyb import Pin, ADC, UART # load resourcesuart = UART(4, baudrate=9600) # create UART object on X1, X2sensor_pin = Pin('Y9', Pin.IN) # configure Y9 for digital inputalarm_pin = Pin('Y10', Pin.OUT_PP) #configure Y10 for digital outputdelay = 60000 # delay in milliseconds before triggering alarmwhile True: # loop continuouslyif sensor_pin.value() == 1: # if sensor input goes highstart_time = pyb.millis() # mark the timewhile sensor_pin.value() == 1: # keep monitoring inuptif pyb.millis() - start_time >= delay: # if sensor remains on for delay timealarm_pin.high() # turn on the local alarmif not (pyb.millis() - start_time + delay) % 60000: # once a minuteuart.write('Alarm\n') # send a text alertelse: # when sensor is lowalarm_pin.low() # turn alarm off
- RESULTS: Connect a second XBee, also configured to factory defaults, to your computer. Then use a terminal program like XCTU or CoolTerm to receive the alarm alerts. After the switch has been pressed continuously for 60 seconds, the alarm light will turn on. You will receive text alerts in the terminal every minute until the button is released.
Transform UART
This example shows how to accept incoming text strings and transform them to different outgoing text strings.
- SETUP: Use the hello world setup.
- PROGRAM: Load the code sample into your pyboard’s main.py file1234567# main.py -- Transform UART v1.0 - XBee MicroPythonfrom pyb import UART # load UART resourcesuart = UART(4, baudrate=9600) # create UART object for radiowhile True: # loop continuouslyif uart.any() >= 3: # if there's 3 or more bytes to readif 'hw' in uart.readline(): # look for 'hw' input with a linefeed from hostuart.write('hello world!\n') # write transformed output to radio
- RESULTS: Connect a second XBee, also configured to factory defaults, to your computer. Next, using a terminal program like XCTUor CoolTerm, type “hw” into the active window followed by a return. You should receive “hello world” back as shown below. All text input that doesn’t contain “hw” should be ignored.
Respond to Data Request
This example shows how to accept an incoming serial text command and respond with a sensor data reading.
- SETUP: Use the basic sensing setup.
- PROGRAM: Load the code sample into your pyboard’s main.py file12345678910# main.py -- Respond to Data Request v1.0 - XBee MicroPythonfrom pyb import UART, Pin, ADC # load resourcesuart = UART(4, baudrate=9600) # create UART objectpin = ADC(Pin('Y12')) # configure Y12 for ADCwhile True:if uart.any() >= 5: # if there's 5 or more bytes to readif 'temp' in uart.readline(): # look for sensor requesttemp = (int((pin.read() * (3300/4096)) - 500) / 10) # read analog TMP36 and transformuart.write(str(temp)) # write datauart.write(' Celsius\n') # write text label
- RESULTS: Connect a second XBee, also configured to factory defaults, to your computer. Next, using a terminal program like XCTUor CoolTerm, type “temp” into the active window followed by a return. You should receive a temperature reading back as shown below. All text input that doesn’t contain “temp” should be ignored.
Control Pin via UART
This example shows how to turn an LED on and off using serial text input, via an XBee in transparent mode.
- SETUP: Connect the XBee (configured to factory defaults), and an LED as shown below. You can use the XBee pyboard skin to easily connect the radio module, and a small breadboard connected with jumper wires for the LED and resistor.
- PROGRAM: Load the code sample into your pyboard’s main.py file12345678910111213# main.py -- Control Pin via UART v1.0 - XBee MicroPythonfrom pyb import UART, Pin # load resourcesuart = UART(4, baudrate=9600) # create UART objectoutput_pin = Pin('Y10', Pin.OUT_PP) #configure Y10 for digital outputwhile True: # loop continuouslyif uart.any() >= 3: # if there's 3 or more bytes to readincoming = uart.readline() # read from the UARTif 'on' in incoming: # look for 'on' commandoutput_pin.high() # turn on the LEDuart.write('pin on\n') # write statusif 'off' in incoming: # look for 'off' commandoutput_pin.low() # turn off the LEDuart.write('pin off\n') # write status
- RESULTS: Connect a second XBee, also configured to factory defaults, to your computer. Next, using a terminal program like XCTUor CoolTerm, type “on” into the active window followed by a return. You should receive “pin on” back as shown below, and the LED should turn on. Type “off” followed by a return to douse the LED and receive “pin off” as confirmation. All text input that doesn’t contain “on” or “off” should be ignored.
Basic I2C Sensor Read
This example shows how to do a very basic read an I2C sensor (the BMP180), via an XBee in transparent mode.
- SETUP: Connect the XBee (configured to factory defaults), and the BMP180 as shown below (same connections as older BMP085). You can use the XBee pyboard skin to easily connect the radio module, and a small breadboard connected with jumper wires for the BMP180.
- PROGRAM: Load the code sample into your pyboard’s main.py file12345678910111213# main.py -- Basic I2C Sensor Read - XBee MicroPythonfrom pyb import UART, Pin, I2C # load resourcesfrom struct import unpack # resource to unpack readingsuart = UART(4, baudrate=9600) # create UART objecti2c = I2C(2, I2C.MASTER) # create I2C object on bus 2while True: # loop continuouslyi2c.mem_write(0x2E, 0x77, 0xF4, timeout=1000) # writing 2E to slave 0x77's 0xF4 address initiates a temp. readingpyb.delay(5) # wait > 4.5 milliseconds for readingtemp = i2c.mem_read(2, 0x77, 0xF6) # read 2 bytes starting memory address 0xF6 of slave 0x77temp = unpack(">h", temp)[0] # unpack the readings as a big endian shortuart.write(str(temp)) # write datauart.write(' uncalibrated temperature\n') # write labelpyb.delay(1000) # wait a second between samples
- RESULTS: Connect a second XBee, also configured to factory defaults, to your computer. Then use a terminal program like XCTU or CoolTerm to receive the sensor data. The results will show raw, uncalibrated numbers from the temperature sensor since that’s all this example asks for. Warm the sensor with your hand to watch the numbers increase, then let it cool to see them decrease:
Full BMP180 I2C
This example shows how to fully read an I2C sensor (the BMP180), via an XBee in transparent mode.
- SETUP: Use the BMP180 setup.
- PROGRAM: Load the code sample into your pyboard’s main.py file, then download the BMP180 library and put it into the same directory.12345678910111213141516171819# main.py -- Full BMP180 I2C - XBee MicroPythonfrom pyb import UART # load resourcesfrom bmp180 import BMP180 # load library for BMP180bmp180 = BMP180() # create BMP180 objectbmp180.oversample_sett = 2 # take two samples for each reportedbmp180.baseline = 101325 # set baseline altitudeuart = UART(4, baudrate=9600) # create UART objectwhile True: # loop continuouslytemp = bmp180.temperature # take a calibrated temp readingp = bmp180.pressure # take a calibrated pressure readingaltitude = bmp180.altitude # take a calibrated altitude readinguart.write('temp:') # write data and labelsuart.write(str(temp))uart.write(' pressure:')uart.write(str(p))uart.write(' altitude:')uart.write(str(altitude))uart.write('\n')pyb.delay(1000) # wait a second between samples
- RESULTS: Connect a second XBee, also configured to factory defaults, to your computer. Then use a terminal program like XCTU or CoolTerm to receive the sensor data. The results will show calibrated temperature, pressure and altitude readings. Warm the sensor with your hand, and raise or lower it by a few meters to change the readings:
Resources
Simulating Limited RAM
To simulate 12KB of total RAM on the 192KB pyboard, use this block of code at the start of your program, or imported in a config.py file.
1 2 3 4 5 6 | from gc import collect, mem_free # load only the resources needed collect() # perform a garbage collection just to be sure print ("original memory:", mem_free()) # memory should start fill = mem_free() - (12000 - 2784) # free memory - (RAM - framework) blocker = ' ' * fill # create a block of print ("memory now:", mem_free()) # memory should be about 9K now |
Thanks for sharing such valuable information.
Can you please also guide:
1. How to do a implementation using 16 bit and 64 addresses in API mode.
2. One to many and vice versa communication.