How to wire up and configure an i2c device on Beaglebone

Hi,

I'm trying to connect an i2c device to the Beaglebone. I'm using the
Angstrom-Cloud9-IDE-eglibc-ipk-v2011.12-core-
beaglebone-2011.12.26.img.gz image.

I've read the other posts about using I2C with Beaglebone, as well as
Koen Kooi's blog post http://dominion.thruhere.net/koen/cms/using-the-beaglebone-as-a-weatherstation
(which is the most useful guide that I found).

Based on other posts, it seems that pins 19 and 20 on P9 are the best
ones to use, and that they require pullups.

I'm left with a few questions, which I think might be of interest to
fellow Linux newbies trying to use i2c:

1. Should the pullup resistors always be connected to 3.3V (as opposed
to some other voltage) on the Beaglebone? I used 5K resistors - is
that close enough? (the SRM says 5.5K).
2. Are pins 19 and 20 connected to i2c2 or i2c3? The SRM manual says
i2c2, but based on the results of i2cdetect and other posts I think
it's i2c3. Is there an i2c2 on the Beaglebone?
3. Should i2cdetect automatically find the i2c device at the correct
address if everything is hooked up correctly?
4. Do I always need to enter a command similar to the one in Koen's
article: "echo bmp085 0x77 > /sys/class/i2c-adapter/i2c-3/
new_device"? Is the "bmp085" part just a label that I choose, or does
it need to precisely match some setting in the device?
5.Is a 5V device like the BlinkM supported by the Beaglebone I2C? If
so, is the process for configuring it any different from the process
described in Koen's blog post? (This is the device I tried to get
working, and I'm guessing it's not supported).

Thanks,

Dan.

1. Should the pullup resistors always be connected to 3.3V (as opposed
to some other voltage) on the Beaglebone? I used 5K resistors - is
that close enough? (the SRM says 5.5K).

5k resistors should be fine (I used 4.7k with my device), and since
the I/O voltage on the board is 3.3V, you should only connect the pull-
ups to that. (Pin 3 or 4 on P9)

2. Are pins 19 and 20 connected to i2c2 or i2c3? The SRM manual says
i2c2, but based on the results of i2cdetect and other posts I think
it's i2c3. Is there an i2c2 on the Beaglebone?

The numbering in the OS seems to be different than the numbering in
the SRM. Pins 19 and 20 are on i2c2 in the hardware numbering scheme,
but in Linux, the device name is /dev/i2c-3.

3. Should i2cdetect automatically find the i2c device at the correct
address if everything is hooked up correctly?

That depends on your device and whether it will respond to the read
probes that i2cdetect uses, but in general, yes.

4. Do I always need to enter a command similar to the one in Koen's
article: "echo bmp085 0x77 > /sys/class/i2c-adapter/i2c-3/
new_device"? Is the "bmp085" part just a label that I choose, or does
it need to precisely match some setting in the device?

I just interact with my device using the i2cget and i2cset command
line tools, following the data sheet for my device to know what data
addresses on the device to set and get.

5.Is a 5V device like the BlinkM supported by the Beaglebone I2C? If
so, is the process for configuring it any different from the process
described in Koen's blog post? (This is the device I tried to get
working, and I'm guessing it's not supported).

I've never tried using a 3.3V master and a 5V I2C device, but I have
used this level shifter for the other direction with an Arduino (5V
master and 3.3V device):

(The description and comments were kind of confusing for this board.
I used the TX on channel 1 and 2 for the I2C SDA and SCL.)

Stan,
Thanks for the info. I was able to get i2cdetect to work with a 3.3V
device, and will give the level shifter a shot (when I have one) for
the 5V device.
Poking around further, I'm guessing the /sys/class/i2c-adapter
approach mentioned in my question #4 works only if there is a kernel
module for the device. For example, there is a kernel-module-bmp085
for the BMP085 barometric sensor.
For everything else, there is the i2cget and i2cset approach that you
recommended.
Thanks,
Dan.

Hi Dan,

Is there an i2c support within cloud9ide environment or more precisely within bonescript custom .js?

thanks

Dne sobota, 31. december 2011 22:07:43 UTC+1 je oseba Dan napisala:

I would like to ask the same question that klemenz is asking. Does cloud9 provide a framework to run i2c slaves with js or python?

yassyass, This seems to be 6yr old question ~ I got the Bone script JS working using cloud9 IDE for an MCP23017 last year -
I got it working on 4.4.54-ti-r93 and I think I had problems with the later build 4.4.68-ti-r108

I was beginner to BBB, but I had used I2C a lot in uP C env. I choose BBB to implement a project reading from a number of MCP23017 - and then it was used by JS networking that somebody else did

I found the documentation to be clear that it does work, and the code traceable… but it did take some digging, and as ever prototyping the interface, characterizing the interface and building on top of it. I used an adafruit prototype cape to prove I could interface to the I2C.

However I also found late into the project, that I could only init one I2C at a time… I wonder if anybody else found a way to have two I2C operational at the same time.??

My issue was that I wanted to add a number of MCP23017 - more MCP23017 than one I2C bus could support.

It was contract work for me, so here are some snippets,

enable-pins.sh:

sudo config-pin overlay cape-universaln
config-pin p9.17 i2c
config-pin p9.18 i2c
echo try: cat /sys/devices/platform/bone_capemgr/slots

BbbMcp23017.js:

var b = require(‘bonescript’);
var kelly_i2c = require(‘i2c’); //npm install i2c https://github.com/kelly/node-i2c

//From https://stackoverflow.com/questions/7545641/javascript-multidimensional-array
Array.matrix = function(numrows, numcols, initial) {
var arr = [];
for (var i = 0; i < numrows; ++i) {
var columns = [];
for (var j = 0; j < numcols; ++j) {
columns[j] = initial;
}
arr[i] = columns;
}
return arr;
}
var mcp_act1 = Array.matrix(2,8,false);
var locMcp0 = new kelly_i2c(mcp0_addr+0, {device : i2cloc_port});
//var remMcp0 = new kelly_i2c(mcp0_addr+0, {device : i2crem_port}); doesn’t seem to support init two different busses

//the mcp23017 B&Aregs are read into the following 16 bit array. b15-8(Binputs) b7-0(Ainputs)
//Init value represents OFF for all 16 stations
var mcpRead = Array.matrix(2,8,0); // [I2c#][mcp16bitIndex] 16bit station values

//******************************************************************************

if (zero) {
locMcp0.writeBytes(0x04,[0xff,0x03], function(err){ if (err) {mcp0_act[0]=false;console.log(‘writeBytes1 err’+err);} } );
if (typeof remMcp0 == ‘object’) {
remMcp0.writeBytes(0x0C,[0xff,0xff], function(err){ if (err) {mcp0_act[1]=false;console.log(‘writeBytes2 err’+err);} } );
} else {
mcp1_act[0]=false;
}

//Write INTCON 1 to each GPINTCON/0x08 GPINTENB to enable interrupt monitoring - DEFVAL is 0, so ints on GPIO PIN=1
locMcp0.writeBytes(0x08,[0xff,0xff], function(err){ if (err) {mcp0_act[0]=false;console.log(‘writeBytes1 err’+err);} } );
if (typeof remMcp0 == ‘object’) {
remMcp0.writeBytes(0x0C,[0xff,0xff], function(err){ if (err) {mcp0_act[1]=false;console.log(‘writeBytes2 err’+err);} } );
} else {
mcp1_act[0]=false;
}
}

if (1==mcpInputPullup) {
//Write 0xFF to each GPPUA/0x0C GPPUB/0x0D to enable pullup 100K, Bank=0
locMcp0.writeBytes(0x0C,[0xff,0xff], function(err){ if (err) {mcp0_act[0]=false;console.log(‘writeBytes1 err’+err);} } );
if (typeof remMcp0 == ‘object’) {
remMcp0.writeBytes(0x0C,[0xff,0xff], function(err){ if (err) {mcp0_act[1]=false;console.log(‘writeBytes2 err’+err);} } );
} else {
mcp1_act[0]=false;
}
}

mcp_poll(‘init’); //First time through, then on timer

function doMeter1(x) {
if(x.err) {
console.log('do1:x.err = ’ + x.err);
return;
}
timer_poll = setInterval(sweep1, poll_mcp_sec*993);
}

function sweep1() {
mcp_poll(’’); //only on this sweep
}

function mcp_poll(msg_dbg)
{
//var date = new Date();
//var timeNow = dateFormat(date,‘HH:MM:ss.l’);
var mcpNmLoc=0;
poll_count++;
//console.log(timeNow+’ [’+poll_count+’]’+msg_dbg +’ mcp0=’+mcp0_act[0]+’ mcp1=’ +mcp1_act[0]);

if (true == mcp1_act[mcpNmLoc]) {
// console.log(‘mcp1_act[’+mcpNmLoc+’] poll’);
//Set mcp addr to GPIOA 0x12 or INTFA 0x0E
remMcp0.writeByte(0x12,function (err) { if (err) { console.log(‘mcp1wr:’+err.message); } });
remMcp0.read(2, function(err,rdData) {
if (err) {
console.log(‘mcp1rd:’+err);
mcp1_act[mcpNmLoc]=false;
} else {
onReadMcp1(mcpNmLoc,rdData);
}
});
}

mcpNmLoc=0;
/* Called last so that it runs update_pwm_all() */
if (true == mcp0_act[mcpNmLoc]) {
//console.log( ‘mcp0_act[’+mcpNmLoc+’] poll’);
//Set mcp addr to GPIOA 0x12 or INTFA 0x0E
locMcp0.writeByte(0x12,function (err) { if (err) { console.log(‘mcp0wr:’+err.message); } });
locMcp0.read(2, function(err,rdData) {
if (err) {
console.log(‘mcp0rd:’+err);
mcp0_act[mcpNmLoc]=false;
} else {
onReadMcp0(mcpNmLoc,rdData); //This does work of recording data

////act on it
}
});
} else {
console.log(“mcp0_act false, error no flow Output generated”);
}
}

function onReadMcp0(mcpNmRd,rdValue) {
mcpRead[0][mcpNmRd] =rdValue[0] | (rdValue[1]<<8);
//console.log(‘mcpRead[0][’+mcpNmRd+ ‘]=’ +mcpRead[0][mcpNmRd].toString(hex) );
}

how many do you need ? you can have up to 8 of these devices
if you need more there are other port expanders that are on different
addresses

Hello evilwulfie
I think initially the objective was 240 inputs. So there is always another solution :slight_smile: but in this case I was assuming to use the same the same hardware - expanded as stackable capes - but just route the bus differently to another I2C input. Of course I didn’t prototype two I2C busses - if I had then I could also have just put in an I2C bus buffer and expanded that way. In the end, the hardware designer was rushed and the digital fan in wasn’t as dense as expected and the expansion was limited to the 8 I2C addresses or 128 inputs. Anyway I added the information about the 2nd I2C bus. I’m grateful for who ever did the interface code and made it available as a lib. :slight_smile: