Omnima/OpenWRT and Xbee

I have recently connected up an Omnima Embedded Board to an Xbee device, using it as a low-cost and low-power controller for a home Xbee network. This article explains how to configure an Omnima with OpenWRT/Linux such that is capable of talking to an Xbee device using Python and Pyserial.

The Xbee is mounted in a Sparkfun Xbee Explorer USB module which contains an FTDI USB-serial converter and presents itself as an additional serial port to the Omnima embedded board. The Omnima can then open and access the serial device in order to send and receive data via the Xbee network.

Sparkfun Xbee Explorer USB

USB-Serial Converter and Pyserial

In order to communicate with the Xbee Explorer USB-serial converter we first need to build and install the generic USB-serial kernel module, together with the FTDI driver. To build these drivers you must enable them in your kernel configuration, selecting the generic USB-serial converter and USB FTDI drivers to be built as modules (‘M’) in kernel_menuconfig:

make kernel_menuconfig

In order to access the Xbee from Python programs, you must build the python-mini and Pyserial packages. This is achieved by adding the packages using the feeds script:

./scripts/feeds install python-mini pyserial

You might expect this to be sufficient to use Pyserial on the OpenWRT target, but if you are using python-mini, as is generally required on a board with limited resources like the Omnima, you will find that Pyserial is missing a key module required for serial comms. For this reason you must actually build the full-blown python package, although you will only pick one module out of here. You don’t actually need to use the full-blown Python package, you can still use python-mini and supplement it with any additional required modules using the modules built by the full Python package. To enable the building of full Python use:

./scripts/feeds install python

With the kernel modules, Pyserial and Python enabled, you should now run menuconfig to enable the modules you just selected:

make menuconfig

In the Languages menu select Python, Python-mini and Pyserial. In the Kernel Modules menu select kmod-usb-serial and kmod-usb-serial-ftdi. In each case you should build them as modules using ‘M’ rather than ‘*’ as you don’t want to increase the size of the kernel image due to the limited flash on the Omnima device. Building as modules keeps the flash kernel image size down, but still allows you to load the modules later from a USB or other filesystem device.

Now quit and build the system:

make

You will now have a set of .ipk files for Python-mini, Pyserial and the USB-serial kernel modules in the bin/packages folder, and the full-blown python package from which we can pick and choose any additional modules we need which are missing from the more basic python-mini package which we are going to use. Copy the .ipk installers over to a temporary folder on the device, for example if you have an SSH server running use the following:

cd bin/packages/target...
scp python-mini* pyserial* kmod-usb-serial_* kmod-usb-serial-ftdi* root@192.168.1.110:/opkg

Now from a shell on the device, install python-mini and pyserial:

opkg install /opkg/python-mini* /opkg/pyserial*

Next, install the USB-serial kernel modules. You might expect to do this using simply:

opkg install /opkg/kmod-usb-serial_* /opkg/kmod-usb-serial-ftdi*

However you may get the following error:

 * ERROR: Cannot satisfy the following dependencies for kmod-usb-serial:
         *  kmod-usb-core

I suspect this is because on the Omnima board we typically build usb-core into the kernel image rather than as a separate module, which confuses opkg’s dependency-checking. If you’re sure that you have kmod-usb-core enabled using a ‘*’ in menuconfig, you can force opkg to ignore dependencies as follows:

opkg install -nodeps /opkg/kmod-usb-serial_* /opkg/kmod-usb-serial-ftdi*

This should install the appropriate devices for communication with the USB-serial converter on the Xbee carrier board. You can confirm by inserting the Xbee carrier module cable into the USB port, and viewing the output of dmesg. You should see a note that it has created the TTY device “USB0”. With this in place you are ready to write an application which can talk to the Xbee module.

Python Serial Application

You can use any programming language for your application which communicates with the Xbee module via serial, but for the purposes of this example we will use Python together with the Pyserial module.

If you attempt to use python-mini and import the Pyserial module (using import serial) out of the box, however, you will be met with the following error message:

"ImportError: No module named termios"

This is because the serial module is removed from the default python-mini installation, in order to keep its size down. We can get around this, however, by pulling in the file from the full Python package which we built earlier. We simply copy the termios.so module from the full-blown Python build which still resides on the development PC onto the target device’s python-mini installation directory.

scp build_dir/target-mipsel_uClibc-0.9.30.1/Python-2.6.1/ipkg/python/usr/lib/python2.6/lib-dynload/termios.so root@192.168.1.110:/usr/lib/python2.6/lib-dynload

Note that the ipkg/python folder contains the full Python tree, while ipkg/python-mini contains the cut-down package tree. You can compare the two to see which other modules have been removed from python-mini.

After having copied termios.so on to the target, you should now be able to SSH into the target, run the python command and import the Pyserial module using import serial.

Communications with the Xbee module using Pyserial is modelled on simple file open/read/write/close calls. An example application which opens the serial device, reads a byte and then closes the port is as follows:

ser_handle = serial.Serial ('/dev/ttyUSB0', baudrate=9600, bytesize=8, parity='N', stopbits=1, xonxoff=0, rtscts=1)
byte = ser_handle.read()
ser_handle.close()

This uses the Xbee module’s default baudrate and other serial settings. Further details on how to write Pyserial applications are available from its homepage.

Running Your Application at Boot Time
Once you have created a suitable Python application for communicating with the Xbee module, you may want to set it to run automatically when the Omnima boots. This is done by creating an init.d script which calls up your Python application. A simple example that supports starting an application (but not stopping) follows:

#!/bin/sh /etc/rc.common
# Example Pyserial application startup script

START=60

start() {
	echo Starting Pyserial Application
	/root/myapp/myapp.py
}

This script should be stored in the /etc/init.d folder, and once created should be made executable using chmod +x /etc/init.d/myapp.

You can now run /etc/init.d/myapp start to test your application is successfully started by this script. Once you are happy with the script, you can make it autorun at boot time using /etc/init.d/myapp enable.

You can now reboot the device and check that your application was started.

Extending Python-mini
You may find that the python-mini package is missing some key modules required for the applications you wish to write. If you find this is the case then you can use the same method described above for adding serial/termios support. Whenever python-mini complains of missing modules, you can copy them from the full-blown Python install on your development PC. The missing modules are generally .py files (for example smtplib.py) in the ipkg/python/usr/lib/python2.6/ folder, but in some cases (as with termios.so) they are compiled object modules in ipkg/python/usr/lib/python2.6/lib-dynload.

Bookmark and Share This Article
[del.icio.us] [Digg] [Google] [Reddit] [Slashdot] [StumbleUpon] [Technorati] [Twitter] [Yahoo!] [Email]
This entry was posted in HowTo and tagged , , , , , , , , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *