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. 0×70 << 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. Continue?
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] 0x00 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] 0x3b
So here the result is 0x003b=59 centimeters. All pretty easy if you can get the level translation issue sorted.

> … 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.
I don’t know about Australia, but I got a MAX3372 very cheap here in Germany:
I ordered a free sample on the maxim-homepage, which was completely free of charge (incl. shipping). Maybe that’s worth a try (next time….)
(On the other hand, I still struggle with connecting I2C-devices. I only get “remote I/O error”. But maybe I made a mistake on soldering that tiny SMD to my adapter…..)
Thanks for this, I used a P82B96 from TI as they are one of a dwindling few companies that send free samples to australia for university students. Using the i2c tools commands you specified I’m able to get my beagleboard XM to communicate with an arduino running at 5V. Thanks again for sharing this!
hi,
nice post! one question: for i2c you need two pullups for each wire. are the pullups in the beagleboard included or have you added them external?
sorry for my bad english!
thanks a lot!
Hi. If you’re using the TXS0102 for the level conversion it has built in pull-up resistors. If you’re not using that you will need pull-up resistors as the beagleboard unfortunately doesn’t have any. Good luck!
Hi, nice post! i have a question. It seems (from your picture) that you connected the OE pin of the TXS0102 to 5V, while on the datasheet it says to be 1.8V referenced; so is this a mistake ? or was it intentional ?
I’m saying this cause i’m trying to do “mostly” the same thing and i connected the OE pin to 1.8V, but i don’t see anything listed on my “i2cdetect -r 2″ output; so i was wondering if that might be what i’m doing wrong.
Hi – you’re right it should be referenced to 1.8V. I’ve used 1.8V on some later boards and that does seems to work correctly. Definitely worth getting your hands on an oscilloscope or logic analyser when you’re sorting out I2C issues. I use a cheap DSO Nano v2 with the Benf firmware). Good luck!
thank you for your reply. OE pin doesn’t seem to be my problem, however i’m thinking that MUX configuration might be wrong on my Beagle, so i’m messing with it right now.
i’ll definitely get my hands on an oscilloscope in a couple of days, meanwhile thank you.