Interfacing the BeagleBoard with an SRF08 Ultrasonic Ranger over I2C

The SRF08 is an ultrasonic ranger with a 3cm-6m range, and an I2C interface. It’s fairly straightforward to hook it up to a BeagleBoard using the I2C bus exposed on pins 23 and 24 of the expansion header (see page 96 of the BeagleBoard manual for the expansion header pin-out).

Here it is on the breadboard:

Level Translation

The one complication with this is that the BeagleBoard’s I2C interface runs at 1.8V, and the SRF08’s runs at 5V. If the I2C lines were uni-directional, this wouldn’t be too much of a problem as you could just use a voltage divider or transistor to handle the voltage step, but unfortunately the I2C lines are bi-directional (meaning both the master and slave are allowed to change the voltage level on the line).

A clever chap from Philips wrote an application note on how to achieve bi-directional level translation with a single MOSFET. I was able to get this to work with one of the BSN20 MOSFETs recommended in the application note, but I couldn’t get it to translate from 1.8V to 5V. The best I could do was around 2.5V to 5V which makes sense if you look at the ID to VGS chart in the BSN20’s data sheet (Figure 6).

There’s quite a few ICs which handle 2 channel, open-collector, bi-directional level translation. Some examples I found were:

Unfortunately all of them appear to be surface mount, so unless you’re able to work with surface mount components, you’re options may be limited. Luckily surface mount wasn’t as hard as I thought. I chose the TXS0102, as the BeagleBoard uses this itself, and also it was the only one I could get in Australia that didn’t require me to get a second mortgage to pay for the shipping.

The circuit itself is easy to setup, so I won’t include the schematic here. If you’re using the TXS0102 make sure you set the OE pin to high, or you’ll get some obscure error messages when you attempt to read or write to the bus. The TXS0102 also includes a 10K pull-up resistor for each channel, so no need to add your own.

Accessing the I2C Bus on the BeagleBoard

The i2ctools package contains a number of utilities which give you access to the I2C bus from the command line. On a BeagleBoard running Angstrom (and with a network connection) you can install this package with:

opkg install i2c-tools

Once you’re all wired up, you can scan the I2C bus with i2cdetect:

root@beagleboard:~# i2cdetect -r 2
WARNING! This program can confuse your I2C bus, cause data loss and worse!
I will probe file /dev/i2c-2 using read byte commands.
I will probe address range 0x03-0x77.Continue? [Y/n]
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          [ 4275.681945] i2c_omap i2c_omap.2: controller timed out
-- [ 4275.725128] i2c_omap i2c_omap.2: Arbitration lost
-- [ 4276.744659] i2c_omap i2c_omap.2: controller timed out
-- [ 4276.788116] i2c_omap i2c_omap.2: Arbitration lost
-- [ 4276.828186] i2c_omap i2c_omap.2: Arbitration lost
-- [ 4276.868103] i2c_omap i2c_omap.2: Arbitration lost
-- [ 4277.885101] i2c_omap i2c_omap.2: controller timed out

These errors are what I got the first time, and indicates that something is wrong with your circuit – most likely that your missing the pull-up resistors (or you’re not connected properly to the IC if it has built-in pull-up resistors). I’m guessing that the i2c driver is waiting for SCL to go high, which isn’t happening because of the lack of a pull-up resistor, so it just times out. Once you have this sorted you should get a result like:

root@beagleboard:~# i2cdetect -r 2
WARNING! This program can confuse your I2C bus, cause data loss and worse!
I will probe file /dev/i2c-2 using read byte commands.
I will probe address range 0x03-0x77.
Continue? [Y/n]    
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- UU -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: 70 -- -- -- -- -- -- --

The 70 in the bottom left is the SRF08. Slightly confusingly, the SRF08 datasheet reports the I2C address as 0xE0. This is because the least significant bit in an I2C address is used to indicate whether it is a read (1) or write (0) address, so sometimes this bit is left off when reporting addreses. 0x70 << 1 == 0xe0.

Once we’ve got the device showing up in i2cdetect, the rest is easy. To initiate a ping use:

root@beagleboard:~# i2cset 2 112 0 81
WARNING! This program can confuse your I2C bus, cause data loss and worse!
I will write to device file /dev/i2c-2, chip address 0x70, data address 0x00, data 0x51, mode byte.

This will trigger an ultrasonic ping, and cause the LED on the back of the module to flash briefly. You can retrieve the distance by querying the values in registers 2 and 3 (the high and low order bytes of the result, respectively):

root@beagleboard:~# i2cget 2 112 2
WARNING! This program can confuse your I2C bus, cause data loss and worse!
I will read from device file /dev/i2c-2, chip address 0x70, data address 0x02, using read byte data.
Continue? [Y/n]
root@beagleboard:~# i2cget 2 112 3
WARNING! This program can confuse your I2C bus, cause data loss and worse!
I will read from device file /dev/i2c-2, chip address 0x70, data address 0x03, using read byte data.
Continue? [Y/n]

So here the result is 0x003b=59 centimeters. All pretty easy if you can get the level translation issue sorted.

Posted in BeagleBoard, Electronics, I2C | Tagged , , | 7 Comments

Surface Mount Soldering Made Easy(ish)

I’ve been playing around with electronics for a while, making do with my trusty breadboard for prototypes, and occasionally some veroboard if I wanted something more permanent. Unfortunately times are changing, and fewer and fewer interesting components are being made available in breadboard-friendly DIP packages (I blame Apple for convincing everyone that all electronic gadgets should be the size of a credit card).

This had been frustrating me for a while, but came to a head on my latest project where I needed an I2C level converter. Despite many wasted afternoons scouring octopart, digikey and mouser I came up empty handed, so decided it was about time I figured out this surface mount thing.

As it turned out, it was all pretty straightforward, though I did have to buy quite a lot of new equipment. Here’s my first surface mount PCB (a 0.5mm pitch DCU to DIP adapter for a TXS0102):

It’s worth pointing out that you don’t have to go the full PCB etching route like I did. Sparkfun have a number of adapter boards which break out surface mount packages to DIP. These look great for a quick prototype, but I’d been meaning to try PCB manufacturing for a while, so I thought I’d give it a go.

There’s a couple of popular ways to go about making your own PCBs. The first, and cheapest is the toner transfer method. This involves printing your circuit onto photo paper with a laser printer, then transferring the toner directly to your PCB using heat and pressure. The toner can then be used as a normal acid resist. The method sounds good however there are a lot of reports of people having mixed success, and it looks like it requires a lot of experimentation to find the right combination of laser printer, paper, and transfer method.

The second method is the standard photo sensitive resist technique. This is more expensive, but potentially more reliable, which sounded good to me. Here’s the steps I went through to create my first surface mount PCB:

  1. Create the PCB image.
    Eagle is a schematic editor which is free for non-commercial use (though it does feel a bit like 1997). Sparkfun have a good tutorial on using it which is worth checking out. To create the final image, just use File -> Export…-> Image, rather than generating the gerber files as described in the tutorial. Here’s my image:
    I created four copies of the board layout so I could experiment with different exposure times in a later step.Getting hold of land patterns can be difficult for some components. The ‘smd-ipc.lbr’ library which comes with Eagle has many standard patterns. Sparkfun also have their own Eagle library which you can download from here. Failing those options, you can manually create the land pattern if you can find a datasheet which describes it (which is what I ended up doing for the TXS0102).
  2. Print it onto acetate or polyester
    The Kinsten website claims that a sheet of translucent polyester gives better contrast than transparent acetate because the polyester absorbs more of the ink than the acetate. I used the polyester sheets and got good results with tracks 0.2mm wide, and I suspect it would probably go even smaller. I had the misfortune to only own an ink jet printer (Canon MP600) and despite trying a bunch of different printer settings I couldn’t get a high contrast image (basically the ink wouldn’t dry), so I ended up trekking down to the local print shop and using their fancy laser printer.

    Update 4/3/12: I bought a Samsung Ml-1865 monochrome laser printer from Office Works for about $70, which works well.

  3. Expose the photo-sensitive PCB
    UV exposure boxes are pretty expensive, however I found a relatively cheap one at Kinsten (product code ALT-UV). Oddly enough, the packaging indicated it was actually a UV finger nail drying machine. It also came with 3 x 15 watt UV tubes which are supposed to have a wavelength which matches the photo sensitive resist. Here it is in action:
    The exposure process is pretty simple: peel off the plastic backing from the photo sensitive PCB, lay the printed polyester face down on top, place a layer of glass on top (to keep it flat), then slide it into the UV exposure box. I used 4 copies of my circuit, and exposed each for a different time to find the optimum exposure time. The 4 copies were exposed for 75, 100, 150, and 200 seconds respectively. The optimum looks to be about 100 seconds.
  4. Develop the photo resist
    After exposing the PCB to the UV the next step is to immerse the board in developer solution. After about 30 seconds the green photo resist that was exposed to the UV starts coming off into the solution (it looks a bit like blue smoke), eventually leaving just the photo resist that was masked by the polyester. Once it has developed sufficiently you have to rinse it off with water to stop the reaction. Here’s the board: You can see the traces get thinner from left to right (reflecting greater exposure times).
  5. Acid Bath!
    The fun part. To work well the etchant needs to be heated to 50-60°C and be continuously agitated. Without these conditions, the reaction will take a lot longer and may undercut the copper around the resist. Kinsten sell a kit with a heater, thermometer and air pump (I promise I don’t get kickbacks from Kinsten), though you could probably get a way a plastic tub, kettle, and a plastic spoon. As the reaction progressed the solution turned a faint blue color. After about 6 minutes the copper not protected by the resist vanished, leaving the traces still covered in green acid resist. Once this looks finished, rinsing the board off in water stops the reaction.
  6. Remove the resist
    The last step is to remove the resist from our copper traces. An easy way to do this is to expose the board to UV for a couple of minutes and then dip it into the developer solution we used earlier. Other people just scrub it off, but I hate the idea of damaging the traces after this much work. Here’s the final result:
  7. Neutralizing the developer and etchant
    To prevent dissolving my landlord’s plumbing I bought some neutralizing kits from, you guessed it, Kinsten. Unfortunately they didn’t come with directions, however I can recommend not dumping the powder directly into the solution or it will heat up, do nasty things to your brand new plastic tank, and scare your wife. So I hear, anyway. <Shuffles feet>

UPDATE 4/3/2012
Since writing this article I’ve made a couple of dozen boards, and have the process working pretty reliably now. Most of the early problems I had were caused by the film not lying perfectly flat on top of the PCB. Often this was caused by the PCB being slightly warped, or having a slight burr on an edge, caused by the cutting process. I’ve tried a number of different cutting techniques in an attempt to minimize this:

  • Tin Snips
    These produce straight cuts quite quickly, but tend to warp the board badly, and can de-laminate the PCB near the edge.
  • Hack Saw
    Messy, quite time consuming, and can be difficult to produce perfectly straight edges. Doesn’t warp the board, but can leave burrs on the edge which need to be filed down afterwards.
  • Score-and-snap
    This is the method I use most of the time: clamp a steel ruler on top of the PCB with one edge lined up to where you want the cut to be. Score it a dozen times with a blade (with a lot of pressure). Flip the board over and do the same thing on the other side, being careful to align the cuts on both sides of the board. Snap the board, either over the edge of the desk, or with a clamp. The edge normally needs to be cleaned up a bit with a file. This is time consuming, but produces straight cuts and doesn’t usually warp the board.

Even with a perfectly flat board I would often get fuzzy regions. My first attempt to fix this was to use a weight to push the board, film, and glass sheet together. To do this I had to flip the UV enclosure upside down, then place the sheet of glass on top, followed by the film, the PCB, and a weight (usually some books about the same size as the PCB).

This worked much better than previously, but still wasn’t perfect. It turned out that the extra weight was causing the glass to bend slightly (I was using some glass from a cheap photo frame), which would cause the film and PCB to separate in some places, causing the fuzzy patches. The solution was to get some thicker glass. I ended up buying a 200mm x 200mm x 5mm piece of glass from a local glass shop, which doesn’t bend visibly, even with a couple of old university text books on top. Note that the exposure time will need to increase due to the glass and the extra distance from the UV source.

Posted in Electronics | Tagged , , , , | 4 Comments

Playing with the SUP500F GPS module

The SUP500F is a pretty nice unit: small, low power consumption (33mA), 10Hz update, and quick start up time (29 second cold start with an open sky).

Here it is on the breadboard:

I’m using a MAX232 to convert the RS-232 voltages from the PCs serial port to TTL (5V), and a simple voltage divider to reduce the 5V TTL signal to the 3V required by the SRF500F’s UART. Continue reading

Posted in GPS | Tagged | 1 Comment

Streaming UVC webcam video over 802.11n with a BeagleBoard

Here’s an overview of the general setup:

And a closeup of the BeagleBoard and the various bits and pieces required to stream the webcam images:

Physical components:

  • BeagleBoard (revision C4)
  • 2GB SD Card
  • USB Hub (USB 2.0, High Speed, powered). You’ll most likely need an externally powered hub as USB ports are only required to supply up to 100mA.
  • ASUS USB-N10 Wireless N USB adaptor
  • Logitech C600 webcam
  • 5V power supply
  • USB to RS-232 Serial cable.
  • IDC10 to DB9 cable.


  • Angstrom demo image.
    Angstrom is an embedded linux distribution. You’ll want the demo image to verify that your board is ok, and to use as a fallback if your generated system misbehaves.
  • Angstrom development environment.
    Used to rebuild and customize the Angstrom image, and you can also use its toolchain to cross-compile your own code.
  • Driver for N10 wireless adapter
    This is included in later linux kernels, but doesn’t seem to be available in Angstrom (you could probably modify the kernel config and recompile the kernel as an alternative to building the driver).
  • MJPG Streamer
    An application which can stream UVC web cam images over HTTP.

Continue reading

Posted in BeagleBoard | Tagged , , , | 25 Comments