Home » Electronics

Category Archives: Electronics

Network Backups via Rsync and Rsnapshot

Network Backups via Rsync and Rsnapshot (via www.jeffskinnerbox.me)
I got a 4 Terabyte Seagate Backup Plus hard drive as a Christmas present and I plan to put it to use as a central backup for my Linux desktop, multiple Raspberry Pi, my laptop, and anything else that my come along. My plan is to keep things simple but I wish to do regular hourly, daily, weekly, and monthly incremental backups. This will give me the ability to recover files from the past, but also to recover from a hardware failure or software install that has gone very badly.

There are many backup tools you can pick from but I wanted to stick with something basic, widely used, and simple. Rsync is one of the most widely used Linux backup solutions, and in fact, it is often used by other backup tools as a foundational component. Rsync stands for remote synchronization tool. Rsync is a UN*X command line utility, containing a special protocal and algorithm, that synchronizes files and directories from one location to another while minimizing data transfer by using fast incremental file transfers. (rsync has also been ported to Microsoft Windows, Mac, and other operating systems.) The first time, rsync sends all the data over the network to your backup machine. The benefit comes the next time you backup………

(more…)

Having Fun with Wine, VirtualBox, and TurboTax

Having Fun with Wine, VirtualBox, and TurboTax (via www.jeffskinnerbox.me)

Sometime ago, I committed myself to Linux and Wine, with the promise that I would sincerely abandon Microsoft Windows by notdual booting my system nor installing any virtualization software. Well, it is now tax-time and the Federial goverment wants their “fair share” of my income. Will my prefered tax software package, TurboTax, run with Linux & Wine? All the evidence I have gathered (see Wine’s ratings for one data point) on the web leads me to believe I will be very disapointed. I can’t find any success stories! Never the less, I will use this as a learning opportunity. I’m going to plung forward and try to get TurboTax working with Wine, …. and it it fails me, resort to VirtualBox, which appears to have at least some success stories…..

(more…)

IPython Notebook in Virtualenv

IPython Notebook in Virtualenv (via www.jeffskinnerbox.me)
I discovered a problem with using nbconvert for posting IPython Notebooks to my blog. Basically it doesn’t work for my version of IPython, so I looked for an upgrade. I found it but its only delivered bundled with the latest version of IPython. Currently, I’m stuck with using IPython 0.13.2 on my Ubuntu system, at least if I use the distribution provide via Ubuntu. And I can only expect to have problems if I try mixing an older version of IPython with the latest version of nbconvert.

I sure Ubuntu will be getting around to supporting the latest version of IPython (i.e. IPython 1.1.0). in the next few weeks to months, but that doesn’t help me now. I’m hesitant to do a whole sale upgrade of IPython on my system since it my upset other thing I got going on.

The answer to my dilemma will be using the Python Org tool virtualenv (see this for full documentation). This tool will give me a virtual environment that will not disrupt my other projects. Virtualenv is a tool to create isolated Python environments, quite likechroot jail on Unix systems. In a chroot, programs cannot access anything outside of chroot but in virtualenv as the name implies, it creates isolated environments only with respect to libraries, but the programs can still access the files and folders normally. With this, I can support my blog IPython 1.1.0 while also maintaining my other projects which requires IPython 0.13.2……

(more…)

I’m Moving so I can Blog with IPython Notebook

I have moved to www.jeffskinnerbox.me

Signals & Systems for Dummies

Signals & Systems for Dummies

To gain a deeper understanding of the GNU Radio software, I want to rebuild some skills & insights in digital signal processing.  But before I take on this topic, I want to refresh my signals & systems skills I learned long ago while in college.  I have chosen Mark Wickert’s book, Signals and Systems For Dummies, to do this.

Learning IPython for Interactive Computing and Data Visualization

Learning IPython for Interactive Computing and Data Visualizatio

Go ahead and laugh if you wish, but I got good reasons for choosing this book. I like its brevity, since I don’t want to spend a great deal of time re-honing these old skills (I expect them to come back quickly), and its use of IPython will help me master a powerful tool that I foresee using within this blog; specifically the IPython Notebook.  To begin learning IPython, I’m currently reading Learning IPython for Interactive Computing and Data Visualization by Cyrille Rossant.  So it’s currently “back to school” for me on many levels.

IPython Notebook Spectrogram

Example of a IPython Notebook

So this brings me to the topic of this posting.  Initially I considered moving my blog off of WordPress.com to a WordPress.org hosting site.  This should allow me to post IPython Notebook pages.  WordPress.com  is very restrictive on what you can do with your blog, but the WordPress software, when  self hosted via WordPress.org, can provide you a great deal of blogging freedom.  I need to take advantage of some of the powerful WordPress Plugins and WordPress.com will not support any of them.  Moving to a self-hosted WordPress blog doesn’t appear to be very difficult.  The biggest trick will be picking the right web hosting company that is strong WordPress supporter who will make it easily move my blog from WordPress.com to WordPress.org.

I then took a closer look at how others have successfully using IPython Notebook for blogging.   I took a very close look at Carl Boettiger’s online Lab Notebook.  This introduced me to GitHub Pages and Jekyll.   With these tools you can create an archived, static site that is hosted for free.  I saw the synergy between these tools and how I work with my Linux box, electronics, and now IPython and its seemed like the way to go. The site “Learning Jekyll By Example: Build a Jekyll Website, Start to Finish” says it well:

    • Jekyll can be hosted on any web hosting service that serves static files.
    • Jekyll-powered websites are also extremely secure.
    • Jekyll is mainly targeted at tech-savvy bloggers.
    • But what Jekyll lacks in newbie-friendliness it makes up for in power and flexibility.
    • Jekyll allows you, the content author, to display your work as you see fit, without the typical restrictions imposed by other blogging platforms.

Continues at the new site … www.jeffskinnerbox.me

GNU Radio and Gqrx SDR Receiver

grc logoIn my last post, I was using the RTL2832 TV tuner dongle to get a simple Software Defined Radio (SDR) operational.  I wanted to use the SDR# program as my receiver but found that the MS Windows tool would not work and so I targeted Gqrx as an alternative. Gqrx is dependent on the GNU Radio.  So in this post, I plan to get Gqrx and GNU Radio up and operational with the RTL-SDR dongle.  I spend some time with other tools to help further verify (with mixed success) that GNU Radio is working.

The contain here comes from multiple source and I attempt to list those sources below.  For a good video to get a sense of what your in for, check out this video. Also, this post covers many of the topics here.

GNU Radio is a free & open-source software development toolkit that provides signal processing blocks to implement software defined radios. It can be used with readily-available low-cost external RF hardware to create software-defined radios, or without hardware in a simulation-like environment. It is being used in hobbyist, academic, and commercial environments to support both wireless communications research and real-world radio systems. 

Gqrx is an experimental AM, FM and Single Side Band (SSB) software defined receiver implemented using GNU Radio and the Qt GUI toolkit. Currently it works on Linux and can use the RTL_SDR dongles as input source.

Also within this post, I venture out from gqrx to examine a few other tools.  I don’t cover much territory, nor have much success.  The insperation to examine these other tools comes mainly from the lengthy post “RTL-SDR and GNU Radio with Realtek RTL2832U [Elonics E4000/Raphael Micro R820T] software defined radio receiver“.  Also check out “Getting Started with GNU Radio and RTL-SDR (on Backtrack)“.

Build GNU Radio on Ubuntu

The GNU Radio web site has specific instructions and a build script for installing it on Ubuntu (I’m using version 13.04).  This process claims it may take 1-2 hours to do the install (for me it ran in 1 hour 14 minutes).  The steps are as follows:

cd ~/src
mkdir ~/gnuradio
cd ~/gnuradio
wget http://www.sbrac.org/files/build-gnuradio && chmod a+x ./build-gnuradio && ./build-gnuradio --verbose

When prompted, tell it to proceed and give it sudo privilege by typing “Y”. Because of the --verbose option, you will see a lot of text whizzing by as the build-gnuradio script does its thing. You’ll also see a percentage complete indicator as the script works its way down it tasks.

The GNU Radio build creates a large variety of tools which get installed into /usr/local/bin.  You also notice that tools not directly related to GNU Radio are also created. I’ll leave it for another time to understand and explain the GNU Radio environment.

The “Hello World” of GNU Radio

To verify that the software is working, best thing is to create the typical “Hello, World” program, just we might have done for our first foray into C++, Python, or other programming language.  In the world of GNU Radio, this program has come to be the phone dial tone. To do this, I followed the video The “Hello World” of GNU Radio: Dial Tone and the gnuradio.org.  I did this using the GNU Radio Companion (executable located at /usr/local/bin/gnuradio-companion).  GNU Radio Companion (GRC) is a graphical tool for creating signal flow graphical models and generating Python source code for the model created.

GRC’s generated flow and code for the “Hello, World” program is listed below. The Python code for the dial tone program was placed in the home directory, and in my case, it was called dail_tone.py. While it can be executed via the gnuradio-companion, it can also be executed via python dial_tone.py. The user interface for the GRC and the corresponding Python code it generated is listed below:

dial_tone.grc - -home-jeff - GNU Radio Companion_006

#!/usr/bin/env python
##################################################
# Gnuradio Python Flow Graph
# Title: Dial Tone
# Author: Jeff Irland
# Description: "Hello, World" program - produces phone dial tone
# Generated: Sat Jun 22 21:24:56 2013
##################################################

from gnuradio import analog
from gnuradio import audio
from gnuradio import blocks
from gnuradio import eng_notation
from gnuradio import gr
from gnuradio import window
from gnuradio.eng_option import eng_option
from gnuradio.gr import firdes
from gnuradio.wxgui import fftsink2
from gnuradio.wxgui import forms
from gnuradio.wxgui import scopesink2
from grc_gnuradio import wxgui as grc_wxgui
from optparse import OptionParser
import wx

class dial_tone(grc_wxgui.top_block_gui):

	def __init__(self):
		grc_wxgui.top_block_gui.__init__(self, title="Dial Tone")
		_icon_path = "/usr/share/icons/hicolor/32x32/apps/gnuradio-grc.png"
		self.SetIcon(wx.Icon(_icon_path, wx.BITMAP_TYPE_ANY))

		##################################################
		# Variables
		##################################################
		self.samp_rate = samp_rate = 32000
		self.noise_slider = noise_slider = .005

		##################################################
		# Blocks
		##################################################
		_noise_slider_sizer = wx.BoxSizer(wx.VERTICAL)
		self._noise_slider_text_box = forms.text_box(
			parent=self.GetWin(),
			sizer=_noise_slider_sizer,
			value=self.noise_slider,
			callback=self.set_noise_slider,
			label='noise_slider',
			converter=forms.float_converter(),
			proportion=0,
		)
		self._noise_slider_slider = forms.slider(
			parent=self.GetWin(),
			sizer=_noise_slider_sizer,
			value=self.noise_slider,
			callback=self.set_noise_slider,
			minimum=0,
			maximum=.1,
			num_steps=1000,
			style=wx.SL_VERTICAL,
			cast=float,
			proportion=1,
		)
		self.Add(_noise_slider_sizer)
		self.wxgui_scopesink2_0 = scopesink2.scope_sink_f(
			self.GetWin(),
			title="Scope Plot",
			sample_rate=samp_rate,
			v_scale=0,
			v_offset=0,
			t_scale=0,
			ac_couple=False,
			xy_mode=False,
			num_inputs=1,
			trig_mode=gr.gr_TRIG_MODE_AUTO,
			y_axis_label="Counts",
		)
		self.Add(self.wxgui_scopesink2_0.win)
		self.wxgui_fftsink2_0 = fftsink2.fft_sink_f(
			self.GetWin(),
			baseband_freq=0,
			y_per_div=10,
			y_divs=10,
			ref_level=0,
			ref_scale=2.0,
			sample_rate=samp_rate,
			fft_size=1024,
			fft_rate=15,
			average=False,
			avg_alpha=None,
			title="FFT Plot",
			peak_hold=False,
		)
		self.Add(self.wxgui_fftsink2_0.win)
		self.blocks_add_xx_0 = blocks.add_vff(1)
		self.audio_sink_0 = audio.sink(32000, "pulse", True)
		self.analog_sig_source_x_1 = analog.sig_source_f(samp_rate, analog.GR_COS_WAVE, 350, .1, 0)
		self.analog_sig_source_x_0 = analog.sig_source_f(samp_rate, analog.GR_COS_WAVE, 440, .1, 0)
		self.analog_noise_source_x_0 = analog.noise_source_f(analog.GR_GAUSSIAN, noise_slider, 0)

		##################################################
		# Connections
		##################################################
		self.connect((self.blocks_add_xx_0, 0), (self.wxgui_scopesink2_0, 0))
		self.connect((self.blocks_add_xx_0, 0), (self.audio_sink_0, 0))
		self.connect((self.analog_sig_source_x_0, 0), (self.blocks_add_xx_0, 2))
		self.connect((self.analog_sig_source_x_1, 0), (self.blocks_add_xx_0, 1))
		self.connect((self.analog_noise_source_x_0, 0), (self.blocks_add_xx_0, 0))
		self.connect((self.blocks_add_xx_0, 0), (self.wxgui_fftsink2_0, 0))

	def get_samp_rate(self):
		return self.samp_rate

	def set_samp_rate(self, samp_rate):
		self.samp_rate = samp_rate
		self.analog_sig_source_x_0.set_sampling_freq(self.samp_rate)
		self.analog_sig_source_x_1.set_sampling_freq(self.samp_rate)
		self.wxgui_fftsink2_0.set_sample_rate(self.samp_rate)
		self.wxgui_scopesink2_0.set_sample_rate(self.samp_rate)

	def get_noise_slider(self):
		return self.noise_slider

	def set_noise_slider(self, noise_slider):
		self.noise_slider = noise_slider
		self.analog_noise_source_x_0.set_amplitude(self.noise_slider)
		self._noise_slider_slider.set_value(self.noise_slider)
		self._noise_slider_text_box.set_value(self.noise_slider)

if __name__ == '__main__':
	parser = OptionParser(option_class=eng_option, usage="%prog: [options]")
	(options, args) = parser.parse_args()
	tb = dial_tone()
	tb.Run(True)

When the GRC flow execution button is pressed, the scope and FFT plots are are created as shown below:

Dial Tone_005

The build for GNU Radio also installs the RTL-SDR software, so it would be wise to test GNU Radio with the RTL_SDR hardware and make sure everything is operating as expected.  I want to make a simple FM receiver, comparable to what was done via rtl_fm in RTL-SDR – Software Defined Radio (SDR) for $20. Something equivalent to:

rtl_fm -W -f 99.5M | play -r 32k -t raw -e signed-integer -b 16 -c 1 -V1 -

Using the following postings as a guide:

I had sufficient success to convince myself that GNU Radio was work.

Building Gqrx on Ubuntu

Gqrx is a software defined AM, FM and SSB software defined radio receiver for RTL-SDR based dongles (as well as the Universal Software Radio Peripherals and Osmo SDR devices).  It features a  Qt GUI.  As a QT program, you’ll need to make sure you have QT4 installed (version 5 will not work) and that you have the qtcreator tool is installed:

sudo apt-get install qt4-default
sudo apt-get install phonon-backend-gstreamer

Now download the source for Gqrx via its page on GitHub  and extract it into your target directory. The posting Getting Started With RTL-SDR and the README on the GitHub site where useful in understanding how to do the install.  I did the following:

cd ~/src
git clone git://github.com/csete/gqrx.git
cd gqrx
qmake gqrx.pro
make

At this point, you should find the gqrx executable in ~/src/gqrx directory.  Start up via ./gqrx and you’ll get the screen below (or set your values to equal this):

Configure I-O devices_001

Click “OK” and the screen below will pop up.  Make sure you have the RTL-SDR dongle plugged in and select the button on the top left to start processing data.  I have tuned the radio to a local FM station at 85.7MHz and listen to Washington Nationals vs. Phillies baseball!

Gqrx 0.0 - rtl=0_004

Building Multimode Radio Receiver

This radio receiver is capable of demodulating muitiple modes, specifically AM, FM, USB, LSB , WFM. TV-FM, PAL-FM. It’s easy to use and  has an automated scanning and spectral zoom features where clicking on the spectrogram or panorama to tune to the frequency of interest.

Multimode documentation is sparse to non existent. The posts “Using the Realtek RTL2832 USB “dongle” as a gnuradio multimode receiver” and “RTL-SDR and GNU Radio with Realtek RTL2832U [Elonics E4000/Raphael Micro R820T] software defined radio receiver” and “Getting Started with GNU Radio and RTL-SDR (on Backtrack)” gave some important hints on how to install multimode and get it operational.  I did the following:

cd ~
svn co https://www.cgran.org/svn/projects/multimode/trunk/ ~/src/multimode
make install

When I executed multimode.py, it didn’t product a display.  I suspect its some subtle Python code problem, or more likely.  incompatibility with the latest GNU Radio libraries.  For now, I’m going to abandon this.

GNU Radio Signal Scanner

gr-scan is a program  built upon GNU Radio, rtl-sdr, and the OsmoSDR Source Block.  This receiver constantly changes frequencies in a set order looking for a frequency that has someone transmitting. It is intended to scan a range of frequencies and print a list of discovered signals.  Installation involved the following steps:

cd ~./src
mkdir gr-scan
cd gr-scan

with your browser, download: http://www.techmeology.co.uk/gr-scan/gr-scan-2012082301.tar.gz
gzip -d gr-scan-2012082301.tar.gz
tar -xvvf gr-scan-2012082301.tar
cd gr-scan-2012082301
make

When I attempted to do the make, it complained about missing Gun Radio files.  I suspect the GNU Radio libraries and include files are layed out differently since the time gr-scan was designed (August of 2012).  I’m leaving fixing this to another time.

What’s Next

In this and the previous SDR posts, I focused on getting a taste of the technology without committing myself to much of an effort.  I really need to study and understand the tools that I have assembled. I still need to do a great deal more studying of  the radio spectrum itself … I feel like I’m wondering in the dark most of the time.

Also, I feel that I’m very limited by the antenna I’m presently using (the pitiful dipole that came with the RTL dongle).  I’m thinking of building a better antenna.  Maybe try to pickup a NOAA weather satellites, with its distinctive audio signal when demodulated, and decode one of its satellite weather photos …. maybe.

Another problem with the RTL-SDR is that its internal oscillator is cheap  and drifts, resulting in clock errors with  many kHz of frequency display error in SDR – depending on a band you’re listening to.  This is very annoying if you use your dongle as a radio scanner – what’s the point of knowing frequency of a transmitter if it’s almost random on your SDR?   This frequency error is linear across the spectrum, and can be adjusted in most SDR programs by entering a PPM (parts per million) offset value.  So I need to calculate this error offset so I can  calibrate the SDR software.

RTL-SDR – Software Defined Radio (SDR) for $20

While researching the GNU Radio project, I came upon references to the RTL2832 TV tuners. These dongle are made to receive and decode the European standard digital television, Digital Video Broadcasting — Terrestrial (DVB-T). (By the way, the North American standard is Advanced Television Systems Committee (ATSC), and not  compatible with DVB-T, so this will not work in North America for TV reception.)  In 2012, Antii Palosaari, discovered that there is a device mode for the Realtek DVB-T device chip (RTL2832U) in which raw samples can be captured and transferred to a host computer. This feature enables this device to be used as an inexpensive “front end”  for a Software Defined Radio (SDR) that could be implemented on a PC or other device.

A SDR provide the ability to sample and record the electromagnetic energy (or radio frequency, called “RF” for short) with no preconceived idea as to the structure of the RF signal.  In a sense, you can interact with the RF signal in its must fundamental form.  In addition, a SDR allows you to implement, by means of software, a radio communication system where components that have been typically implemented in hardware.

SDR solutions for the professional-grade applications and amateur radio have been around for some time, but the appearance of cheap solutions for the hacker is new.  There are general purpose SDR platforms for over $1000, like the Ettus Research Universal Software Radio Peripheral (USRP), the $525 SDR-IQ Receiver, to the $450 bladeRF from the Kickstarter Nuand or Great Scott’s DARPA-Funded HackRF for an estimate $300, and now the $20 hacker grade dongle discussed here.  But unlike most of the other referenced solutions,  the dongle  requires a PC, or some sort of attached processor, to provide the signal processing.

In all SDR solutions, a significant amounts of the signal processing is handed over to a numerical processor, rather than being done in special-purpose RF hardware. Such a design produces a radio which can receive and transmit widely different radio protocols (referred to as a waveform) based solely on the software used.  So in a SDR solution, the electromagnetic waveform is rapidly sampled, the sample values are converted to numerical values, and these numbers are manipulated via a discipline called digital signal processing (DSP).  Ultimately, the resulting DSP numerical values produced are converted to an analog signal that goes to a speaker, TV, or other such output device.

The DVB-T dongles can provide a critical component of a cheap SDR, since the chip allows transferring the raw I/Q samples to the host. What I/Q samples are is well beyond what I wish to describe here, but let it be said that practical hardware design concerns make I/Q data the critical for signal processing.  So the fact the dongle does the digital sampling, called a analog-to-digital converter (ADC), and outputs I/Q samples, makes it a valuable asset for a SDR solution.

So how does one get your PC configured to take the dongles I/Q output and create a SDR?  There is GNU Radio (where this post first begun), but a simpler starting point would be the popular, easy, and open source SDR#.  SDR# can perform the required signal processing in an intuitive user interface (if your into Ham Radio, or bit of a RF hacker, and such).  Unfortunately, I couldn’t get SDR# (a MS Windows application) to operate under  Linux and I had to resorted to some simpler utilities.

The Dongle

All this sounds exciting to me (what a geek!) so I purchased from Amazon one of the dongles, specifically the NooElec TV28T v2 USB DVB-T,  FM+DAB & RTL-SDR Receiver, RTL2832U & R820T Tuner, MCX Input.

71RaTxr2WJL._SL1500_

NooElec TV28T

    • NooElec TV28T – This is the manufacture and model name for the device
    • DVB-T – This device is made to receive and decode the European standard digital television, Digital Video Broadcasting — Terrestrial (DVB-T)
    • FM+DAB & RTL-SDR Receiver – The device can also receive FM radio and Digital Audio Broadcasting (DAB) used in several countries, particularly in Europe. RTLSDR is the popular name give to this class of device, which contain the RTL2832U chip, which can be hacked for SDR use.
    • RTL2832U & R820T Tuner – These are the DVB-T demodulator and TV Tuner chips used in the device.
    •  MCX Input – Is a 3.6 millimeter (0.14 in) micro coaxial (MCX) coaxial RF connector 30% smaller that Sub-Miniature version B (SMB) connectors that are typically used in the USA.  MCX is a standard in Europe. It provides broadband capability from DC to 6 GHz.

From the research I have done, I have found that this dongle provides an approximate tuning range of 25MHz-1700MHz for the SDR.  It has been demonstrated to be compatible with most SDR software, including SDR#.  You can pick up FM radio but  don’t expect to pick up long-wave or AM broadcasts since their spectrum lies below 25MHz. You can listen to the 12m 10m 6m 2m 1.25m 70cm 33cm and 23cm ham band, as well as CB, Marine VHF, RC Band, FRS, GMRS, and Airband (Aviation).

The dongle will not provide the desired SDR function out of the box.  It must first be configured (aka hacked) to stream the I/Q samples to the USB output.  This is where Antii Palosaari’s discovery comes into play.  The wiki’s rtlsdr.org and OsmoSDR are good sources for disparate information concerning RTL2832U based SDR, typically called RTL-SDR.  For my purposes, I wanted to get something initially working on my PC (Linux OS) but ultimately I wanted to have the dongle attached to a Raspberry Pi (RPi) and have the RPi be a server or archive of I/Q samples (sort of a intelligent wide band scanner as done in Raspberry Pi and DVB-T receivers and here Raspberry Pi as Remote Server for RTL2832u SDR and here SDR with Raspberry Pi and DVB-T receivers) that could be processed by my PC.  Therefore, the first step is to get the dongle and a good SDR processor working on my PC.

Building rtl-sdr Library and Capture Tools

The  OsmoSDR wiki has some good instructions on how to build the rtl-sdr software. I basically followed the wiki’s instructions but I had to first install cmake (sudo apt-get install cmake) and libusb (sudo apt-get install libusb-1.0-0-dev) to get a successful make.  I then using the following commands:

cd ~/src
git clone git://git.osmocom.org/rtl-sdr.git
cd rtl-sdr/
mkdir build
cd build
cmake ../
make
sudo make install
sudo ldconfig
cmake ../ -DINSTALL_UDEV_RULES=ON

The result is source code placed in ~/src/rtl-sdr/build/src and the executables are placed in /usr/local/bin: rtl_adsb, rtl_eeprom, rtl_fm, rtl_sdr, rtl_tcp, rtl_test.  The documentation for these utilities is nearly non-existent.  The only documentation I could fine is for the rtl_fm, a posting called Rtl_fm Guide: The long lost documentation.  If you use the command line option --help, you will get some description for each of the tools (see the very end of this post for some screen captures).  Here is a short description and some example usages:

    • rtl_sdr – This is an I/Q recorder for RTL2832 based DVB-T receivers. To send 10 samples to stdout, and sampled at 1.8Ms/s with frequency tuned to 392MHz: rtl_sdr -s1.8e6 -f392e6 -n10 -.
    • rtl_test – Bench-marking tool for RTL2832 based DVB-T receivers.  The -t option only works for Elonics E4000 tuners (Therefore, on non-E4000 tuners, you can not test for the tuning range).  To check the possible tuning range: rtl_test -t.  To check the maximum sample-rate possible on your machine (change the rate down until no sample loss occurs): rtl_test -s 2.5e6
    • rtl_fm – A simple narrow band FM demodulator for RTL2832 based DVB-T receivers.  Rtl_fm is a general purpose analog demodulator. It can handle FM, AM and SSB. It can scan more than a hundred frequencies a second. Make sure rtl_fm and the player are both set to use the same data rate.  Tune into a local FM radio station : rtl_fm -W -f 99.5M | play -r 32k -t raw -e signed-integer -b 16 -c 1 -V1 -
    • rtl_tcp –  An I/Q sample server for RTL2832 based DVB-T receivers.  I/Q samples are streamed to a specified IP address and port.
    • rtl_adsb – A simple Automatic dependent surveillance-broadcast (ADS-B) decoder.  ADS-B is a surveillance technology for tracking aircraft as part of the Next Generation Air Transportation System (NextGen).
    • rtl_eeprom – An EEPROM programming tool for RTL2832 based DVB-T receivers.

First Run of the Dongle

The first thing to do is to plug in the dongle and run the test rtl_test -t.  It gave me an error statement expressing “installing the udev rules file rtl-sdr.rules”.  The site “rtl-sdr on Ubuntu” provides some instructions on how to fix this.  The command lsusb | grep Realtek gives me the information I need to create the following entry into /etc/udev/rules.d:

SUBSYSTEM=="usb", ATTRS{idVendor}=="0bda", ATTRS{idProduct}=="2838", GROUP="adm", MODE="0666", SYMLINK+="rtl_sdr"

After another try, I got a successful test.  Next, I sent ten I/O samples to stdout and then tuned into a local FM radio station using these commands:

rtl_sdr -s1.8e6 -f392e6 -n10 -
rtl_fm -W -f 99.5M | play -r 32k -t raw -e signed-integer -b 16 -c 1 -V1 -

sdrsharp

SDR Sharp

Getting SDR# Running in Linux (didn’t work)

The  rtlsdr.org wiki has some instructions on how to get SDR# working within Linux.  Also, the SDR# home page has a link called One shot install script for Linux. Both these sites require you to build the software from source code. Mono is able to run Microsoft .NET applications in Linux.  I attempted this and got errors that I could not figure out (I’m not a MS Windows developer type and I’m not interested becoming one!).

Given this, I chose a different path. I found another posting that claim to get SDR# running in Linux. In this case, only executable will be loaded, not source code that needs to be compiled. You can download SDR# executable from this posting.  You’ll also need to install mono and PortAudio.  Here is how I did it:

sudo apt-get install mono-complete monodevelop
sudo apt-get install libportaudio2
cd ~/src
mkdir sdrsharp
cd sdrsharp

Within ~/src/sdrsharp, install the downloaded SDR# zip file and unzip it.

cd sdr-nightly
ln -s /usr/local/lib/librtlsdr.so librtlsdr.dll
ln -s /usr/lib/i386-linux-gnu/libportaudio.so.2 libportaudio.so

Note, for the above link, you may need to use locate libportaudio.so.2 to find the PortAudio library.

To test things out, I ran the application using mono sdrsharp.exe and got a core dump.  I attempted this again using the stable version of SDR# instead of the nightly build and got the same results.  After the typical thrashing about, I found a bug report for this problem.  Also see “SDR Software – Good, bad and very ugly“.  Also, there seems to be some sort of dispute between SDR# and a new group calling itself Open SDR#.  I’m not sure, but what appears to be at the heart of this is the level of support of SDR# within Linux.  All this is disappointing since SDR# is a very popular tool and I wish I could find away to make use of it within Linux.

The next logical SDR tool to try would be the Linux-based Gqrx SDR receiver, but in this case, it is dependent on GNU Radio.  I’m attempting to delay my conquest of GNU Radio until I do some experimenting with the dongle.  So lets turn our attention to a much simpler tool.

Getting RTLSDR Scanner Running

RTLSDR Scanner is a simple frequency scanning GUI using the OsmoSDR rtl-sdr library.  I more or less followed the installation instructions but they are confusing/out-of-date and you’ll needed to do some adjustments.  The OsmoSDR rtlsdr library has already been installed earlier in the text, so its not listed here.  To get the required files for RTLSDR Scanner:

sudo apt-get install python python-wxgtk2.8 python-matplotlib python-numpy
cd ~/src
git clone git://github.com/roger-/pyrtlsdr.git
cd pyrtlsdr
sudo setup.py
cd ~/src
git clone git://github.com/EarToEarOak/RTLSDR-Scanner.git

With this, I found I could run ~/src/pyrtlsdr/demo_waterfall.py.  Make sure to read the comments in the file to understand how to change the center frequency, gain, etc.  The image below is demo_waterfall.py tuned to the amateur radio 6 meters band.  The image is called a spectrogram (sometimes call spectral waterfall) is a dynamic, visual representation of the spectrum of frequencies in the RF signal.  Blue is low signal strength, where yellow, and red are higher strengths.

demo_waterfall.py

demo_waterfall.py

To get ~/src/RTLSDR-Scanner/src/rtlsdr_scan.py to work, I had to do some coping of files as shown below:

cp ~/src/pyrtlsdr/rtlsdr/rtlsdr.py  ~/src/RTLSDR-Scanner/src/rtlsdr.py
cp ~/src/pyrtlsdr/rtlsdr/librtlsdr.py  ~/src/RTLSDR-Scanner/src/librtlsdr.py

The image below is from rtlsdr_scan.py, again tuned to the amateur radio 6 meters band.  Here again you see the signal strength of the individual amateur radios as vertical spikes.

rtlsdr_scan.py

rtlsdr_scan.py

So we now have auditory and visual proof the dongle is doing its job. Now its on to GNU Radio!

Command-Line Options for RTLSDR Capture Tools

For reference purposes, below are screen shots of the RTLSDR capture tool’s command line options.

rtl_test -s

rtl_test -s

rtl_test

rtl_test

rtl_tcp

rtl_tcp

rtl_sdr

rtl_sdr

rtl_adsb

rtl_adsb

rtl_fm

rtl_fm

A Better Mobile Display for the Raspberry Pi

2013-04-10 20.37.23

iSSH Terminal Session

As I described in an earlier post, I run my Raspberry Pi (RPi) as a headless system, using Cygwin/X‘s xterm for command line interaction with the RPi, with my PC being my X server to support any X Window applications.  I can move files between the PC and the RPi via my pseudo-Dropbox.  I really recommend this configuration and its working perfectly for me.

This configuration gives me a great deal of utility but no mobility …. I’m still tied to my desktop PC.  Maybe I should consider replacing the desktop PC with a laptop but I don’t want to spend the money.  I have seen some small,  inexpensive keyboards and displays that could be connected directly to the RPi, and you could cobble together a mobile unit, or the more elegant Kindle version, but this still doesn’t give me the mobility look & feel I would like.

iPad to the rescue (assuming you have one ….)!   I found a great app call iSSH by Zingersoft.  Its claims that it is a “comprehensive VT100, VT102, VT220, ANSI, xterm, and xterm-color terminal emulator over SSH and telnet, integrated with a tunneled X server, RDP and VNC client. ”   I installed it, configured it quickly, and got  a terminal connection to the RPi without reading the documentation …. Impressive since successfully configuring ssh, Xserver, etc. can be challenging sometimes.  (Note: The easy of this was largely due to setting up RPi environment properly in the first place. See the earlier post).  To top it off, iSSH has a slick look & feel.

Configuring iSSH

iSSH X Server Session

iSSH X Server Session

Zingersoft’s documentation on configuring iSSH is easy to follow and requires just a few steps.  I had no problem getting an terminal session working to the RPi but I did have problems with graphics programs (i.e. X Window client programs).  It appears that iSSH’s terminal isn’t really xterm but a terminal emulation (secured via ssh).  The iSSH terminal doesn’t use the X server.  In fact, while in the terminal session,  to see the X server display (i.e. to see graphics applications rendered via the RPi X client) you must hit the button at the top right of the iPad display.

Frankly, the fact that the X application didn’t work the first time wasn’t a big surprise to me.  I have been struggling with getting my X Window configuration set up to work reliably for some time.  What I was observing was that X would work fine for sometime but at some point I would get the error message “couldn’t connect to display”.

This error is very common and nearly every X user has seen some version of this before.  I assume that the right way to solve this was to gain a deeper understanding of X Windows and discover its root cause .  I did gain a deeper understanding of X Windows, but a solution to my problem never jumped out from the “official” materials I read.  I found the solution when I happened upon the blog “X11 Display Forwarding Fails After Some Time“.

The root cause of my error message is the time out of the X Forwarding.  I have been using the -X option when using ssh.  This is the more secure option for X Forwarding, but comes at a price, as shown below.

    • Using ssh -X, X forwarding is enabled in “Untrusted” mode, making use of various X security extensions, including a time-limited Xauth cookie.
    • Use ssh -Y to enable “Trusted” mode for X, which will enable complete access to your X server. There is no timeout for this option.

So my Display problem isn’t really an error, per say, but ssh timing out on me.  To fix this, I added the entry ForwardX11Timeout 596h into my ~/.ssh/config file on my PC.  With this problem solved, I continued my journey into X.

My Journey to a Better Understanding of X

Using X Windows for the first time can be somewhat of a shock to someone familiar with other graphical environments, such as Microsoft Windows or Mac OS.  X was designed from the beginning to be network-centric, and uses a “client-server” model. In the X model, the “X server” runs on the computer that has the keyboard, monitor, and mouse attached. The server’s responsibility includes tasks such as managing the display, handling input from the keyboard and mouse, and other input or output devices (i.e., a “tablet” can be used as an input device, and a video projector can be an output device, etc.). Each X application (such as xterm) is a “client”. A client sends messages to the server requesting things like “Please draw a window at these coordinates”, and the server sends back messages such as “The user just clicked on the OK button”. These standardized set of messages make up the X Protocol.

The X server and the X clients commonly run on the same computer. However, it is perfectly possible to run the X server on a less powerful computer (e.g. in my case a PC or iPad), and run X applications (the clients) on a powerful machine that serves multiple X servers (or it can be a simple RPi, as in my case). In this scenario the communication between the X client and server takes place over the network (WiFi for my iPad), via the X Protocol. There is nothing in the protocol that forces the client and server machines to be running the same operating system, or even to be running on the same type of computer.

The Display

It is important to remember that the X server is the is the software program which manages the monitor, keyboard, and pointing device. In the X window system, these three devices are collectively referred to as the “display”.  Therefore, the X server serves displaying capabilities, via the display, to other programs, called X clients, that connect to  the X server.  All these connections are established via the X protocol.

The relationship between the X server and the display are tight, in that the X server is engineered to support a specific display (or set of displays).  As a user of X, you don’t have any control over this relationship, only the software developer who created the server can modify this relationship (generally speaking).  On the other hand, as a user you have free hand in configuring the X protocol connection between the X server and the X clients.

How do you establish a X Protocol connection between any given server and a client?  This is done via the environment variable “DISPLAY”.  A Linux environment variable DISPLAY tells all its X clients what display they should use for their windows. Its value is set by default in ordinary circumstances, when you start an X server and run jobs locally. Alternatively, you can specify the display yourself.  One reason to do this is when you want log into another system, and run a X client there, and but have the window displayed at your local terminal.  That is, the DISPLAY environment variable must point to your local terminal.

So the environment variable “DISPLAY” stores the address for X clients to connect to. These addresses are in the form: hostname:displaynumber.screennumber where

    • hostname is the name of the computer where the X server runs. An omitted hostname means the localhost.
    • displaynumber is a sequence number (usually 0). It can be varied if there are multiple displays connected to one computer.
    • screennumber is the screen number. A display can actually have multiple screens. Usually there’s only one screen though where 0 is the default.

Setting the DISPLAY variable depends of your shell, but for the Bourne, Bash or Korn shell, you could do the following to connect with the systems local display:

export DISPLAY=localhost:0.0

The remote server knows where it have to redirect the X network traffic via the definition of the DISPLAY environment variable which generally points to an X Display server located on your local computer.

X Security

So you see, as the user, you have full control over where you wish to display the X client window.   So what prevents you from doing something malicious,  like popping up window on someone else  terminal or read their key strokes?  After all, all you really need is their host name.  X servers have three ways of authenticating connections to it: the host list mechanism (xhost) and the magic cookie mechanism (xauth). Then there is ssh, that can forward X connections, providing a protected connection between client and server over a network using a secure tunnelling protocol.

The xhost Command

The xhost program is used to add and delete host (computer) names or user names to the list of machines and users that are allowed to make connections to the X server. This provides a rudimentary form of privacy control and security.  A typical use is as follows: Let’s call the computer you are sitting at the “local host” and the computer you want to connect to the “remote host”. You first use xhost to specify which computer you want to give permission to connect to the X server of the local host. Then you connect to the remote host using telnet. Next you set the DISPLAY variable on the remote host. You want to set this DISPLAY variable to the local host. Now when you start up a program on the remote host, its GUI will show up on the local host (not on the remote host).

For example, assume the IP address of the local host is 128.100.2.16 and the IP address of the remote host is 17.200.10.5.

On the local host, type the following at the command line:

xhost + 17.200.10.5

Log on to the remote host

telnet 17.200.10.5

On the remote host (through the telnet connection), instruct the remote host to display windows on the local host by typing:

export DISPLAY=128.100.2.16:0.0

Now when you type xterm on the remote host, you should see an xterm window on the local host.  You should remove the remote host from your access control list as follows.

xhost - 17.200.10.5

Some additional xhost commands:

xhost    List all the hosts that have access to the X server
xhost + hostname    Adds hostname to X server access control list.
xhost - hostname    Removes hostname from X server access control list.
xhost +     Turns off access control (all remote hosts will have access to X server … generally a bad thing to do)
xhost -    Turns access control back on (all remote hosts blocked access to X server)

Xhost is a very insecure mechanism. It does not distinguish between different users on the remote host. Also, hostnames (addresses actually) can be spoofed. This is bad if you’re on an untrusted network.

The xauth Command

Xauth allows access to anyone who knows the right secret. Such a secret is called an authorization record, or a magic cookie. This authorization scheme is formally called MIT-MAGIC-COOKIE-1.  The cookies for different displays are stored together in the file .Xauthority in the user’s home directory (you can specify a different cookie file with the XAUTHORITY environment variable).  The xauth application is a utility for accessing the .Xauthority file.

On starting a session, the X server reads a cookie from the.Xauthority file. After that, the server only allows connections from clients that know the same cookie (Note: When the cookie in .Xauthority changes, the server will not pick up the change.).  If you want to use xauth, you must start the X server with the -auth authfile argument.   You can generate a magic cookie for the .Xauthority file using the utility mcookie (typical usage: xauth add :0 . `mcookie`).

Now that you have started your X session on the server and have your cookie in .Xauthority, you will have to transfer the cookie to the client host. There are a few ways to do this.  The most basic way is to transfer the cookie manually by listing the magic cookie for your display with xauth list and injecting it into the remote hosts .Xauthority via the xauth utility.

Xauth has a clear security advantage over xhost. You can limit access to specific users on specific computers and it does not suffer from spoofed addresses as xhost does.

X Over SSH

Even with the xhost and xauth methods, the  the X protocol is transmitted over the network with no encryption.  If you’re  worried someone might snoop on your connections (and you should worry), use ssh.  SSH, or the Secure Shell, allows secure (encrypted and authenticated) connections between any two devices running SSH. These connections may include terminal sessions, file transfers, TCP port forwarding, or X Window System forwarding.  SSH supports a wide variety of encryption algorithms. It supports various MAC algorithms, and it can use public-key cryptography for authentication or the traditional username/password.

SSH can do something called “X Forwarding” makes the communication secure by “tunneling” the X protocol over the SSH secure link.  Forwarding is a type of interaction with another network application, through a inter-mediator, in this case SSH. SSH intercepts a service request from some other program on one side of an SSH connection, sends it across the encrypted connection, and delivers it to the intended recipient on the other side. This process is mostly transparent to both sides of the connection: each believes it is talking directly to its partner and has no knowledge that forwarding is taking place.  This is called tunneling since X protocol is encapsulated within the a SSH protocol.

When setting up an SSH tunnel for X11, the Xauth key will automatically be copied to the remote system(in a munged form to reduce the risk of forgery) and the DISPLAY variable will be set.

To turn on X forwarding over ssh, use the command line switch -X or write the following in your local ssh configuration file:

Host remote.host.name
ForwardX11 yes

The current version of SSH supports the X11 SECURITY extension, which provides two classes of clients: trusted clients, which can do anything with the display, and untrusted clients, which cannot inject synthetic events (mouse movement, keypresses) or read data from other windows (e.g., take screenshots). It should be possible to run almost all clients as untrusted, leaving the trusted category for screencapture and screencast programs, macro recorders, and other specialized utilities.

If you use ssh -X remotemachine the remote machine is treated as an untrusted client and ssh -Y remotemachine the remote machine is treated as trusted client.  ‘-X’ is supposedly the safe alternative to ‘-Y’.  However, as a Cygwin/X maintainer says “this is widely considered to be not useful, because the Security extension uses an arbitrary and limited access control policy, which results in a lot of applications not working correctly and what is really a false sense of security”.

You can configuring SSH via the following files:

    • per-user configuration is in ~/.ssh/config
    • system-wide client configuration is in /etc/ssh/ssh_config
    • system-wide daemon configuration is in /etc/ssh/sshd_config

The ssh server (sshd) at the remote end automatically sets DISPLAY to point to its end of the X forwarding tunnel. The remote tunnel end gets its own cookie; the remote ssh server generates it for you and puts it in~/.Xauthority there. So, X authorization with ssh is fully automatic.

X over SSH solves some of the problems inherent to classic X networking. For example, SSH can tunnel X traffic through firewalls and NAT, and the X configuration for the session is taken care of automatically. It will also handle compression for low-bandwidth links.  Also, if you’re using X11 forwarding, you may want to consider setting ForwardX11Trusted no to guard against malicious clients.

The Window Manager

The X design philosophy is much like the Linux/UNIX design philosophy, “tools, not policy”.  This philosophy extends to X not dictating what windows should look like on screen, how to move them around with the mouse, what keystrokes should be used to move between windows, what the title bars on each window should look like, etc.  Instead, X delegates this responsibility to an application called a “Window Manager”.

There are many window managers available for X and each  provides a different look and feel.  Some of them support  highly configurable virtual desktops like, KDE and GNOME, some of them are lightweight desktop like LXDE which comes with the RPi, or you can operate bare bones (like I am on my PC while using the RPi) and let MS Windows be your Window Manager via Cygwin/X.  The iPad’s iSSH can run without a Window Manager.  In effect, X server uses the display as it sees fit and your unable to control where things loaded. iSSH does have a Window Manage your can use as an option called dwm.  Its a tiling window manager, which is a reasonable way to go given that your pointing device is your finger on the iPad.

X Display Manager

The X Display Manager (XDM) is an optional part of the X Window System that is used for login session management.  XDM provides a graphical interface for choosing which display server to connect to, and entering authorization information such as a login & password.  Like the Linux getty utility, it performs system logins to the display being connected to and then runs a session manager on behalf of the user (usually an X window manager).  XDM then waits for this program to exit, signaling that the user is done and should be logged out of the display. At this point, XDM can display the login and display chooser screens for the next user to login.

In the small world of my RPi’s, a PC, and an iPad, I have no need for an XDM and don’t use one.

Enough of the X Journey … Now in Conclusion

So what does the iSSH give me? I can now sit on the couch, watch TV, and simultaneously login into the RPi with full X Windows support.  Some would call this Nirvana but I call it just VERY NICE.  The iPad/iSSH combination isn’t the perfect user experience but Zingersoft did a good job.

By the way …. the above iPad screen shot of the X Server display with a globe was rendered using the following code:

#!/usr/bin/env python

"""
    Source: http://www.scipy.org/Cookbook/Matplotlib/Maps
"""

from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt
import numpy as np

Use_NASA_blue_marble_image = False

# set up orthographic map projection with
# perspective of satellite looking down at 50N, 100W.
# use low resolution coastlines.
# don't plot features that are smaller than 1000 square km.
map = Basemap(projection='ortho', lat_0=50, lon_0=-100, resolution='l', area_thresh=1000.)

# draw coastlines, country boundaries, fill continents.
if Use_NASA_blue_marble_image:
    map.bluemarble()
else:
    map.drawcoastlines()
    map.drawcountries()
    map.fillcontinents(color='coral')

# draw the edge of the map projection region (the projection limb)
map.drawmapboundary()

# draw lat/lon grid lines every 30 degrees.
map.drawmeridians(np.arange(0, 360, 30))
map.drawparallels(np.arange(-90, 90, 30))

# lat/lon coordinates of five cities.
lats = [40.02, 32.73, 38.55, 48.25, 17.29]
lons = [-105.16, -117.16, -77.00, -114.21, -88.10]
cities = ['Boulder, CO', 'San Diego, CA', 'Washington, DC', 'Whitefish, MT', 'Belize City, Belize']

# compute the native map projection coordinates for cities.
x, y = map(lons, lats)

# plot filled circles at the locations of the cities.
map.plot(x, y, 'bo')

# plot the names of those five cities.
for name, xpt, ypt in zip(cities, x, y):
        plt.text(xpt + 50000, ypt + 50000, name)

# make up some data on a regular lat/lon grid.
nlats = 73
nlons = 145
delta = 2. * np.pi / (nlons - 1)
lats = (0.5 * np.pi - delta * np.indices((nlats, nlons))[0, :, :])
lons = (delta * np.indices((nlats, nlons))[1, :, :])
wave = 0.75 * (np.sin(2. * lats) ** 8 * np.cos(4. * lons))
mean = 0.5 * np.cos(2. * lats) * ((np.sin(2. * lats)) ** 2 + 2.)

# compute native map projection coordinates of lat/lon grid.
x, y = map(lons * 180. / np.pi, lats * 180. / np.pi)

# contour data over the map.
CS = map.contour(x, y, wave + mean, 15, linewidths=1.5)

plt.show()

The Simplest XBee Network

SAMSUNGAs I continue my investigation of the XBee radio, I’m impressed by the functionality compressed into the the small package, but I have been frustrated by one fact.  It has been a hard road to understand the device and to make it do something useful.  There is a confusing mass of commands and options that can be used.  To make things more difficult for me, it is my nature to study my subject at depth, and understand it well, before I commit myself to a project.  The XBee radios are proving to be a deep subject.  I have been struggling to get a simple 802.15.4 network up and working, at least one that is sufficiently complex to be useful for my needs.

I stumbled into the realization that I don’t have to master 802.15.4 and a large set of XBee commands to make a very simple but potentially useful network.  It’s a very basic observation about all radio devices like the XBee.  You see, at its core the XBee radio is  a modem.  It encodes digital information, transmits its digits via electromagnetism, within a specific frequency band, to be received by another XBee, and  then converted back to digital information.  The use of packet data, the 802.15.4 protocol, and all the AT commands are layers on top of the XBee’s  modem capability.  The modem, the core communications sub-component, is a serial communications device with a Universal Asynchronous Receiver/Transmitter (UART) as examined in an earlier blog.  So why not we just treat the XBee radio as a simple serial communication device?  Drop the idea of packetized data and 802.15.4 protocol and just do raw serial communications.

While this simplification is seductive, it does come at a price. Data is packetized and transmitted using a protocol for very good reasons.  In data transmission you must consider the fact that data could get corrupted, you need to share the communication channel with others,  data streams may be long (if not endless) and need to be properly sequenced, communications is main between specific devices as apposed to just broadcasting, and many other concerns.  You give up much of this by doing raw serial communications but you gain simplicity.

What I plan to do here is list some simple, proof of concept programs that I used to create a network with a Arduino and Raspberry Pi (RPi)  using XBee radios.  You could simply add additional devices, using the same code, and it will become a fully interconnected network (i.e. where every device can talk to every other devices directly).  While inferior to a 802.15.4 network on many levels, its quick to get operational and easy to debug.  Also keep in mind that this is built on the XBee radio,  but you could do this with most any radio which supports serial communications.

Architecture

I’ll be using a Arduino and a RPis for for my network, each with a XBee radio thought which they can communicate. I’ll establish terminal interface into each device so I can enter text for the device to transmit and the terminal will also show what messages where revived. All  terminals will be within windows on my PC using PuTTY, Xterm, or the Arduino’s serial monitor screen.

Initializing the XBee Radios

First step is to make sure all the XBee radios that will be part of your network are properly configured.  Specifically, you need to make sure the PAN ID and Channel ID of the XBee radio’s are identical.  To accomplish this, I used the XBeeTerm.py utility I posted in my earlier blog titled Configuration Utilities for XBee Radios.  I’m going to setup my network with two XBee radios (but you can use as many as you wish) and I used the configuration file below on both radios:

# To remove comments, white spaces, and blank lines, use the following:
#		sed '/^#/d; s/\([^$]\)#.*/\1/' Modem-Device.txt | sed 's/[ \t]*$//' > modemd.txt
# Run this script to configure the XBee radio using the following:
#		./XBeeTerm.py modemd.txt
#
baudrate 9600		# (XBeeTerm command) set the baudrate used to comm. with the XBee
serial /dev/ttyUSB0	# (XBeeTerm command) serial device which has the XBee radio
+++ 			# (XBee command) enter AT command mode on the XBee
ATRE			# (XBee command) restore XBee to factory settings
ATID B000		# (XBee command) Set the PAN ID to eight byte hex (all XBee's must have this same value)
ATCH 0E			# (XBee command) set the Channel ID to a four byte hex (all XBee's must have same value)
ATPL 0			# (XBee command) power level at which the RF module transmits (0 lowest / 4 highest)
ATWR			# (XBee command) write all the changes to the XBee non-volatile memory
ATFR			# (XBee command) reboot XBee radio
exit			# (XBeeTerm command) exit python shell

Arduino Configuration

The sketch on the Arduino is very simple. Called XBeeModem.ino and is listed blow:

/*
    The XBee devise should be connected to the Arduino Uno in the following way:
        XBee RX is connected to Arduino TX pin 3
        XBee TX is connected to Ardunio RX pin 2
        XBee +5V and Ground pins connect to the same on the Arduino
 */

#define RXPIN 2
#define TXPIN 3
#define BAUDRATE 9600

#include

SoftwareSerial XBeeSerial =  SoftwareSerial(RXPIN, TXPIN);

void setup()
{
    pinMode(13, OUTPUT);

    // Set the data rate for the hardware Serial port
    // and post a message stating so on the Arduino's Serial Monitor.
    Serial.begin(BAUDRATE);
    Serial.println("Arduino #1 up and running.");

    // Set the data rate for the SoftwareSerial port and
    // send a message out stating so via the XBee to the other devices.
    XBeeSerial.begin(BAUDRATE);
    XBeeSerial.println("Arduino #1 up and running.");
}

void loop()
{
    char c;

    // Read data arriving from the XBee and send to Arduino Serial Monitor.
    if (XBeeSerial.available()) {
        Serial.print((char)XBeeSerial.read());
    }

    // Capture data typed at the Arduino Serial Monitor, echo the data to the Serial Monitor,
    // and send that data via the XBee.
    if (Serial.available()) {
        c = (char)Serial.read();
        Serial.print(c);
        XBeeSerial.print(c);
    }

    delay(100);
}

Raspberry Pi Configuration

The Python program on the RPi is also very simple, except for one point.  Linux I/O reads will block if there are no characters to read.  You must “turn-off” blocking.  The program is called XBeeModem.py and is listed blow:

#!/usr/bin/env python

"""XBeeModem.py bypasses the XBee's 802.15.4 capabilities and simply uses it modem for communications

    You don't have to master 802.15.4 and a large set of XBee commands
    to make a very simple but potentially useful network.  At its core,
    the XBee radio is  a modem and you can use it directly for simple serial communications.

    Reference Materials:
        Non-blocking read from stdin in python - http://repolinux.wordpress.com/2012/10/09/non-blocking-read-from-stdin-in-python/
        Non-blocking read on a subprocess.PIPE in python - http://stackoverflow.com/questions/375427/non-blocking-read-on-a-subprocess-pipe-in-python

    Originally Created By:
        Jeff Irland (jeff.irland@gmail.com) in March 2013
"""

# imported modules
import os                   # portable way of using operating system dependent functionality
import sys                  # provides access to some variables used or maintained by the interpreter
import time                 # provides various time-related functions
import fcntl                # performs file control and I/O control on file descriptors
import serial               # encapsulates the access for the serial port
from pretty import switchColor, printc  # provides colored text for xterm & VT100 type terminals using ANSI escape sequences

# text colors to be used during terminal sessions
ERROR_TEXT = 'bright red'
CMD_INPUT_TEXT = 'normal'
CMD_OUTPUT_TEXT = 'bright yellow'
TERM_OUTPUT_TEXT = 'purple'
TERM_INPUT_TEXT = 'bright purple'

if __name__ == '__main__':
    serial = serial.Serial()
    serial.port = '/dev/ttyUSB0'
    serial.baudrate = 9600
    serial.timeout = 1
    serial.writeTimeout = 1
    serial.open()

    # make stdin a non-blocking file
    fcntl.fcntl(sys.stdin, fcntl.F_SETFL, os.O_NONBLOCK)

    # post startup message to other XBee's and at stdout
    serial.writelines("RPi #1 is up and running.\r\n")
    print "RPi #1 is up and running."

    switchColor(CMD_OUTPUT_TEXT)
    print "Entering loop to read and print messages (Ctrl-C to abort)..."

    try:
        while True:
            # read a line from XBee and convert it from b'xxx\r\n' to xxx and print at stdout
            switchColor(TERM_OUTPUT_TEXT)
            line = serial.readline().decode('utf-8')
            if line:
                print line

            # read data from the keyboard (i.e. stdin) and send via the XBee modem
            switchColor(TERM_INPUT_TEXT)
            try:
                line = sys.stdin.readline()
                serial.writelines(line)
            except IOError:
                time.sleep(0.1)
                continue

    except KeyboardInterrupt:
        printc("\n*** Ctrl-C keyboard interrupt ***", ERROR_TEXT)
        serial.writelines("RPi #1 is going down.\r\n")

    finally:
        switchColor(CMD_INPUT_TEXT)

Closing

It doesn’t get much simpler than this. With a little work, you might make something useful out of this technique but its very limited in the types of problems that it could handle. Never the less, it was a good diversion for me to clear my mind. Now back to the XBee’s core capabilites, the 802.15.4 protocol, and the other minutia!

Configuration Utilities for XBee Radios

My ultimate aim is to wirelessly network several Arduino based platforms with a centralized Raspberry Pi controller. There is much for me to learn to get this operational, not the least of which is the radio device I plan to use, the Xbee.  To get up to speed on the Xbee, I found the tutorials at AdafruitSparkfun, and Parallax helpful.   More detailed references are listed at the end of this post, but the very first challenge is to configure the XBee radios for operation.  This post provides insight on how this can be done, and my main mission, create a few simple utilities that make that job easy.

Xbee Radios

I purchased two XBee Series 1 Module (Freescale 802.15.4 firmware) from Adafruit.  These are manufactured by Digi and are low-power module with wire antenna  (XB24-AWI-001).  They have a 250 kbps RF data rates and operate at 2.4 GHz.  These radios use the IEEE 802.15.4 networking protocol and can perform point-to-multi-point or peer-to-peer networking , but as configured here, they do not mesh.  The Digi models that handle meshing are Digimesh, ZNet2.5 and Zigbee (ZB).  Digimesh is a version of firmware that runs on Series 1 hardware. So, if you choose to, you can upgrade these modules to Digimesh firmware to get meshing.

Xbee Adapter Board

Along with the XBee radios, I purchased adapter boards designed to make it easier to work with the radios. The adopter provides on-board 3.3V regulator power from a 5 volt source, voltage level shifting circuitry so you can connect  5V circuitry to the XBee, commonly used pins are brought out along the edge (making it easy to breadboard), and engineered to be interface via FTDI cable to a computer via USB.  The image and the text below describe the pin-out for the Adafruit  XBee Adapter:

Adafruit Xbee Adapter Pinout

    1. 3V pin – This is either an input power pin (if 5V is not provided) or an output from the 250mA regulator if 5V is provided
    2. DTR – “Data terminal ready”  is a flow control pin used to tell the XBee that the microcontroller or computer host is ready to communicate.
    3. RST – “Reset”  pin can be used to reset the XBee.  By default it is pulled high by the 10K resistor under the module. To reset, pull this pin low.’
    4. Ground – common ground for power and signal
    5. CTS – “Clear to Send” this is a flow control pin that can be used to determine if there is data in the XBee input buffer ready to be read
    6. 5V – This is the power input pin into the 3.3V regulator. Provide up to 6V that will be linearly converted into 3.3V
    7. RX – “Receive Data” is the XBee’s serial recieve pin. Serial data is sent on this pin into the XBee to be transmitted wirelessly
    8. TX – “Transmit Data” is the XBee’s serial transmit pin. Serial data is sent on this pin out of the XBee, after it has been transmitted wirelessly from another module
    9. RTS – “Ready to Send” is a flow control pin that can be used to tell the XBee to signal that the computer or microcontroller needs a break from reading serial data.
    10. see pin #1

The DTR, RTS, RST and RX pins (going into the XBee) pass through a level converter chip that brings the levels to 3.3V. Adafruit claims you can use pretty much anywhere between 2.7 to 5.5V data to communicate with the XBee. The breakout pins on the bottom of the board are not level shifted and you should try to keep data going directly into the XBee pin under 3.3V

Xbee radio installed in a XBee Adapter with the USB FTDI TTL-232 Cable attached

XBee Initial Configuration and Testing

You need a way to communicate withe the Xbee, via it adapter,  to set it up.  This can be done via Adafruit’s  USB FTDI TTL-232 Cable, and the Digi X-CTU serial terminal program.  By the way, the X-CTU user guide describes the many more things it can do beyond the configuration shown here.

    1. Plug in the USB FTDI TTL-232 Cable into a PC USB port.  If drivers are not installed automatically (it didn’t for me), follow the steps at the FTDI site.
    2. Download the X-CTU, double click on the executable file, and follow the instructions to install the program.
    3. Now connect the USB FTDI TTL-232 Cable to the Xbee Adapter as shown in the picture to the right and insert the USB end of the cable to you PC.  Start the X-CTU.
    4. To connect, configure and upgrading the Xbee, follow the Adafruit instructions for the Xbee Adapter board. Note that if you follow the instructions (I didn’t – I kept it at 9600 baud), the modem’s serial interface is now set to 19,200 baud, not the default 9600 used by X-CTU.  Remember this next time you use X-CTU with this Xbee.
    5. If your instructed by X-CTU to reset the Xbee, you can do this by shorting the reset pin, RST pin,  to ground.

The configuration can be touchy, it can go badly, or not at all.  In my case, I seem to have one Xbee Adapter that can reliably perform a firmware upgrade but the other one took some time due to a lose fitting between the Adaptor and  Xbee.  If you run into configuration problems, check out these sites: Using XCTU to Invoke the BootloaderThe Unofficial XBee FAQ,  How to recover from a failed firmware upgrade.

Quickly Getting the Xbee’s Communicating

The next step for me was just do a basic test of getting two XBee device communicating with each other. This is just a sanity test to see evidence of communication between the devices. Basically, I just followed the instructions provided by Adafruit.
simple test

    1. Using the X-CTU, set the PAN ID to the same value on the two Xbee’s.
    2. Select an Ardunio that has been programmed to send repeated brief messages to its serial port.  I used the standard LED Blinking sketch but put in some write statements in the loop.
    3. Using an Arduino and breadboard, connect +5V and ground to provide power. Make sure the XBee’s LED is blinking.
    4. Connect the RX line (input) of the XBee to the TX line (output) of the Arduino. Connect the RX line (input) of the Arduino to the TX line (output) of the Xbee. Plug the Arduino into your PC’s serial port.
    5. Now take the second Xbee and connect the  USB FTDI TTL-232 Cable to the Xbee and the PC.  The cable is doing nothing but appling power to the Xbee.
    6. Now you should see the receive LED periodically light on the USB FTDI TTL-232 Cable tethered Xbee.
    7. You now got proof that the two Xbee’s are communicating.  The Arduino connected Xbee is sending data to its serial port and the USB FTDI TTL-232 Cable tethered Xbee is receiving it.

Above you’ll find a picture of the configuration, and below is the Arduino sketch I used.

/*
 *  Xbee Test via Blink LED
 *
 *Turns on an LED on for one second, then off for one second, repeatedly.
 *Also increase brigthness of analog LED.
 *
 *The circuit:
 * LED1 connected from digital pin 13 to ground.
 * LED2 connected from analog pin 9 to ground.
 * Note: On most Arduino boards, there is already an LED on the board
 * connected to pin 13, so you don't need any extra components for this example.

 *Created 1 June 2005
 *By David Cuartielles
 *http://arduino.cc/en/Tutorial/Blink
 *based on an orginal by H. Barragan for the Wiring i/o board
 *Modified by Jeff Irland in December 2012
 */

int ledPin1 =  13;    // LED connected to digital pin 13
int ledPin2 =  9;     // LED connected to analog pin 9
int brightness = 0;

// The setup() method runs once, when the sketch starts
void setup()   {
    Serial.begin(9600);
    pinMode(ledPin1, OUTPUT);     // initialize the digital pin as an output
    Serial.println("Arduino done with setup()");
}

// the loop() method runs over and over again,
// as long as the Arduino has power
void loop()
{
    digitalWrite(ledPin1, HIGH);   // set the LED on
    Serial.println("LED set HIGH.");
    delay(1000);                   // wait for a second

    digitalWrite(ledPin1, LOW);    // set the LED off
    Serial.println("LED set LOW.");
    delay(1000);                   // wait for a second

    brightness = brightness + 5;
    analogWrite(ledPin2, brightness);
    Serial.println("LED brightness increased.");
}

Installing XBee Python Tools for the RPi

While the MS Windows based Digi X-CTU tool is just fine, I want to use the RPi’s and Python to access the XBee serial communication API, and its advanced features, for one or more XBee devices.  I prefer simple utilities, that can be scripted within the Linux shell.  Call me a Linux snob if you wish, but I don’t care for MS Windows!

In my post “Selecting XBee Radios and Supporting Software Tools“, I referenced a Python package that could be used to create my utilitiesd, call python-xbee, and I will be using it here. It claims to provides a semi-complete implementation of the XBee binary API protocol and allows a developer to send and receive the information they desire without dealing with the raw communication details. It also claims the  library is compatible with both XBee 802.15.4 (Series 1) and XBee ZigBee (Series 2) modules, normal and PRO.

First, we need to load some additional required Python Packages, that being pySerial and Nose. pySerial extends python’s capabilities to include interacting with a serial port and Nose is a package providing a very easy way to build tests, based on the Python class unittest.  (Don’t let this all scare you away, these are necessary but your not going to use them directly).  To load these package:

sudo pip install pySerial
sudo pip install nose

Download the python-xbee tools from Google Code or Python Org and place them into the RPi’s $HOME/src.  The README file provides installation instructions.  It states that the following command automatically test and install the package for you:

sudo python setup.py install

There is a simple to use RPi platform tool that I have modified for my needs, that is a XBee serial command shell for interacting with XBee radios.  It performs the core functions of the official configuration tool, X-CTU, which only runs on Windows. (There happens to be a cross-platform version of X-CTU called moltosenso Network Manager but I don’t need all this horse power.)  I’ll use this X-CTU-alternative to configure the individual XBee radios.  With the X-CTU, you can update firmware, etc. but most of the time you need the program to do simple configuration tasks. You could use Linux’s minicom, but I prefer a simpler tool which can be scripted so I can configure several XBee radios identically.  I found much of what I wanted in an existing Python XBee tools for configuration.  I made some modification/improvements, I call it the XBeeTerm, and its listed below:


#!/usr/bin/env python

"""XBeeTerm.py is a XBee serial command shell for interacting with XBee radios

	This command interpretors establishes communications with XBee radios so that AT Commands can be sent to the XBee.
	The interpretors output is color coded to help distinguish user input, from XBee radio output, and from
	interpretors output. This command-line interpretor uses Python modual Cmd, and therefore, inherit bash-like history-list
	editing (e.g. Control-P or up-arrow scrolls back to the last command, Control-N or down-arrow forward to the next one,
	Control-F or right-arrow moves the cursor to the right non-destructively, Control-B or left-arrow moves the cursor
	to the left non-destructively, etc.).

	XBeeTerm is not a replacement for the Digi X-CTU program but a utility program for the Linux envirnment.  You can pipe
	scripts of XBee configration commands, making it easy to multiple radios.  Also, XBeeTerm wait for the arrival of a
	XBee data packet, print the XBee frame, and wait for the next packet, much like a packet sniffer.

	XBeeTerm Commands:
		baudrate <rate>		set the baud rate at which you will communicate with the XBee radio
		serial <device>		set the serial device that the XBee radio is attached
		watch				wait for the arrival of a XBee data packet, print it, wait for the next
		shell or !			pause the interpreter and invoke command in Linux shell
		exit or EOF			exit the XBeeTerm
		help or ?			prints out short discription of the commands (similar to the above)

	Just like the Digi X-CTU program, the syntax for the AT commands are:
		AT+ASCII_Command+Space+Optional_Parameter+Carriage_Return
		Example: ATDL 1F<CR>

	Example Session:
		baudrate 9600			# (XBeeTerm command) set the baudrate used to comm. with the XBee
		serial /dev/ttyUSB0		# (XBeeTerm command) serial device which has the XBee radio
		+++ 					# (XBee command) enter AT command mode on the XBee
		ATRE					# (XBee command) restore XBee to factory settings
		ATAP 2					# (XBee command) enable API mode with escaped control characters
		ATCE 0					# (XBee command) make this XBee radio an end device
		ATMY AAA1				# (XBee command) set the address of this radio to eight byte hex
		ATID B000				# (XBee command) Set the PAN ID to eight byte hex
		ATCH 0E					# (XBee command) set the Channel ID to a four byte hex
		ATPL 0					# (XBee command) power level at which the RF module transmits
		ATWR					# (XBee command) write all the changes to the XBee non-volatile memory
		ATFR					# (XBee command) reboot XBee radio
		exit					# (XBeeTerm command) exit python shell

	Referance Materials:
		XBee 802.15.4 (Series 1) Module Product Manual (section 3: RF Module Configuration)
			ftp://ftp1.digi.com/support/documentation/90000982_A.pdf
		python-xbee Documentation: Release 2.0.0, Paul Malmsten, December 29, 2010
			
			

Click to access XBee-2.0.0-Documentation.pdf

cmd - Support for line-oriented command interpreters http://docs.python.org/2/library/cmd.html cmd - Create line-oriented command processors http://bip.weizmann.ac.il/course/python/PyMOTW/PyMOTW/docs/cmd/index.html Easy command-line applications with cmd and cmd2 http://pyvideo.org/video/306/pycon-2010--easy-command-line-applications-with-c Orginally Created By: Amit Snyderman (amit@amitsnyderman.com), on/about August 2012, and taken from https://github.com/sensestage/xbee-tools Modified By: Jeff Irland (jeff.irland@gmail.com) in January 2013 """ # imported modules import os # portable way of using operating system dependent functionality import sys # provides access to some variables used or maintained by the interpreter import time # provides various time-related functions import cmd # provides a simple framework for writing line-oriented command interpreters import serial # encapsulates the access for the serial port import argparse # provides easy to write and user-friendly command-line interfaces from xbee import XBee # implementation of the XBee serial communication API from pretty import switchColor # colored text in Python using ANSI Escape Sequences # authorship information __author__ = "Jeff Irland" __copyright__ = "Copyright 2013" __credits__ = "Amit Snyderman, Marije Baalman, Paul Malmsten" __license__ = "GNU General Public License" __version__ = "0.1" __maintainer__ = "Jeff Irland" __email__ = "jeff.irland@gmail.com" __status__ = "Development" __python__ = "Version 2.7.3" # text colors to be used during terminal sessions CMD_INPUT_TEXT = 'normal' CMD_OUTPUT_TEXT = 'bright yellow' XBEE_OUTPUT_TEXT = 'bright red' SHELL_OUTPUT_TEXT = 'bright cyan' WATCH_OUTPUT_TEXT = 'bright green' class ArgsParser(): """Within this object class you should load all the command-line switches, parameters, and arguments to operate this utility""" def __init__(self): self.parser = argparse.ArgumentParser(description="This command interpretors establishes communications with XBee radios so that AT Commands can be sent to the XBee. It can be used to configure or query the XBee radio", epilog="This utility is primarily intended to change the AT Command parameter values, but could be used to query for the parameter values.") self.optSwitches() self.reqSwitches() self.optParameters() self.reqParameters() self.optArguments() self.reqArguments() def optSwitches(self): """optonal switches for the command-line""" self.parser.add_argument("--version", action="version", version=__version__, help="print version number on stdout and exit") self.parser.add_argument("-v", "--verbose", action="count", help="produce verbose output for debugging") def reqSwitches(self): """required switches for the command-line""" pass def optParameters(self): """optonal parameters for the command-line""" pass def reqParameters(self): """required parameters for the command-line""" pass def optArguments(self): """optonal arguments for the command-line""" self.parser.add_argument(nargs="*", action="store", dest="inputs", default=None, help="XBeeTerm script file with AT Commands to be executed") def reqArguments(self): """required arguments for the command-line""" pass def args(self): """return a object containing the command-line switches, parameters, and arguments""" return self.parser.parse_args() class XBeeShell(cmd.Cmd): def __init__(self, inputFile=None): """Called when the objects instance is created""" cmd.Cmd.__init__(self) self.serial = serial.Serial() if inputFile is None: self.intro = "Command-Line Interpreter for Configuring XBee Radios" self.prompt = "xbee% " else: self.intro = "Configuring XBee Radios via command file" self.prompt = "" # Do not show a prompt after each command read sys.stdin = inputFile def default(self, p): """Command is assumed to be an AT Commands for the XBee radio""" if not self.serial.isOpen(): print "You must set a serial port first." else: if p == '+++': self.serial.write('+++') time.sleep(2) else: self.serial.write('%s\r' % p) time.sleep(0.5) output = '' while self.serial.inWaiting(): output += self.serial.read() if output == '' : print 'XBee timed out, so reissue "+++". (Or maybe XBee doesn\'t understand "%s".)' % p else: switchColor(XBEE_OUTPUT_TEXT) print output.replace('\r', '\n').rstrip() def emptyline(self): """method called when an empty line is entered in response to the prompt""" return None # do not repeat the last nonempty command entered def precmd(self, p): """executed just before the command line line is interpreted""" switchColor(CMD_OUTPUT_TEXT) return cmd.Cmd.precmd(self, p) def postcmd(self, stop, p): """executed just after a command dispatch is finished""" switchColor(CMD_INPUT_TEXT) return cmd.Cmd.postcmd(self, stop, p) def do_baudrate(self, p): """Set the baud rate used to communicate with the XBee""" self.serial.baudrate = p print 'baudrate set to %s' % self.serial.baudrate def do_serial(self, p): """Linux serial device path to the XBee radio (e.g. /dev/ttyUSB0)""" try: self.serial.port = p self.serial.open() print 'Successfully opened serial port %s' % p except Exception, e: print 'Unable to open serial port %s' % p def do_shell(self, p): """Pause the interpreter and invoke command in Linux shell""" print "running shell command: ", p switchColor(SHELL_OUTPUT_TEXT) print os.popen(p).read() def do_watch(self, p): """Wait for the arrival of a XBee data packet, print it when it arrives, wait for the next""" if not self.serial.isOpen(): print "You must set a serial port first." else: print "Entering watch mode..." switchColor(WATCH_OUTPUT_TEXT) while 1: packet = xbee.find_packet(self.serial) if packet: xb = xbee(packet) print xb def do_exit(self, p): """Exits from the XBee serial terminal""" self.serial.close() print "Exiting", os.path.basename(__file__) return True def do_EOF(self, p): """EOF (end-of-file) or Ctrl-D will return True and drops out of the interpreter""" self.serial.close() print "Exiting", os.path.basename(__file__) return True def help_help(self) : """Print help messages for command arguments""" print 'help\t\t', self.help_help.__doc__ print 'shell <cmd>\t', self.do_shell.__doc__ print 'EOF or Ctrl-D\t', self.do_EOF.__doc__ print 'exit\t\t', self.do_exit.__doc__ print 'watch\t\t', self.do_watch.__doc__ print 'serial <dev>\t', self.do_serial.__doc__ print 'baudrate <rate>', self.do_baudrate.__doc__ # Enter into XBee command-line processor if __name__ == '__main__': # parse the command-line for switches, parameters, and arguments parser = ArgsParser() # create parser object for the command-line args = parser.args() # get list of command line arguments, parameters, and switches if args.verbose > 0: # print what is on the command-line print os.path.basename(__file__), "command-line arguments =", args.__dict__ # process the command-line arguments (i.e. script file) and start the command shell if len(args.inputs) == 0: # there is no script file shell= XBeeShell() shell.cmdloop() else: # there is a script file on the command-line if len(args.inputs) > 1: print os.path.basename(__file__), "will process only the first command-line argument." if os.path.exists(args.inputs[0]) : inputFile = open(args.inputs[0], 'rt') shell = XBeeShell(inputFile) shell.cmdloop() else: print 'File "%s" doesn\'t exist. Program terminated.' % args.inputs[0]

The XBeeTerm.py module imports functions from the pretty.py package, specifically to colorize the output for xterm on the Raspberry Pi.  This package is provided here:

#!/usr/bin/env python

"""pretty.py will color text for Xterm/VT100 type terminals using ANSI Escape Sequences

	A library that provides a Python print, stdout, and string wrapper that makes colored terminal
	text easier to use(e.g. without having to mess around with ANSI escape sequences).

	Referance Materials:
		Colored text in Python using ANSI Escape Sequences
			http://nezzen.net/2008/06/23/colored-text-in-python-using-ansi-escape-sequences/

	Orginally Created By:
		Copyright (C) 2008 Brian Nez <thedude at bri1 dot com>

	Modified By:
		Jeff Irland (jeff.irland@gmail.com) in January 2013
"""

# imported modules
import sys

# authorship information
__author__ = "Jeff Irland"
__copyright__ =	"Copyright 2013"
__credits__ = "Brian Nez"
__license__ = "GNU General Public License"
__version__ = "1.0"
__maintainer__ = "Jeff Irland"
__email__ = "jeff.irland@gmail.com"
__status__ = "Production"

# Dictionary of ANSI escape sequences for coloring text
colorCodes = {
	'black':	'0;30',		'bright gray':	'0;37',
	'blue':		'0;34',		'white':		'1;37',
	'green':	'0;32',		'bright blue':	'1;34',
	'cyan':		'0;36',		'bright green':	'1;32',
	'red':		'0;31',		'bright cyan':	'1;36',
	'purple':	'0;35',		'bright red':	'1;31',
	'yellow':	'0;33',		'bright purple':'1;35',
	'dark gray':'1;30',		'bright yellow':'1;33',
	'normal':	'0'
}

def printc(text, color):
	"""Print in color"""
	print "\033["+colorCodes[color]+"m"+text+"\033[0m"

def writec(text, color):
	"""Write to stdout in color"""
	sys.stdout.write("\033["+colorCodes[color]+"m"+text+"\033[0m")

def switchColor(color):
	"""Switch terminal color"""
	sys.stdout.write("\033["+colorCodes[color]+"m")

def stringc(text, color):
	"""Return a string with ANSI escape sequences to color text"""
	return "\033["+colorCodes[color]+"m"+text+"\033[0m"

# Simple test routine to validate thing are working correctly
if __name__ == '__main__':
	printc("Welcome to the pretty.py test routine!", 'white')

	printc("I will now try to print a line of text in each color using \"writec()\"", 'white')
	for color in colorCodes.keys():
		writec("Hello, world!", color)
		print "\t", color

	printc("\n\nI will now try to print a line of text in each color using \"switchColor()\"", 'white')
	for color in colorCodes.keys():
		switchColor(color)
		print 'Hello World #2!'

	printc("\n\nI will now try to print a line of text in each color using \"printc()\"", 'white')
	for color in colorCodes.keys():
		printc('Hello World #3!', color)

	printc("\n\nI will now try to print a line of text in each color using \"stringc()\"", 'white')
	for color in colorCodes.keys():
		print stringc('Hello World #4!', color)

Identifying the RPi USB device used by the XBee

Since the python-xbee library wants to talk to the via a Linux serial devices, I’m using the USB FTDI TTL-232 Cable (FTDI is the USB chip manufacturer) used in the XBee configuration step done earlier.  I connected the cable to the RPi USB port  and then we need to find the serial tty the cable is associated with.  To do this, it takes a bit of detective work. Run the commands:

lsusb
dmesg | grep Manufacturer
dmesg | grep FTDI

A better command might be (but I’m not sure it will work every time):

dmesg | grep -i usb | grep -i tty

The interpretation of the output tells us the cable is attached to serial device /dev/ttyUSB0.  See the output below.

best use of dmesg

Another possibility is to use udevadm to gather information about specific devices but I never figured out exactly how to use it to answer my question.  Python also has a package called PyUSB that might provide some help, but also here you’ll still need the vendor and product identification information.

Chances are that when you plug the cable into the same USB port the next time, it will default to the same tty but there is no certainty.  To assign a permanent tty name to the device, and never do any of this again, check out Persistent names for usb-serial devices.

Configuring the XBee Radios for API Mode

The configuration and testing of the XBee’s done earlier was done in AT Command mode (Transparent Mode). In AT mode, everything sent to the RX line of the XBee radio will be sent out via the antenna, and all the incoming data from antenna will go to the XBee’s TX line.  This is why we could check the sanity of the XBee radios in the earlier section, XBee Initial Configuration and Testing using a simple Arduino sketch.  We sent junk to the XBee and it transmitted it!

Now we’ll configure two XBee radios (with a Coordinator and a single End Device) to form a network using API Mode.  In API Mode, XBee won’t send out anything until it received the correct form of commands from the serial interface.  The XBee AT Command Set (page 27), specifically the  ATAP 2 command, allows you to configure the XBee radio for API Mode.   So why API Mode, consider the following:

    • When sending a packet, the transmitting radio receives an ACK, indicating the packet was successfully delivered. The transmitting radio will resend the packet if it does not receive an ACK.
    • Receive packets (RX), contain the source address of transmitting radio
    • You can configure a remote radio with the Remote AT feature
    • Easily address multiple radios and send broadcast TX packets
    • Receive I/O data from 1 or more remote XBees
    • Obtain RSSI (signal strength) of an RX packet
    • Packets include a checksum for data integrity

The XBeeTerm utility will  easily configure the XBee radios for API mode and set the appropriate network parameters.  To get a deeper appreciation of configuring the XBee radios, see the References at the end.  For here, I’ll just run through the steps using the XBeeTerm.py tool and the configuration commands used, documented in file scripts.

Coordinator Configuration File: Config-Coordinator.txt

# To remove comments, white spaces, and blank lines, use the following:
#		sed '/^#/d; s/\([^$]\)#.*/\1/' Config-Coordinator.txt | sed 's/[ \t]*$//' > coord.txt
# Run this script to configure the XBee radio using the following:
#		python XBeeTerm.py coord.txt
#
baudrate 9600			# (XBeeTerm command) set the baudrate used to comm. with the XBee
serial /dev/ttyUSB0		# (XBeeTerm command) serial device which has the XBee radio
+++ 					# (XBee command) enter AT command mode on the XBee
ATRE					# (XBee command) restore XBee to factory settings
ATAP 2					# (XBee command) enable API mode with escaped control characters
ATCE 1					# (XBee command) make this XBee radio the network coordinator
ATMY AAA0				# (XBee command) set the address of this radio to eight byte hex (must be unique)
ATID B000				# (XBee command) Set the PAN ID to eight byte hex (all XBee's must have this same value)
ATCH 0E					# (XBee command) set the Channel ID to a four byte hex (all XBee's must have same value)
ATPL 0					# (XBee command) power level at which the RF module transmits (0 lowest / 4 highest)
ATWR					# (XBee command) write all the changes to the XBee non-volatile memory
ATFR					# (XBee command) reboot XBee radio
exit					# (XBeeTerm command) exit python shell

End Device Configuration File: Config-End-Device.txt

# To remove comments, white spaces, and blank lines, use the following:
#		sed '/^#/d; s/\([^$]\)#.*/\1/' Config-End-Device.txt | sed 's/[ \t]*$//' > endd.txt
# Run this script to configure the XBee radio using the following:
#		python XBeeTerm.py endd.txt
#
baudrate 9600			# (XBeeTerm command) set the baudrate used to comm. with the XBee
serial /dev/ttyUSB0		# (XBeeTerm command) serial device which has the XBee radio
+++ 					# (XBee command) enter AT command mode on the XBee
ATRE					# (XBee command) restore XBee to factory settings
ATAP 2					# (XBee command) enable API mode with escaped control characters
ATCE 0					# (XBee command) make this XBee radio an end device
ATMY AAA1				# (XBee command) set the address of this radio to eight byte hex (must be unique)
ATID B000				# (XBee command) Set the PAN ID to eight byte hex (all XBee's must have this same value)
ATCH 0E					# (XBee command) set the Channel ID to a four byte hex (all XBee's must have same value)
ATPL 0					# (XBee command) power level at which the RF module transmits (0 lowest / 4 highest)
ATWR					# (XBee command) write all the changes to the XBee non-volatile memory
ATFR					# (XBee command) reboot XBee radio
exit					# (XBeeTerm command) exit python shell

As they stand right now, these files could not be processed by XBeeTerm.py because of the comments (included to make the contents understandable).  To clean this up, the command sed '/^#/d; s/\([^$]\)#.*/\1/'will remove all shell type comments from a file and sed 's/[ \t]*$//'will remove unneeded white space.  Putting this all together and you can use this to prepare the above files for XBeeTerm.py:

sed '/^#/d; s/\([^$]\)#.*/\1/' Config-Coordinator.txt | sed 's/[ \t]*$//' > coord.txt
sed '/^#/d; s/\([^$]\)#.*/\1/' Config-End-Device.txt | sed 's/[ \t]*$//' > endd.txt

Now execute the following python XBeeTerm.py coord.txt and you get the output below:

XBeeTerm Script

The yellow text is responses back from the XBee serial terminal and the red text is from the XBee radio itself.  Since all the red text is “OK”, all the commands took and the XBee radio is now configured as a Coordinator.  Now repeat this for the End Device XBee radio.

In this example, I have one End Device but what if you have multiple devices, do you need a Config-End-Device.txt file for each end device?  The only change within the configuration file is the radio’s address, which is established via the ATMY command.  Here is a trick to avoid the need for multiple files.  First, configure all your End Devices using the configuration file.  Then, for each radio, modify the ATMY use the following:

echo -e "baudrate 9600\nserial /dev/ttyUSB0\n+++\nATMY AAA1\nATWR\nATFR\nexit" | python XBeeTerm.py

but for each End Device radio, increment the ATMY address by one (e.g. AAA2, AAA3, …).

Querying XBee for Configuration

Now that we believe the XBee radios are properly configured, lets verify that by query the radios.  You could use XBeeTerm to perform this function by including only the AT Command without the parameter but I wanted a more informative tool. For this, I have created another utility that can take a list of AT Commands as arguments and query the XBee radio for the AT’s parameter value.  This utility, call XBeeQuery.py, is listed below:


#! /usr/bin/python

"""
	This utility will query a XBee radio for some of it's AT Command parameters and print their values, as well as
	optional discriptive information.  It has a set of default AT Commands or the use can provide the desired set
	of AT Commands on the command-line.

	The dictionay of AT Command descriptive information is limited but can be easily expanded.  The descriptive
	information was taken from the first referance given below. Also note that if this utility appears to hang,
	it is almost certainly waiting on a response from the XBee. To continue processing the AT Command list, use Ctrl-C.

	Reference Materials:
		XBee/XBee-PRO OEM RF Modules: Product Manual v1.xCx - 802.15.4 Protocol
			ftp://ftp1.digi.com/support/documentation/90000982_A.pdf
		python-xbee Documentation: Release 2.0.0, Paul Malmsten, December 29, 2010
			
			

Click to access XBee-2.0.0-Documentation.pdf

Parser for command-line options, arguments and sub-commands http://docs.python.org/2/library/argparse.html#module-argparse """ # imported modules import os # portable way of using operating system dependent functionality import sys # provides access to some variables used or maintained by the Python interpreter import serial # encapsulates the access for the serial port import argparse # provides easy to write and user-friendly command-line interfaces from xbee import XBee # implementation of the XBee serial communication API from pretty import stringc # provides colored text for xterm and VT100 type terminals using ANSI Escape Sequences # authorship information __author__ = "Jeff Irland" __copyright__ = "Copyright 2013" __credits__ = "Paul Malmsten" __license__ = "GNU General Public License" __version__ = "0.1" __maintainer__ = "Jeff Irland" __email__ = "jeff.irland@gmail.com" __status__ = "Development" __python__ = "Version 2.7.3" # text colors to be used during terminal sessions NORMAL_TEXT = 'normal' CMD_TEXT = 'bright red' NAME_TEXT = 'bright yellow' CAT_TEXT = 'bright yellow' DESC_TEXT = 'normal' RANGE_TEXT = 'bright cyan' DEFAULT_TEXT = 'bright green' class ArgsParser(): """Within this object class you should load all the command-line switches, parameters, and arguments to operate this utility""" def __init__(self): self.parser = argparse.ArgumentParser(description="This utility will query a XBee radio for some of it's AT Command parameters and print their values. It has a set of default AT Commands or the use can provide the desired set of AT Commands on the command-line.", epilog="This utility is for query only and will not change the AT Command parameter values.") self.optSwitches() self.reqSwitches() self.optParameters() self.reqParameters() self.optArguments() self.reqArguments() def optSwitches(self): """optonal switches for the command-line""" self.parser.add_argument("--version", action="version", version=__version__, help="print version number on stdout and exit") self.parser.add_argument("-v", "--verbose", action="count", help="produce verbose output for debugging") self.parser.add_argument("-n", "--name", required=False, action="store_true", help="print the name (i.e. short description) of the XBee AT Command") self.parser.add_argument("-d", "--description", required=False, action="store_true", help="print the full description of the XBee AT Command") def reqSwitches(self): """required switches for the command-line""" pass def optParameters(self): """optonal parameters for the command-line""" self.parser.add_argument("-b", "--baudrate", required=False, action="store", metavar="RATE", type=int, default=9600, help="baud rate used to communicate with the XBee radio") self.parser.add_argument("-p", "--device", required=False, action="store", metavar="DEV", type=str, default='/dev/ttyUSB0', help="open this serial port or device to communicate with the XBee radio") def reqParameters(self): """required parameters for the command-line""" pass def optArguments(self): """optonal arguments for the command-line""" self.parser.add_argument(nargs="*", action="store", dest="inputs", help="AT Commands to be queried") def reqArguments(self): """required arguments for the command-line""" pass def args(self): """return a object containing the command-line switches, parameters, and arguments""" return self.parser.parse_args() class ATDict(): """Within this object class you should load a dictionary of { "AT Command" : [ "Name", "Category", "Description", "Parameter Range", "Default Value" ] }""" # Networking & Security, RF Interfacing, Sleep Modes (NonBeacon), Serial Interfacing, I/O Settings, Diagnostics, AT Command Options def __init__(self): self.commands = { "CH" : [ "Channel", "Networking", "Set/Read the channel number used for transmitting and receiving data between RF modules.", "0x0B - 0x1A", "0x0C" ], "ID" : [ "PAN ID", "Networking", "Set/Read the PAN (Personal Area Network) ID. Use 0xFFFF to broadcast messages to all PANs.", "0 - 0xFFFF" , "0x3332" ], "DH" : [ "Destination Address High", "Networking", "Set/Read the upper 32 bits of the 64-bit destination address. When combined with DL, it defines the destination address used for transmission. To transmit using a 16-bit address, set DH parameter to zero and DL less than 0xFFFF. 0x000000000000FFFF is the broadcast address for the PAN.", "0 - 0xFFFFFFFF", "0" ], "DL" : [ "Destination Address Low", "Networking", "Set/Read the lower 32 bits of the 64-bit destination address. When combined with DH, DL defines the destination address used for transmission. To transmit using a 16-bit address, set DH parameter to zero and DL less than 0xFFFF. 0x000000000000FFFF is the broadcast address for the PAN.", "0 - 0xFFFFFFFF", "0" ], "MY" : [ "16-bit Source Address", "Networking", "Set/Read the RF module 16-bit source address. Set MY =0xFFFF to disable reception of packets with 16-bit addresses. 64-bit source address(serial number) and broadcast address (0x000000000000FFFF) is always enabled.", "0 - 0xFFFF", "0" ], "SH" : [ "Serial Number High", "Networking", "Read high 32 bits of the RF module's unique IEEE 64-bit address. 64-bit source address is always enabled.", "0 - 0xFFFFFFFF [read-only]", "Factory-set" ], "SL" : [ "Serial Number Low", "Networking", "Read low 32 bits of the RF module's unique IEEE 64-bit address. 64-bit source address is always enabled.", "0 - 0xFFFFFFFF [read-only]", "Factory-set" ], "RR" : [ "XBee Retries", "Networking", "Set/Read the maximum number of retries the module will execute in addition to the 3 retries provided by the 802.15.4 MAC. For each XBee retry, the 802.15.4 MAC can execute up to 3 retries.", "0 - 6", "0" ], "RN" : [ "Random Delay Slots", "Networking", "Set/Read the minimum value of the back-off exponent in the CSMA-CA algorithm that is used for collision avoidance. If RN = 0, collision avoidance is disabled during the first iteration of the algorithm (802.15.4 - macMinBE).", "0 - 3 [exponent]", "0" ], "MM" : [ "MAC Mode", "Networking", "Set/Read MAC Mode value. MAC Mode enables/disables the use of a Digi header in the 802.15.4 RF packet. When Modes 0 or 3 are enabled(MM=0,3), duplicate packet detection is enabled as well as certain AT commands.", "0 = Digi Mode, 1 = 802.15.4 (no ACKs), 2 = 802.15.4 (with ACKs), 3 = Digi Mode (no ACKs)", "0" ], "NI" : [ "Node Identifier", "Networking", "Stores a string identifier. The register only accepts printable ASCII data. A string can not start with a space. Carriage return ends command. Command will automatically end when maximum bytes for the string have been entered. This string is returned as part of the ND (Node Discover) command. This identifier is also used with the DN (Destination Node) command.", "20-character ASCII string", "-" ], "NT" : [ "Node Discover Time", "Networking", "Set/Read the amount of time a node will wait for responses from other nodes when using the ND (Node Discover) command.", "0x01 - 0xFC [x 100 ms]", "0x19" ], "CE" : [ "Coordinator Enable", "Networking", "Set/Read the coordinator setting. A value of 0 makes it an End Device but a value of 1 makes it a Coordinator.", "0 = End Device, 1 = Coordinator", "0" ], "SC" : [ "Scan Channels", "Networking", "Set/Read list of channels to scan for all Active and Energy Scans as a bitfield. This affects scans initiated in command mode (AS, ED) and during End Device Association and Coordinator startup", "0 - 0xFFFF [bitfield](bits 0, 14, 15 not allowed on the XBee-PRO)", "0x1FFE (all XBee-PRO Channels)" ], #"SD" : [ "Scan Duration", "Networking", "Set/Read the scan duration exponent. For End Device - Duration of Active Scan during Association. For Coordinator - If ‘ReassignPANID’ option is set on Coordinator [refer to A2 parameter], SD determines the length of time the Coordinator will scan channels to locate existing PANs. If ‘ReassignChannel’ option is set, SD determines how long the Coordinator will perform an Energy Scan to determine which channel it will operate on. ‘Scan Time’ is measured as (# of channels to scan] * (2 ^ SD) * 15.36ms). The number of channels to scan is set by the SC command. The XBee can scan up to 16 channels (SC = 0xFFFF).", "0-0x0F [exponent]", "4" ], "A1" : [ "End Device Association", "Networking", "Set/Read End Device association options. bit 0 - ReassignPanID (0 - Will only associate with Coordinator operating on PAN ID that matches module ID / 1 - May associate with Coordinator operating on any PAN ID), bit 1 - ReassignChannel(0 - Will only associate with Coordinator operating on matching CH Channel setting / 1 - May associate with Coordinator operating on any Channel), bit 2 - AutoAssociate (0 - Device will not attempt Association / 1 - Device attempts Association until success Note: This bit is used only for Non-Beacon systems. End Devices in Beacon-enabled system must always associate to a Coordinator), bit 3 - PollCoordOnPinWake (0 - Pin Wake will not poll the Coordinator for indirect (pending) data / 1 - Pin Wake will send Poll Request to Coordinator to extract any pending data), bits 4 - 7 are reserved.", "0 - 0x0F [bitfield]", "0" ], #"XX" : [ "", "", "", "", "" ], #"XX" : [ "", "", "", "", "" ], } def dictionary(self): """return the whole dictionary of command""" return self.commands def command(self, cmd): """return the colorized AT Command""" return stringc(cmd, CMD_TEXT) def name(self, cmd): """return the colorized name of the AT Command""" return stringc(self.commands[cmd][0], NAME_TEXT) def category(self, cmd): """return the colorized category of the AT Command""" return stringc(self.commands[cmd][1], CAT_TEXT) def description(self, cmd): """return the colorized description of the AT Command""" return stringc(self.commands[cmd][2], DESC_TEXT) def range(self, cmd): """return the colorized range of the AT Command""" return stringc(self.commands[cmd][3], RANGE_TEXT) def default(self, cmd): """return the colorized devault value of the AT Command""" stringc(self.commands[cmd][3], DEFAULT_TEXT) class FrameID(): """XBee frame IDs must be in the range 0x01 to 0xFF (0x00 is a special case). This object allows you to cycles through these numbers.""" def __init__(self): self.frameID = 0 def inc(self): if self.frameID == 255: self.frameID = 0 self.frameID += 1 return self.frameID def byte2hex(byteStr): """Convert a byte string to it's hex string representation""" hex = [] for aChar in byteStr: hex.append("%02X " % ord(aChar)) return ''.join(hex).strip() if __name__ == '__main__': # parse the command-line for switches, parameters, and arguments parser = ArgsParser() # create parser object for the command-line args = parser.args() # get list of command line arguments, parameters, and switches if args.verbose > 0: # print what is on the command-line print os.path.basename(__file__), "command-line arguments =", args.__dict__ # create required objects frameID = FrameID() # create a cycling frame ID sequence number to be used in XBee frames at = ATDict() # create a dictionary of XBee AT Commands definitions ser = serial.Serial(args.device, args.baudrate) # Open the serial port that has the XBee radio xbee = XBee(ser) # Create XBee object to communicate with the XBee radio # if user provided desired AT Commands, use them for query, otherwise use the whole dictionary if len(args.inputs) == 0: args.inputs = at.dictionary() # for the command list provided, query the XBee radio AT Command's parameters for cmd in args.inputs: xbee.send('at', frame_id=chr(frameID.inc()), command=cmd) try: response = xbee.wait_read_frame() if args.name: print at.command(cmd) + " = " + byte2hex(response['parameter']) + " " + at.name(cmd) else: print at.command(cmd) + " = " + byte2hex(response['parameter']) if args.description: print at.description(cmd) + "\n" except KeyboardInterrupt: print "*** AT Command \"" + at.command(cmd) + "\" interrupted. ***" if args.description: print " " ser.close()

Here is a sample output for the XBeeQuery utility:

XBeeQuery Script

References

Configuring the XBee Radios

General Documentation

Selecting XBee Radios and Supporting Software Tools

DigiMesh_networking

My ultimate aim is to wirelessly network several Arduino based platforms with a centralized Raspberry Pi controller or gateway.  There is much for me to learn to get this operational, not the least of which is the selection of the radio device platform I plan to use. After reviewing other devices, I have settled on the XBee, in part because of its popularity, its mesh capabilities, and it power management.  To get up to speed on the Xbee, I found the tutorials at AdafruitSparkfun, and Parallax helpful.   Some additional good references are listed at the end of this post.

As I did in the post Raspberry Pi Serial Communication: What, Why, and a Touch of How, I have a desire (obsessive need?) to do some extensive researching before diving into implementing a project.  What is listed below are my research findings.

XBee Series 1 vs. Series 2

Digi’s XBee website gives you a confusing set of options for selecting radios but after reviewing multiple sources, it boils down to the XBee Series 1 vs. Series 2 for the DIY type applications I would do.

    • XBee Series 1 Module (Freescale technology with 802.15.4 firmware) have a 250 kbps RF data rates and operate at 2.4 GHz.  These radios use the IEEE 802.15.4 networking protocol and can perform point-to-multi-point networking.  You can also do peer-to-peer networking (a form of mesh network) but this will require a firmware  upgrade called DigiMesh designed specifically for the Series 1 hardware.
    • XBee Series 2 Module (Ember/Silicon Labs technology with ZigBee firmware) are similar to the Series 1 in many respects but use the ZigBee standard, and  therefore, have the potential for interoperability with devices made by different vendors.

Mesh networking (topology) is a type of networking where each node must not only capture and disseminate its own data, but also may serve as a relay for other nodes, that is, it must collaborate to propagate the data in the network.  This gives the network self configuringself healingdynamic routing, and other capabilities.  Wireless mesh networks can be implemented with various wireless technology including 802.11802.15802.16, cellular technologies or combinations of more than one type.  The mesh enabling capability for these technologies is the routing protocol being used. There are many routing protocols being used by mesh networks today for many different types of products, but I will concern ourselves with just the XBee Series 1 and Series 2 products.

The Zigbee Alliance is a group of more than 300 companies who is responsible for publishing and maintaining the Zigbee specification. In the ZigBee network topology,  there are different node types in the network (Coordinator, Router, End Device). DigiMesh is a proprietary peer-to-peer networking using a simplified topology (no need to define and organize coordinators, routers or end-nodes).  Digi has a white paper that does a nice comparison of the two types of meshing products.

To further clarify the similarity/difference between Series 1 & 2, see the table below:

Feature

XBee Series 1 / 802.15.4

XBee Series 2 / ZigBee

Ramifications

Price

~ $23

~ $26

Price shouldn’t be a driver but If you are looking for a simple point-to-point configuration, you should go with the Series 1. The Series 2 requires considerable setup and configuration.

Transmit Power Output 

Indoor/Urban Range 

Line-of-Sight Range

1 mW (0dbm)

up to 100 ft.

up to 300 ft.

2 mW (+3dbm)

up to 133 ft.

up to 400 ft.

The additional power of the Series 2 give you a ~25% increase in range.

Firmware

Comes standard with 802.15.4 firmware for point-point or star topology. Requires DigiMesh firmware to mesh.

does not offer any 802.15.4-only firmware; it is always running the XBee ZB ZigBee mesh firmware

DigiMesh, while proprietary, appears to have less overhead and easier to configure

Network Topologies

Point-to-Point, Star, and Mesh (with DigiMesh firmware)

Point-to-Point, Star, and Mesh

With a closer reading of the specs, you’ll find that the Series 1 with DigiMesh has a peer-to-peer topology but the Series 2 is hierarchical. I believe peer-to-peer is superior.

Routing Protocol

Ad hoc On-Demand Distance Vector (AODV) Routing + Hierarchical Tree Routing as last resort

Ad hoc On-Demand Distance Vector (AODV) Routing

I suspect there are more differences here but couldn’t uncover them.

RF Data Rate

250 Kbps

250 Kbps

RF data rate doesn’t have much practical meaning

Practical Maximum Throughput

~ 80kbps

ZigBee is significantly slower than the 802.15.4

ZugBee is a full OSI stack, and as a result, has significant overhead.

Power-Down Current

10 uA

1 uA

Series 2 was built for low power consumption.

After pondering this all for a bit, I believe the choose boils down to two questions:

    • Is the interoperability of ZigBee important to you?
    • What are the benefits of ZigBee vs. DigiMesh?

The answer to the first question is “no”.  While I find ZigBee’s interoperability seductive, the practical matter is that I just don’t see that many applications that I could envision integrating into a project.  Maybe some day, but not within my planning horizon.  As to the second question, I don’t see any advantages to ZigBee’s imposed topology of coordinators, routers, and end-nodes.  I believe the homogeneous types of nodes will give my applications the flexibility I may need. Of course, there are many other things one might want to consider, but I think this analysis is sufficient for my needs.  I’m going with the XBee Series 1 Module and I’ll install DigiMesh firmware when it comes time to build meshed networks.

AT Mode vs. API Mode

XBee modules support two modes of operation – AT mode and API mode.  In API mode, you communicate with the radio by sending and receiving packets. In AT (transparent) mode, the XBee radio simply relays serial data to the receiving XBee, as identified by the DH+DL address.  Series 1 radios support both AT and API modes with a single firmware version, allowing you switch between the modes with the  X-CTU software.

To create simple point-to-point links, XBee works nicely in AT mode without much coding. However, if your goal is to build a network consisting of more than two devices, AT mode becomes too difficult to bear. You will spend almost all the time switching in and out of AT mode, wasting time and draining batteries in the process. On the other hand, in API mode commands and data travel in specially formatted frames and no switching is necessary. Another advantage of API mode is that serial speed on transmitters doesn’t have to match – one can be configured for 115,200bps, another for 2400bps, third left with default 9600bps. There is another nice feature called remote command; you can remotely request the state of XBee module pins, for example, or change an output pin level.

It’s clear that I’ll want to work in API mode, but judging from the examples of XBee API mode code, it sure would be nice to have a library package that has designed in some basic utilities that I can leverage.  That is the next topic.

Supporting Software

One of the first packages I discovered was the Xbee Network Protocol (XNP).  I was impressed by the volume and quality of the documentation.  Never the less, I passed on it for two reasons.  First, it isn’t as mature as other packages I discovered (and not widely used), and most importantly, it appears to be implementing mesh networking in software.  Ether the author didn’t recognize that the Series 1 modules can mesh via the DigiMesh firmware (not a surprise since many websites wrongfully report that the Series 1 do not mesh) or he just wants to roll-his-own (what better way to learn about mesh routing protocols).

xbee-arduino is a C++ Arduino library for communicating with XBees in API mode, with support for both Series 1 and Series 2.  Judging from the documentation,  it appears that it could be ported to Raspberry Pi but it would be far easier to use something targeted for the RPi (see below).  With the latest beta software, the XBee’s serial communications can be handle via SoftwareSerial, freeing up the Arduino USB for debugging.  It also appears to that the author is experimenting  if not already supporting DigiMesh. The package is well documented, actively maintained, and equally important, appears to be popular.

Another possibility for the Raspberry Pi is the python-xbee. This Python package is not as well documented as the xbee-arduino but does appear to be actively used and supported. The fact that its on the Python Organization’s web site as a listed package gives it some additional credibility. See this and this with respect to DigiMesh support.

libxbee is another C++ library but targeted at Linux and Windows. Fewer users and the author states “development is coming to an end” may mean this platform isn’t as strong as the others.

While not a very rigorous analysis, I believe I’ll place my bets on xbee-arduino for Arduino development and python-xbee for Raspberry Pi development.  Using Python is intriguing in part because it appears to be the preferred software language for the RPi.  But what if you have some C++ code, a popular language for Linux, and that you want to use some existing libraries? There are tools that could make this happen. You could use Python’s C/C++ extension modules. Also, there is the Simplified Wrapper and Interface Generator (SWIG), which is a software development tool that connects programs written in C/C++ with a variety of high-level programming languages. SWIG is used with different types of target languages including common scripting languages such as Perl, PHP, Python, Tcl and Ruby.

References

An unspoken consideration in my analysis is documentation availability/quality, example implementations  for learning, and the availability of software libraries I could potential use. Here are some of the more interesting things I uncovered.

Tutorials (ZigBee but can be generalized to the XBee)

XBee Documentation

Example Implementations

    • Collection of XBee Projects – Digi’s collection of XBee projects done by the Hacker/DIY community
    • XBee Examples & Guides – Digi’s website giving you step-by-step instructions for simple projects
    • Playing Xbee: Part 1, 2, 3, 4 – author does a nice “teaching tour” on his introduction to XBee

Other Sources

<span>%d</span> bloggers like this: