The GatuHomeLab (2.1) - BeagleBone Black I2C Communication in Java
The BeagleBone Black maximum voltage we can apply to the pins for analog to digital converter is 1.8V. As many outputs from analog devices are 3 to 5V, I think it is better, also to protect the board, to use an I2C ADC converter.
This is what we will use for our example.
- a BeagleBoneBlack Rev C.
- An I2C ADC 12 bits (Seeedstudio link)
- An Accelerometer / or another analog device to measure
For the example we will use a three axis accelerometer, but any device with analog output will work fine in this case.
BeagleBone Black Operating System
We are using Debian, with latest version from http://beagleboard.org/latest-images
We have an explanation in this web page (http://datko.net/). Basically we have to identify the port and the linux address...
To do that we have to take into consideration that the BBB has three I2C buses:
i2c0: Not exposed in the expansion headers / 0x44E0_B000
i2c1: pins P9 17,18 (and 24,26) / 0x4802_A000
i2c2: pins P9 19,20 (and 21,22) / 0x4819_C000
Let's check which one we can use...
root@beaglebone:~# ls -l /sys/bus/i2c/devices/i2c-* lrwxrwxrwx 1 root root 0 Jan 1 2000 /sys/bus/i2c/devices/i2c-0 -> ../../../devices/ocp.2/44e0b000.i2c/i2c-0 lrwxrwxrwx 1 root root 0 Jan 1 2000 /sys/bus/i2c/devices/i2c-1 -> ../../../devices/ocp.2/4819c000.i2c/i2c-1
Here we can see that the 4819c address, that correspond to the I2c2 bus (using pins P9 19 and 20), it is mapped in our Linux BBB as i2c-1.
Connect the ADC as per the previous image, taking care to connect properly SCL and SDA to P9-19 and P9-20 respectively.
Then we can check with the command i2cdetect if we can see the ADC (in the command we indicate "1" because we are using the i2c-1 in linux)
root@espinete:/home/borja# i2cdetect -r 1 WARNING! This program can confuse your I2C bus, cause data loss and worse! I will probe file /dev/i2c-1 using read byte commands. I will probe address range 0x03-0x77. Continue? [Y/n] Y 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: — — — — — — — — — — — — — 10: — — — — — — — — — — — — — — — — 20: — — — — — — — — — — — — — — — — 30: — — — — — — — — — — — — — — — — 40: — — — — — — — — — — — — — — — — 50: 50 — — — UU UU UU UU — — — — — — — — 60: — — — — — — — — — — — — — — — — 70: — — — — — — — —
Attention: The I2C ADC that we are using has the default address of 0x55. The BeagleBone Black has reserved this address for some EEPROM communication... so we can not use it. We had to change the I2C address to another one outside that range, to 0x50. Then we can see it answering in the previous example ("50").
To access the pins and the I2C bus from our java code, we will use LibBullDog. This is a wonderful library, that will allow us to interact with the devices attached to the BBB, and give us the power of java programming language in a Debian Linux environment.
We will make our own package with wrappers to use the library and adapt it to our code. To speak with an I2C device, we need to follow a protocol. That means that many times we have to write commands in certain registers, and configure the device to ask for readings. Then it is very useful to make these wrappers, where you put all this work, as a black box, and later you just take care of the project you are working in.
The ADC is based in the ADC121C021, so we have to find the datasheet and read it to find out the protocol. We have also the code for Arduino in the Seedstudio page where it also shows how it works, and we can use it to make our own in Java.
Here the link to the files for this post -- source code --
public class ADCi2c extends I2cDevice{ byte REG_ADDR_RESULT=0x00; byte REG_ADDR_CONFIG=0x02; //constructor public ADCi2c(I2cBus bus, int address) { super(bus, address); } //constructor public ADCi2c(I2cConnection connection) { super(connection); } //methods public void initMode() { try { this.open(); System.out.println("ADCi2c::initMode:: open ok"); this.writeByte(REG_ADDR_CONFIG); //select the CONFIGURATION REGISTER OF THE ADC System.out.println("ADCi2c::initMode:: write byte 0x02 ok"); this.writeByte(0x20);//set sampling rate to 27ksps System.out.println("ADCi2c::initMode:: write byte 0x20 ok"); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); System.out.println("ADCi2c::initMode::error "+e.toString()); } } public void closeMode() { try { this.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); System.out.println("ADCi2c::closeMode::error "+e.toString()); } System.out.println("ADCi2c::closeMode:: close ok"); } public int readIntValue() { byte[] buffer = new byte[2]; try { this.writeByte(REG_ADDR_RESULT); this.readBytes(buffer); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } int intValue = (((BulldogUtil.getUnsignedByte(buffer[0]) << 8)) | BulldogUtil.getUnsignedByte(buffer[1])); return intValue; } }
The class extends the I2cDevice from LibBulldog. The construction it is done telling which bus we are using, and the address for the device. Then we use the initMode() to configure the device, and we can then start reading values. When we are done, we just close with closeMode().
We are connecting an accelerometer to the ADC. So we can make now a class to use the previous one, and get the data as we please, the ADCi2c_Accelerometer.
Here the link to the files for this post -- source code --
public class ADCi2c_Accelerometer{ I2cBus bus; int address; String I2Cbus; ADCi2c adc; String I2C; public ADCi2c_Accelerometer(int address, String I2C) { this.address=address; this.I2C=I2C; } /* * Starts the communication with the ADC * getting ready for reading from the Accelerometer * */ public void init() { final Board board = Platform.createBoard(); I2cBus bus = board.getI2cBus(I2C); adc=new ADCi2c(bus,address); adc.initMode(); } /* * Close the communication with the ADC * */ public void close(){ adc.closeMode(); } /* * Get Accelerometer value from ADC * */ public int getValue(){ return adc.readIntValue(); } }
In the next post we will see how to make the executable jar file and put it in the BeagleBone Black.