Tag Archives: i2c

I got I2C working well a couple of weeks back and got both the modules I am using working well with the beaglebone. I later modified the code to allow API calls to read the values from the two modules. Now I have a proper working directory for the complete project and I’ve decided to test out other things separately and then import them into this single working directory.

This post is to describe how to get the I2C working on the Beaglebone. I got some help from https://github.com/quick2wire/beaglebone. The only problem was that I planned on using C/C++, not python, for better support with OpenCV. I’ll explain the protocol along with the code together. This post assumes you know a bit of electronics. Make sure you don’t connect any 5V supply to any of the beaglebone pins and don’t draw too much power. This means you should only use modules which are working on 3.3V logic and not on 5V logic! If they are 5V logic, you’ll need to some some sort of voltage divider or so. I will not delve into this on this post. If you’re doubtful about something, please feel free to ask me because a wrong connection could be the death of your board (As I’ve read on some other posts).

or the corresponding cpp header files. The i2c-dev.h gives you access to the i2c protocols.

What you need to understand about I2C is that it is a bus. You can connect multiple devices to the same two wires on the Beaglebone. There are three such buses on the Beaglebone and the third is the most accessible. I2C has just two pins required, the serial data and the serial clock. Bus 3, from the datasheet, is located on P9 at pins 19 and 20.

Since we are working with Linux, we don’t need to deal with the low level protocol. We directly connect these two pins with the corresponding pins on the module. Of course, you’ll need to power up the module. In my case, it need a five volt power supply and 3.3 logic voltage. DO NOT POWER THE MODULE USING THE BEAGLEBONE! Some ports may be able to do so but I’m not sure exactly which ones and even then, the power limits are fairly low so I suggest using a separate power supply. (I used an arduino’s 5V supply). The logic supply can be obtained from pins 3 and 4 on P9 on the beaglebone. Make sure you common the ground with the beaglebone’s GND pins at pins 1 and 2 on P9.

After connecting your module and powering it on, try this command in the bash terminal:

i2cdetect -y -r 3

i2cdetect is a part of the package i2ctools. This command will read all the devices on your I2C bus 3 and show you the addresses. My output looks like this:

I’ll post my output the next time I hook it up

Note the addresses of you devices and check with the datasheet to see if they match. Each I2C bus has a maximum of 128 address (And thus 128 devices can be connected to it). Most devices have a unique unchangeable address. Some have a register which can change one or two bits in the address so that you can connect two or more of the same modules. You can directly set the registers with i2cset and read the registers using i2cget from the command line. The syntax is follows:

I2C_SLAVE is a I2C variable defined in the i2c-dev.h header. address is the address of the device which you found in i2cdetect or from your datasheet. You need to do this each time you want to change the device. I made this into a function with an argument for the address.

Now you just need to read or write the data. I made functions for each. Let’s analyze the commands. This is for write:

n is the number of bytes you want to send. The first byte should be the register address and in this case, the second byte is the data to be written. Multiple bytes can be sent if the register is to hold multiple bytes but I haven’t yet seen such a case so I am not too sure about that. To read is just slightly more complex. You first write out the register address you want to read from and then accept incoming data.

Change n to the number of bytes you expect to read. Generally it is one but some devices allow you to send back multiple bytes by oring the register address with 0x80 (In my case, at least… Check your datasheet for this). The output will be at I2C_RD_Buf. And you’re done. Except one thing. Make sure you close the i2c handle like so:

You can use it. You need to compile i2c.cpp with -c flag, include the i2c.h file in you main and then compile. A makefile would be the simplest to do this. I’ve included an example. It is just arbitrary so do modify it for your purposes.