kmod-usb-root@OpenWrt:~# ipkg install kmod-usb-storage root@OpenWrt:~# ipkg install kmod-vfat root@OpenWrt:~# echo “scsi_mod” >> /etc/modules root@OpenWrt:~# echo “sd_mod” >> /etc/module
Trang 1The spcacatprogram spews a lot of information as it interrogates the camera to figure outwhat it’s capable of It then prints a line each time it takes a picture This is a lot of text andafter a while you’ll get tired of it If so, create a little script called camstartand have it contain:
#!/bin/sh
ln -fs /dev/v4l/video0 /dev/video0spcacat -d /dev/video0 -g -f jpg -p 1000 -o > /dev/null
Move your new camstartprogram to /usr/binand use it instead:
root@OpenWrt:~# vi camstart # write the above and save
root@OpenWrt:~# chmod +x camstart root@OpenWrt:~# mv camstart /usr/bin root@OpenWrt:~# camstart &
root@OpenWrt:~# ln -s /tmp/SpcaPict.tif /www/SpcaPict.tif
Now you can point your web browser at your OpenWrt box and view webcam images If yourWRTSL54G has an IP address of 192.168.0.101, then go to http://192.168.0.101/ SpcaPict.tif Press Reload on your browser to get an updated image
You may wonder why you don’t just run the webcam program from inside /www It will writethere without this symlink business The problem is that /wwwis part of the OpenWrt flash mem-ory Flash memory has a limited number of write cycles, a few ten thousand For a USB disk this
is okay because you can easily replace it, but it’s almost impossible to replace the flash soldereddown inside the WRT If the webcam program were allowed to continuously write to the flash,the flash memory would be worn out within a day
Pressing Reload all the time is tedious With a little JavaScript you can have the browserrefresh the image for you Listing 15-1 shows a small dynamic HTML page to accomplishthis, called roombacam.html When you have this file, put it anywhere in the /wwwdirectory.You may need to adjust the symlink to SpcaPict.tifso that it’s in the same directory asroombacam.html Figure 15-8 shows the resulting web page You can now easily watch theworld from the perspective of your Roomba as it goes about its business
Listing 15-1: roombacam.html: Auto-Refreshes the Webcam Image
Trang 3Adding a Flash Drive
It would be nice to be able to save the images recorded by the Roomba The router’s flashmemory shouldn’t be used because of its limited lifespan and small space The router’s RAM is
a little bigger but disappears when the power is removed You could copy the images to anothernetwork device, but that requires the other device to be online constantly A USB flash driveseems perfect It is made for a lot of use and has huge amounts of space
Figure 15-9 shows a typical USB thumb drive You can get a 1 GB thumb drive for under $30from several electronics retailers Each JPEG image from the webcam takes up approximately
16 KB On a 1 GB drive, you could store over 60,000 images
F IGURE 15-9: Typical USB thumb drive, red to match this Roomba
Installing Drivers
Installing the storage drivers in OpenWrt is standard and nothing tricky The storagepackage contains several drivers that work in conjunction Instead of trying to loadthem all manually, add them to /etc/modulesand just reboot the router It ends up beingfaster
kmod-usb-root@OpenWrt:~# ipkg install kmod-usb-storage root@OpenWrt:~# ipkg install kmod-vfat
root@OpenWrt:~# echo “scsi_mod” >> /etc/modules root@OpenWrt:~# echo “sd_mod” >> /etc/modules root@OpenWrt:~# echo “sg” >> /etc/modules
Trang 4root@OpenWrt:~# echo “fat” >> /etc/modules
root@OpenWrt:~# echo “vfat” >> /etc/modules
After rebooting, plug in the USB drive and watch dmesg You should see something like
Listing 15-2 The most important part is the Partition checksection as it tells you the
full path to the disk Use it when mounting the disk
Listing 15-2: dmesg Output for Detected USB Drive
root@OpenWrt:~# dmesg
[ ]
hub.c: new USB device 01:02.0-1, assigned address 2
SCSI subsystem driver Revision: 1.00
Initializing USB Mass Storage driver
usb.c: registered new driver usb-storage
scsi0 : SCSI emulation for USB Mass Storage devices
Vendor: VBTM Model: Store ‘n’ Go Rev: 5.00
Type: Direct-Access ANSI SCSI
revision: 02
Attached scsi removable disk sda at scsi0, channel 0, id 0, lun
0
SCSI device sda: 2013184 512-byte hdwr sectors (1031 MB)
sda: Write Protect is off
Partition check:
/dev/scsi/host0/bus0/target0/lun0: p1
WARNING: USB Mass Storage data integrity not assured
USB Mass Storage device found at 2
USB Mass Storage support registered
Using It
OpenWrt should attempt to mount the disk at the path /mnt/disc0_1 This is mostly reliable
but sometimes doesn’t work To mount it yourself, use the full path from the dmesgoutput and
add the partition you want (usually part1for the first partition) With the resulting device
path, mount the disk and see how much space you have on it:
root@OpenWrt:~# mkdir /mydisk
root@OpenWrt:~# mount /dev/scsi/host0/bus0/target0/lun0/part1
Trang 5At this point, you can cdinto the disk and re-run the spcacatcommand, but leave off the-oargument Then it will create image after image with names like jpeg 07:21:2006- 08:24:03-P0004.tif, which is the date, time, and image number of the capture.
For example, here’s how you might capture 100 images at a one-second interval, saving them tothe flash drive:
root@OpenWrt:~# cd /mydisk root@OpenWrt:~# spcacat -d /dev/video0 -f jpg -g -p 1000 -N 100
When this is running, at any point you can just shut down the router, remove the USB drive,and stick it into your PC to get a visual record of what the router saw as a series of time stampedJPEGs From there, you can make a time-lapse movie using QuickTime Pro or similar program
Controlling Roomba from C
For controlling the Roomba robot, a compiled C program has a few advantages over the othermethods presented so far:
䡲 Faster: Although hard to see on modern PCs, interpreted languages like MicroPerl are
noticeably slower on these embedded systems
䡲 No need for stty: Shelling out to an external program to set serial parameters just seems
inelegant In C, it’s easy to do the equivalent without needing an external program
䡲 Self-contained: No execution environment is needed Execution environments like the
shell or Perl can add complexity If the task is simple, use a simple implementation
Also by programming in C, you have better control over the memory usage and timing of thecode This isn’t critical for the simple Roomba controlling done here, but if you were analyzing
a lot of Roomba sensor data, using space efficiently becomes important when your machineonly has 64 MB of RAM
The roombacmdprogram is divided into a set of basic Roomba commands, called roombalib.c,and the command-line parsing, called roombacmd.c The code compiles and runs not only onOpenWrt Linux but on regular Linux and Mac OS X It should also run in Windows withCygwin
Listing 15-3 shows the three primary functions in roombalib.c The roomba_init_ serialport()function uses standard Unix calls to accomplish what the sttyline did in the Perl script The roomba_drive()function looks very similar to the drive()method inRoombaComm you created in Chapter 5, and the roomba_read_sensors()function looksmuch like the same function in Arduino from Chapter 13
The roombaliblibrary defines a Roombadata structure that just contains the serial port nameand file descriptor Think of it as the data-only part of the RoombaComm object
Trang 6char vhi = velocity >> 8;
char vlo = velocity & 0xff;
char rhi = radius >> 8;
char rlo = radius & 0xff;
if(roombadebug) fprintf(stderr,
“roomba_drive: %.2hhx %.2hhx %.2hhx
%.2hhx\n”,
Trang 7}int roomba_read_sensors(Roomba* roomba){
char cmd[2] = {142, 0}; // SENSOR, get all sensor dataint n = write(roomba->fd, cmd, 2);
roomba_delay(COMMANDPAUSE_MILLIS);
n = read(roomba->fd, roomba->sensor_bytes, 26);
if( n!=26 ) {if(roombadebug) fprintf(stderr,
“roomba_read_sensors: not enough read(n=%d)\n”,n);
return -1;
}return 0;
gcc -Wall -I roombacmd.c roombalib.c -o roombacmd
You can then run it with no arguments to see how to use it, as in Listing 15-4 This piled version of roombacmdisn’t usable in OpenWrt, but you can test it before making anOpenWrt version
com-Listing 15-4: roombacmd Usage
Trang 8Listing 15-4 Continued
-v, verbose=NUM Be verbosive (use more for more
verbose)
-f, forward Go forward at current speed
-b, backward Go backward at current speed
-l, spin-left Spin left at current speed
-r, spin-right Spin right at current speed
-s, stop Stop a moving Roomba
-w, wait=millis Wait some milliseconds
-v, velocity=val Set current speed to val (1 to
roombacmd -p /dev/ttyS0 -v 250 forward
roombacmd -p /dev/ttyS0 spin-left
roombacmd -p /dev/ttyS0 sensors
roombacmd -p /dev/ttyS0 stop
Notes:
- The ‘-p’ port option must be first option and is required
- All options/commands can be cascaded & are executed in order,
like:
roombacmd -p /dev/ttyS0 -f -w 1000 -b -w 1000 -s
to go forward for 1 sec, go back for 1 sec, then stop
Building roombacmd for OpenWrt
To immediately try out a version of roombacmdfor OpenWrt, a pre-compiled ipkgpackage
has been made that you can fetch and install:
root@OpenWrt:~# wget http://roombahacking.com/software/openwrt/i
roombacmd_1.0-1_mipsel.ipk
root@OpenWrt:~# ipkg install roombacmd_1.0-1_mipsel.ipk
You’ll then have /usr/bin/roombacmdat your disposal on your OpenWrt system
Building a version of roombacmdfor OpenWrt is not as easy as building it for a desktop OS,
because you have to cross-compile That is, you have to produce an executable for one
architec-ture on another This is what you did when producing Arduino sketches, but Arduino hides all
that from you The language, GCC, is the same But compiling embedded Linux programs is a
Trang 9bit more complex than compiling AVR programs OpenWrt does make it quite easy with thecompany’s SDK The abbreviated steps are:
1 Get the OpenWrt SDK.
2 Create a directory with your source code and package control commands for ipkg
3 Within that directory, compile using the OpenWrt makefiles.
4 Copy the resulting ipkgpackage to the router and install
To save you some time, the roomcmdC code has been placed in such a directory set up to workwith the OpenWrt SDK Using it you can get started making modifications and improvements
to suite your needs To get the SDK and the bundled roombacmdsource and to start compiling, run these commands:
cross-demo% wget http://downloads.openwrt.org/whiterussian/newest/i
demo% make clean && make
The last line will spew a lot of text as it builds, and then when it’s done you’ll have theroombacmd ipkgfile in bin/packages Copy that file to your OpenWrt box and install
it using ipkg.The roombacmd-ipkgdirectory contains an ipkgpackage description and a Makefile thatabides by the OpenWrt SDK’s standards It’s like a meta-Makefile in that it contains descrip-tions on how an existing Makefile (the one for the regular Linux version of roombacmd)should be modified to compile for OpenWrt OpenWrt has several recipes for how to do this,and roombacmd-ipkguses one of them almost verbatim If you’re familiar with Makefiles, it’s
a little hairy but not too complex If you have other C code you’d like to run on your OpenWrtsystem, you can use the preceding techniques to cross-compile them as well
Currently, you need a Linux system (Debian-based, like Ubuntu) to run the OpenWrt SDK If youhave VMware or VirtualPC, you can run virtual Linux
OpenWrt has a great how-to document on compiling for OpenWrt and building packages athttp://wiki.openwrt.org/BuildingPackagesHowTo
Trang 10Controlling Roomba with CGI
OpenWrt ships with a rudimentary Common Gateway Interface (CGI) capability as part of
its web server With the roombacmdC program installed, it can be used in CGI programs
The most common language used for OpenWrt CGI programs is plain shell scripting You can
write CGI programs in C, but the cross-compiling gets to be a pain If you’ve poked around
the /wwwdirectory, you may have noticed the OpenWrt web interface is all written in shell
Listing 15-5 shows roombapanel.cgi, a small CGI shell script used to control Roomba
with roombacmd The top part of it can be edited to fit the configuration of your system
The middle part is a simple HTML interface with buttons that point to the CGI and set
the $QUERY_STRINGenvironment variable to a valid roombacmdcommand The last part
does the work of commanding Roomba If a button is pressed, the $cmdvariable is set and
that is used as the movement argument to roombacmd Figure 15-10 shows what the CGI
looks like when running The PICPATHand SNAPPATHvariables aren’t used yet, but they
Trang 11F IGURE 15-10: Roomba control panel CGI script in use
Putting It All Together
You now have all the components working and ready to assemble Thankfully, there are no realinterdependencies, so the isolated tests above are valid The first thing to do is get all the hard-ware plugged in and working Then you can finalize the software to control it all
System Configuration
All the device drivers should be configured to load at boot Listing 15-6 shows what the/etc/modulesfile should end up looking like The order is important The general driver(usb-serial,videodev, or so on) must be loaded before the device-specific driver (pl2303,spca5xx_lite, or so on)
Listing 15-6: Final Contents of /etc/modules
root@OpenWrt:~# cat /etc/modules
wlusbcoreusb-ohci
Trang 12Make sure you save any programs you want saved to /usr/binand not in /tmp Otherwise,
they’ll disappear on reboot, since /tmpis a RAM disk This includes roombacmd,camstart,
stty, and any other scripts or commands you want
The web and CGI files you create live in /www, which is already flash, so you won’t have to
worry about them disappearing
Building a USB Serial Tether from a Phone Sync Cable
Using the RS-232 serial tether from Chapter 3 with a generic USB-to-serial adapter works
but is very ungainly The tether’s long cable is hard to manage when the controlling
com-puter is right on top of the Roomba Building a tether with a shorter cable is definitely
pos-sible, but a really small solution is to use a USB data cable originally meant to sync mobile
phones Some mobile phones have logic-level serial ports on them instead of USB
inter-faces, and the sync cables contain small USB-to-serial adapters These cables are available
for about $20 from various places, including Radio Shack Since this is a Roomba USB
dongle, it’s called the Roombongle
Things you’ll need to build the Roombongle:
■ USB data cable for Nokia phones (AKA FutureDial Cable 22), Radio Shack part number
17-762
■ Mini-DIN 8-pin cable, Jameco part number 10604
The construction is really straightforward:
1.Acquire the right USB sync cable Figure 15-11 shows the packaging for the sync cable
used here, and Figure 15-12 shows what the cable looks like It’s very important to get
Cable 22, which has the bulge in the middle, and not one of the other cables Other
cables can be used, but you’ll have to figure out the pinouts
Continued
Trang 13Building a USB Serial Tether from a Phone Sync Cable Continued
F IGURE 15-11: FutureDial Cable 22 USB sync cable for Nokia
F IGURE 15-12: The cable itself — make sure it has the bulge.
Trang 14Building a USB Serial Tether from a Phone Sync Cable Continued
2.When you open up the bulge (see Figure 15-13), you’ll see that it contains a Prolific PL-2303
USB-to-serial interface chip, just like the cheap USB-to-serial adapters You already know that
this chip is well supported on all the OSes (and the pl2303driver is part of any Linux,
includ-ing OpenWrt) You can download the spec sheet for said chip and you’ll see that it normally
operates at 3.3V, but its inputs are 5V-tolerant and its 3.3V outputs are within the valid range
for 5V logic Thus, Roomba should understand it, and vice versa
F IGURE 15-13: Inside the bulge, a PL-2303 USB-to-serial chip
3.Turn the board over and see the serial cable wires (see Figure 15-14, left side) For the Cable
22 sync cable, the wires are:
■Black:GND
■White:RXD, receive from PC (connect to TXD on Roomba)
■Orange:TXD, transmit from PC (connect to RXD on Roomba)
F IGURE 15-14: The wires on the left are the serial
port; Black=GND, White=RXD, Orange=TXD
Continued
Trang 15Building a USB Serial Tether from a Phone Sync Cable Continued
4.Note the position of those wires and unsolder the cable bundle from the board Then take aMini-DIN cable that you’ve figured out which wires are GND, TXD, and RXD for Roomba andsolder them onto the board in the correct position Figure 15-15 shows the finished task
F IGURE 15-15: Soldering on a Mini-DIN 8-pin cable
5.Apply a little hot glue to the Mini-DIN cable where it meets the enclosure and snap on theother half of the enclosure The unused wires from the Mini-DIN can be snipped off (just makesure they don’t short together) or you can take the GND and Vpwr lines from and run them to
an external connector This will enable you to run projects off the robot’s battery as well asusing the USB dongle Figure 15-16 shows the completed dongle with an external power con-nector In this version, the 9V snap-on connector was used to mate with the WRTSL54GSpower adapter made previously
The knowledge to use the USB phone sync cables came from the NSLU2-Linux hackers at
www.nslu2-linux.org/wiki/HowTo/AddASerialPort