Wow. For the first time in my life I've undertaken an electronics project and had it immediately work. I'm still a little shaken by the experience.
As you might recall, in my last post I discussed loading the custom, Linux-based DD-WRT firmware onto the Fonera router. I left off with some thoughts about using that environment to achieve serial communication with an Arduino.
Getting the Fonera to talk to my Arduino turned out to be shockingly easy. The 2200 Fonera model has a four-pin header exposed. The pin closest to the ethernet port is ground; next is serial receive; then comes serial transmit. I scrounged up a female pin header connector from a USB break-out bezel I had lying around (already half-cannibalized — last year I'd used the USB end to make the cable necessary for softmodding the office Xbox). That makes the photo to the right look a bit messier than it needs to. In truth I simply connected ground to ground, then the Fonera transmit pin to the Arduino receive pin.
The Arduino software environment's serial monitor only displays transmitted data, so I whipped up a quick program to read incoming data and echo it back out on the transmit pin (which wasn't connected to anything, but the Arduino's serial output is picked up by my macbook through the USB connection). You can see the program in the picture below. You can also see the result I got when booting up the Fonera:
It worked! First you see the bootloader, then a bunch of garbage. That's nothing to worry about, though. The bootloader runs at 9600 baud, which is what I had the Arduino serial link configured to expect. Once the bootloader is done, the DD-WRT environment takes over, and it ramps the serial port's speed up to 115200 baud, producing the cloud of gibberish that follows the bootloader.
Fortunately, that's easy to fix with the stty command:
stty -F /dev/tts/0 9600
This sets the serial port's speed back to 9600. As you might have inferred, the serial port in the DD-WRT environment sits at /dev/tts/0. You can use that address to send commands over the serial link:
echo "it worked! w00t!" > /dev/tts/0
That'll get sent into the Arduino's waiting arms, as you can see at the end of the ASCII garbage (I didn't send another command before taking the screenshot, but the echoed content ends with a newline, making subsequent commands much easier to pick out).
So to complete this system all I have to do is: add the stty command to the DD-WRT startup scripts; set up a DD-WRT cron job to run a script that checks a remote resource and sends the result, via the serial port, to the Arduino; and write an Arduino program that reads that data from the serial port and executes commands when it finds actionable data.
But cron jobs can only run once a minute. What if we want to poll the remote resource more frequently? There's no Perl, Ruby or Python available on the Fonera, nor any Netcat. Fortunately, there's wget. Combined with some specialized PHP, I was able to get a (very) poor-man's Comet system running — even on my commodity shared webhost (I could've run a custom daemon on EchoDitto's servers, of course, but I figured I might as well try to make this as universally accessible as possible).
<?php ini_set('max_execution_time',60); for($i=0;$i<60;$i++) { print "###" . $i . "\n"; ob_flush(); flush(); sleep(1); } ?>
The three hash marks are there for the benefit of the Arduino — I'll set it up to keep a rolling buffer of the last n bytes of serial data, and check the first three bytes every time it adds a new character. When those bytes match "###" it'll know to process the rest of the buffer (which will, presumably, contain something more interesting than a simple per-second counter). The only other notable parts of the script are the first line, which tries to ensure that the server doesn't kill the request before its sixty second run is over; and the flush() lines, which tell Apache to send the Fonera the response so far rather than waiting until it's fully composed.
I'll connect to this script on a remote server with an every-minute cron script that looks something like this:
killall wget wget -q -O - http://my.server/script.php > /dev/tts/0
And that's it! Admittedly, I haven't yet piped this output to the Arduino to do something useful. But it works like a charm from the console, and, in combination with the serial echo program, constitutes proof-of-concept validation for each part of my planned application.
One-second resolution seems likely to be more than adequate for any of the monitoring tasks I have in mind. Now I just need to find some awesome-looking analog gauges and write a script to keep an eye on when the next bus is going to be rolling by my apartment. All Electronics has some nice big VU meters for $10 or so — if anyone's got a better suggestion, please let me know.
The only downside to all of this is that the Arduino's being underutilized. For the simple apps I have in mind to try first, you could probably get away with some sort of serial-speaking PWM IC. But of course the Arduino's open, and easy, and quite flexible. It's nice to know that I'll have more power (and GPIOs) available if I decide to do something more complex. And now that Arduino kits are less than $20, it's not so much more expensive to build them into your project.
UPDATE: One thing I forgot to note: don't try to program your Arduino while there's anything connected to its serial pins. I made that mistake and was getting very frustrated at my inability to upload my sketch — even when powered off the connected La Fonera was interfering. Temporarily disconnecting the two solved the problem immediately. I was using a relatively old Arduino NG (still ATMega8-based), so for all I know this may not happen to newer models.
Post new comment