In a previous post, I described how to talk to an XBee ZigBee module from a FRDM development platform. In this post, I describe how to do it from Python on e.g. a Windows PC.
First, one obviously has to have a Python environment set up on the computer. I use Python 2.7 and the IPython interactive shell. I will not describe how to install that, but it should not be too hard to do using the instructions on the IPython website.
Then we need to install two modules to enable communication with the XBee. The first one is simply called xbee and can be found here. Download, unpack (using e.g. 7-zip), start a cmd window, cd to the folder with the downloaded files and install it by typing:
python setup.py install
The second is pyserial. Download it from here and install it in a similar manner as described above. This module mentions that it is intended for 32-bit windows, but it has worked fine for me on 64-bit Windows 7.
I use a SparkFun XBee Explorer USB board to interface to the XBee module. This provides an FTDI serial port for communication with the XBee. I soldered an LED with a series resistor between DIO1 and GND to provide easy verification that I was able to control the I/Os of the XBee. The XBee needs to be in API mode. If it is not, the XCTU program from Digi can be used to upload a proper firmware to the module.
Here is the program I wrote to test communication with the XBee:
#! /usr/bin/python # Demo to talk to an XBee ZigBee device # Per Magnusson, 2015-07-28 from xbee import ZigBee import serial import serial.tools.list_ports import time import sys # Look for COM port that might have an XBee connected portfound = False ports = list(serial.tools.list_ports.comports()) for p in ports: # The SparkFun XBee Explorer USB board uses an FTDI chip as USB interface if "FTDIBUS" in p[2]: print "Found possible XBee on " + p[0] if not portfound: portfound = True portname = p[0] print "Using " + p[0] + " as XBee COM port." else: print "Ignoring this port, using the first one that was found." if portfound: ser = serial.Serial(portname, 9600) else: sys.exit("No serial port seems to have an XBee connected.") # Flash the LED attached to DIO1 of the XBee try: xbee = ZigBee(ser) print "XBee test" xbee.at(command='D1', parameter='\x05') # Pin 1 high resp = xbee.wait_read_frame() print resp time.sleep(1) xbee.at(command='D1', parameter='\x04') # Pin 1 low resp = xbee.wait_read_frame() print resp # Try another AT command xbee.at(command='ID') resp = xbee.wait_read_frame() print resp print "Done" ser.close() except: print "Error!" ser.close() raw_input("Press Enter to continue...")
The program has some bells and whistles. First it looks at all the serial ports it can find and selects the first one that could be the XBee (indicated by the text FTDIBUS in the description of the port). It then tries to set up a connection to the ZigBee and issues three local AT commands. The first turns the LED on (then it waits for 1 second), the second turns the LED off and then it issues the ATID command. The response from these commands are printed. At last the serial port is closed and the program waits for the user to press enter to exit the program.
The output may look like this:
In [3]: %run xbee_prog.py Found possible XBee on COM3 Using COM3 as XBee COM port. XBee test {'status': '\x00', 'frame_id': '\x01', 'command': 'D1', 'id': 'at_response'} {'status': '\x00', 'frame_id': '\x01', 'command': 'D1', 'id': 'at_response'} {'status': '\x00', 'frame_id': '\x01', 'parameter': '\x00\x00\x00\x00\x00\x00\x0 0\x01', 'command': 'ID', 'id': 'at_response'} Done Press Enter to continue... In [4]:
Stupid mistake
While writing this program I made a stupid mistake that prevented it from working. I happened to name the program xbee.py and this made the line
from xbee import ZigBee
import the program itself, instead of the installed module. The error message was: ImportError: cannot import name ZigBee. Renaming the program from xbee.py to xbee_prog.py solved this issue.
Now that I realize that Python imported the program itself instead of the module, it is obvious why it could not find ZigBee inside it, but it took a while before I figured that one out.