[Updated August 6: Added a couple of tips to the section on using minicom to configure the XBee.]
[Updated August 7: Added "Windows Weirdness" section with workarounds for problems with pySerial on Windows]
Note: This article is an installment in a series about building a plant light controller (and beyond) on the Netduino microcontroller platform. For previous articles in the series, click here.
When last we saw it, the Netduino project was a pretty smart plant light controller but a pretty dumb clock. The main problem is that it can’t figure out the time on its own – when it’s powered on I have to manually set the time using its menu.
C’mon, Netduino, you don’t need me for that! Haven’t you heard of the Internet?
An Inconvenient Truth
As you probably know, it is quite possible to use a Netduino Plus, or a regular Netduino with an Ethernet shield, to connect a Netduino directly to the Internet. In fact, O’Reilly recently published a book starring the Netduino Plus which shows you how to do that.Instead of Ethernet, I decided to use an Xbee Series 1 connection to a PC acting as an intermediary, partly because I already had that configuration in place to support Tweet-A-Watt monitoring, but also because of certain advantages:
- Wired Ethernet connections aren’t practical for most parts of the home
- XBee is cheaper than Wi-Fi, especially if you plan to use multiple Netduinos in various parts of the home (which we will, once we add sensor monitoring to the mix)
- The Netduino is a relatively constrained development platform compared to a PC. So, it helps to limit the Netduino’s role to what’s required on the “front lines”, and have much of the code running on a PC acting as “command and control”. This, too, will become a bigger advantage when there are multiple Netduinos involved.
The big downside to this approach is that you’re leaving a PC powered on 24/7. That adds up to a lot of wasted electricity, considering how low its workload is going to be. Dedicating a 120W+ PC to this project is absurdly excessive – do you really want to make Al Gore cry? (Well, yeah, me too – but you know what I mean.)
Fortunately, there are an increasing number of ultra low power devices that are capable of acting as the PC for this purpose. As long as it has a USB port, an Internet connection and can run Python, then it’s good to go.
I’ve written about the Beagleboard in the past. When running Linux and the Python script in this project, a Beagleboard XM uses about 3W (as measured by a Kill-A-Watt meter).
By comparison, my “energy efficient” 2 year old Windows PC averages about 120W. My older PC averages about 200W. Considering that it’s able to serve as a full-fledged home server, the Beagleboard is incredible, and hopefully an indication of the future direction of home PCs.
Incidentally, the Netduino/Arduino/LCD combination used in this project burns well less than 1W, so using *duinos in your home projects is definitely an energy-friendly alternative.
A less expensive option, and the one that I’m using in this project, is the $99 TonidoPlug. It comes with Ubuntu already installed, and a built-in Ethernet and USB Port. You can connect the XBee to the USB port directly if you want, and that will work fine for the purposes of this project. However, if you want to run the Tonido software then you’ll need a powered USB hub — the Tonido software requires a USB drive, and there’s only the 1 built-in port.Like the Beagleboards I’ve found the TonidoPlug to be very reliable device, and it’s just as power efficient. It’s not easy to upgrade or replace the OS, but the built-in version of Ubuntu is more than adequate for the projects I have in mind.
If you decide to go with a Beagleboard, one of my past articles covers installing Angstrom and Python, and this eLinux page is gospel if you’re installing Ubuntu.
As for the TonidoPlug, it comes with Ubuntu 9.04 (Jaunty Jack), Python 2.5, and an SSH Server out of the box. All you need to add for this project is the Python serial library and the GNU Screen utility for running the Python app in a background terminal session.
To install them, login as root through SSH, create then directory used by the apt package manager, then install a couple of packages:
mkdir -p /var/cache/apt/archives/partial apt-get update apt-get install python-serial apt-get install screen
Connecting an XBee to a PC
Point-to-point communication ain’t no fun with just one point, so we’ll need to connect an XBee to both the PC and the Netduino.
At the PC end, whether you use a Beagleboard, TonidoPlug, or a full PC, you’ll need a USB adapter for the XBee.
There are many options out there. I’m using an Adafruit XBee Adapter and a USB TTL-232 cable. However, unless you happen to have a spare cable this is a relatively expensive option, since the adapter costs $10 and the cable costs $20. Other options that I’ve used are the $20 Parallax XBee Adapter, and SeeedStudio’s versatile $20 UartSBee.
Before connecting the XBee to the Netduino, you should configure the 2 XBees so that they will talk to one another.
By default, the XBee adapters are all configured as adapter 0 in PAN (network ID) 3332, and they’ll send their data to other adapter 0s. While this works fine if one XBee only sends, and the other XBee only receives, we’ll soon have the Netduino and PC chatting merrily away to one another. So, you should assign one of the XBees to have a different adapter ID (number 1 works fine), then set the other XBee’s destination address to be that same ID.
This page at Adafruit covers the 2 options for configuring an XBee: the Windows-only X-CTU program, and entering AT commands from a serial terminal.
Whichever configuration method you use, you need to change the “MY” setting on the first XBee to 1, and the the “DL” setting on the other XBee to 1. That’s it: the other defaults are fine.
I’d recommend using the X-CTU program if you’re getting started with XBees: it’s much more user friendly and foolproof than a serial terminal. While you are in there, you should update the firmware of the XBees, something you can’t do from a serial terminal.
If you’re hardcore about using a TonidoPlug or Beagleboard as a PC, or want to avoid running X-CTU for other reasons, than a serial terminal is the way to go.
Personally, I’ve used minicom on a Beagleboard and TonidoPlug for this. In order to talk to the XBee you’ll need to run minicom as root and change some of the default settings. Connect an XBee in its adapter to the USB port, then:
- At the Linux command line, enter “minicom -s”. If you plan to save your settings in a profile (a good idea), you should run as root: “sudo minicom -s”
- Select “Serial port setup”
- The serial port settings should be as shown in the screenshot below. Press “E” to change the Bps to 9600, and press “F” to set Hardware Flow Control to “No”. You might also need to change the Serial Device setting: its generally “/dev/ttyUSB0″, but if you have other USB devices connected: it might be /dev/ttyUSB1 or /dev/ttyUSB2, etc.
- Press Enter to return to the minicom configuration menu, then select “Screen and keyboard”
- Press “P” to turn on the Add Linefeed feature, and press “Q” to turn on Local Echo.
- Press Enter to return to the configuration menu again. To save these settings, choose one of the “Save setup” options. To display the serial terminal, select “Exit”.
- The XBee is initially ready to receive and send data. You’ll need to put it in command mode instead. To enter command mode, press the “+” key 3 times (i.e. +++) but don’t press Enter. The XBee should display OK.
The correct terminal commands for the first XBee are:
+++ ATMY 1 ATWR
And for the second XBee
+++ ATDL 1 ATWR
The XBee should send back “OK” after each command.
If you aren’t able to see what you are typing, try turning on Local Echo again: press Ctrl-A then Z to display the menu, then press E.
Note that the XBee will automatically (and silently) exit configuration mode if you wait too long between commands, so if you aren’t getting the OK after an AT command, try entering +++ again.
Connecting an XBee to a Netduino
The hardware connection to the Netduino is relatively simple, because the Netduino uses the same 3.3V voltage level as the XBee and the Netduino’s serial pins talk the same language as the XBee.
The only complication is that the XBee uses an usually tight spacing for its pins, just 2mm apart. This makes it difficult to connect jumper cables to the pins, and impossible to plug the XBee into a breadboard. Most people use a breakout board to solve this problem, such as Sparkfun’s XBee Breakout Board or Adafruit’s XBee Adapter PCB (which is the PCB used in their Adapter Kit – it functions well as a breakout board).
As shown in the photo below, I plugged the XBee into a small breadboard using an Adafruit XBee Adapter. This makes it easy to share the Netduino’s 3.3V pin with other devices besides the XBee, and it allows you to connect an LED to some of the XBee’s pins for troubleshooting:
| XBee Pin | Connection |
|---|---|
| 1 | 3.3V |
| 2 | Netduino RX (e.g D0) |
| 3 | Netduino TX (e.g. D1) |
| 6 | LED (lit when receiving, optional) |
| 10 | Ground |
Running the Python Software
Once the hardware is in place, the next step is to start the Python software running.
You’ll need to have pySerial installed. If you followed my instructions for configuring Angstrom Linux on a Beagleboard, or configuring Ubuntu on a TonidoPlug (earlier in this article), then you’re all set. Otherwise, see the install instructions on the pySerial page.
Download the Python code from my Google Code project. Save the file to any folder on the host PC – if you are using a TonidoPlug or Beagleboard running Linux, then your home folder is fine.
If you are using Linux, you’ll probably need to run the Python code as root in order to access the serial port:
i.e.
sudo python TimeServer.py
The command line parameters for the program are all optional:
TimeServer.py [-nl] [-d] [-port xxxx]
- -nl – turns off logging. Otherwise, any errors will be written to the current directory in a file named controller.txt. Hopefully this file won’t get large, but turning off logging is necessary if you are running the code from a read-only directory.
- -d – turns on debug messages written to the console.
- -port – specifies the serial port that the XBee is connected to. The default is /dev/ttyUSB0. On a TonidoPlug or Beagleboard, that should be the right port. On a Windows PC, the port will have a totally different name, such as COM3 – check Device Manager if you don’t know which one to use. If you are using Windows, see the “Windows Weirdness” section below.
If you launch the program when connecting through SSH, you should first use the GNU Screen utility to open a virtual command prompt, and run the program from there. Otherwise, the program will stop running when you disconnect from SSH.
To run screen, just type “screen”. You’ll be brought to a new command prompt, at which you run TimeServer.py as above.
When TimeRelay is up and running, you can disconnect from your screen session by pressing CTRL-A, then D. This leaves the Python code running in the background. To reconnect to the screen session, enter screen –r –d.
GNU Screen is handy for running a background process like this because you can reconnect at any time, from any place, and run screen –r –d to see the current output from the TimeServer.py program. This is really helpful for debugging, and for restarting the Python code if (heaven forbid!) it should start misbehaving.
Windows Weirdness
Running the Python code on Windows presents a couple of other complications, besides that whole “global warming melting glaciers” thing.
If Python throws an “The system cannot find the file specified” Exception when it tries to open the serial port, you may have run into the problem described on StackOverflow here. Try specifying the COM port as ”\.COMxx”
e.g.
-port \.COM10
Hey, don’t ask me — try it.
Also, opening a serial port sometimes results in an “Access denied” exception on Windows if you don’t close it before opening it. Like I said, don’t ask me. Since closing the serial port before opening it doesn’t seem to cause any problems, I’ve updated the Python code with this fix.
Running the Netduino Code
You can get the Netduino code in one of 2 ways:
- If you are familiar with Subversion, you use any SVN client(my favorite is TortoiseSVN) to get a copy of all the project files. The SVN URL is https://gigamega-micro.googlecode.com/svn/trunk. If you want the older version of the code to match one of the past articles, get the corresponding revision. (See the revision list here)
- Or, download the good old .zip file from the Downloads section of the Google Code project. Here is a direct link to the code for this article.
If the Python program is running, then you’ll know within a minute of powering on the Netduino whether everything is working correctly: the date and time will automatically be set correctly via the XBee connection. Tah-dah!
OK, OK, maybe that wasn’t worth a Tah-dah. But, that’s not all: the LED you connected to the XBee’s receive pin will light up once a minute. Tah-dah!
Hmm, tough audience.
About the only other change to the Netduino software this time is that I finally added a Daylight Savings Time setting to the Netduino’s menu: you can turn DST off or on in the “Date” menu. (Tah-dah!) This is used when calculating the “Sun Up” and “Sun Down” times, if you are basing the plant light timer on those times. Purists will point out that an Internet-connected Netduino shouldn’t have to rely on a manual setting to know when DST is in effect, but we’ll ignore those purists for now.
Programmer’s Show and Tell
The Python code is admittedly very simple: all the better to learn Python programming from, right?
The XBee’s serial port connection is opened during startup. If the connection can’t be opened, the program will display an error message and terminate by calling the Python sys.exit function. If you had some problems getting the serial port working earlier, you’re no doubt well acquainted with this error message.
try:
ser = serial.Serial(SERIALPORT, BAUDRATE, timeout=TIMEOUT)
ser.close() # workaround for known problem when running on Windows
ser.open()
except:
print "Unable to open serial port ", SERIALPORT, ". See ya."
sys.exit(1)
The main loop checks whether the time has changed (just the minute, actually – we’ll let the Netduino handle the seconds). If it has, it calls the sendDateTime() function. It then sleeps for awhile before repeating the loop.
def displayTime():
lastMin = -1
while 1==1:
try:
currTime = datetime.datetime.now()
if DEBUG:
print "in displayTime, currTime = " + currTime.strftime("%Y-%m-%d %H:%M:%S")
currMin = currTime.minute
if lastMin != currMin:
lastMin = currMin
sendDateTime()
time.sleep(15);
except Exception:
LogMsg("Error in displayTime")
print sys.exc_info()[0]
Note that that the Exception handler is different from the one used when opening the serial port: it logs the error, displays some information about the error to the console (using the Python sys.exc_info function), then optimistically keeps going. If there was no Exception handler, any exception in this loop, or in the functions called by this loop, would cause the application to terminate.
This “log it and keep going” approach is generally frowned upon in software design, but I’d recommend it for a simple program like this that runs in the background. You should find that this application, and Python code that communicates via XBee in general, is very low maintenance: you can just start it, then forget about it. You can occasionally check on the code using GNU Screen or by looking at the contents of the controller.txt error log.
The sendDateTime function just converts the date and time to the format that the Netduino is expecting it, then writes it to the serial port. Note that the “ser.flush()” function is used to make sure that the data is sent right away rather than being buffered – this is literally time-sensitive data.
def sendCommand(strPrefix, strCommand):
if ser:
ser.write(strPrefix + ":" + strCommand + chr(0))
ser.flush()
def sendDateTime():
timeStr = time.strftime("%Y-%m-%d %H:%M")
sendCommand("D", timeStr)
On the Netduino side, surprisingly little new code is required to talk to the XBee. We’re using the XBee as a serial port device, rather than making use of the XBee’s API (a more versatile option that I might explore in a future article). From the Netduino’s perspective, the XBee might be some guy sitting at a serial terminal, occasionally typing in a”set time” command. We’ve already implemented that support, back in the “Netduino: Time and Weather” article .
The XBee connection is opened during startup, using almost the exact same code as was used to open a serial connection to a PC terminal:
// last parm should be true for UART terminal (to send // user confirmation), but false for UART XBee uart = new clsUART(strUARTPort, 9600, 512, false);
The event handler is the same one that was used for the PC terminal: the event is raised when our generic serial port class, clsUART, receives some data. In fact, if you’re using the SparkFun Serial LCD Kit, this event handler is still used when the Netduino receives data from the Arduino, as explained in the “A Little Help From Its Friends” article .
Sharing a serial command event handler between Arduino and the XBee works well, and is easy to implement in .Net. The Netduino doesn’t know, or need to know, who’s sending the command, and the .Net Micro framework ensures there isn’t any conflict between the 2 serial ports.
The only thing that’s changed here is that the XBee sends the date and time together in the same command:
D: 2011-07-25 18:01
So, I modified clsUART to check to see if the string is in this format, and it raises both a “date set” and “time set” event if it is.
if (strDateParts.Length == 5)
{
intHours = Int32.Parse(strDateParts[3]);
intMinutes = Int32.Parse(strDateParts[4]);
intSeconds = 0;
blnTimeSet = true;
}
...
// tell rest of application that the date has been set
raiseCommand(strCommand);
if (blnTimeSet)
{
// raise the time event too
raiseCommand("T:" + Program.Int_ToZeroPrefixedString(intHours, 2) + ":" + Program.Int_ToZeroPrefixedString(intMinutes, 2));
}
The event handler already knew how to handle date changes and time changes, so no code change was required there.
The only other significant change was modifying the menu to add a “Daylight Savings Time” switch. Since the menu code was designed to be easily extended – as explained in the Ordering Off the Menu article – this required just 1 new line to the strMenuItems array:
"2-1", "Hour `HH`", "_UD-`HH`", "2-1", "Min `mm`", "_UD-`mm`", "2-1", "DST `DS`", "_DST", // NEW - Daylight Savings Time setting
The format looks rather cryptic, but it will make more sense if you read the “Programmer Show and Tell” section of Ordering Off the Menu.
The code in clsLCDMenu passes the “`DS`” keyword to its callback method for getting the current DST setting, and it passes the “_DST” keyword to the callback method for handling a new setting entered by the user.
For example, the code added to the setValueFromMenu() callback method for the “_DST” keyword is:
else if (menuCode == "_DST")
{
// toggle DST
blnUseDaylightSavingsTime = !blnUseDaylightSavingsTime;
calculateSunriseAndSunset(DateTime.Now);
if (blnUseDaylightSavingsTime)
{
SaveSettingToEEPROM(ADDR_DST, 2);
}
else
{
SaveSettingToEEPROM(ADDR_DST, 1);
}
}
This recalculates the Sunrise and Sunset times (and updates the plant light timers if they are based on these times), then passes the new setting to the Arduino in the Sparkfun LCD Kit to save it to EEPROM.
I love it when a plan comes together!
Wrapping Up
I’ve found the XBee to be a very dependable add-on to the Netduino. I actually wrote the code used in this article back in May and have been running it continuously since then, and I’ve yet to have any cases where the XBee connection permanently drops or stops responding. In my experience, this is a big advantage over using an Ethernet connection – when the Netduino’s Ethernet connection drops it tends to stay down.
So, if the Xbee’s so great, why am I using it only to set the time?
Good question.
If you browse through the main Program.cs class in the source code, you’ll notice a new method called uploadSensorData, that I didn’t address in this article.
Stay tuned for the next step in the project, in which the Netduino talks back, and I draw together a couple of previously separate topics in my blog: the Netduino and Nimbits.





































