Home / Tutorials / BeagleBone Tutorial / Beaglebone Black I2C Tutorial
pcbway
beaglebone black i2c
BeagleBone Tutorial

Beaglebone Black I2C Tutorial

I2C is a popular communications protocol and is used by a lot of sensors and devices. This is why most microcontrollers, including Arduino, PICs, and STM32 have I2C support. In this tutorial, we will look at how to use the I2C protocol on the BBB and create a simple Beaglebone Black I2C application.

Beaglebone Black I2C Bus

There are three I2C buses on the Beaglebone Black according to the AM335X Technical Reference Manual and their memory addresses are:

  • i2c-0: 0x44E0_B000
  • i2c-1: 0x4802_A000
  • i2c-2: 0x4819_C000

The i2c-0 bus is not accessible on the header pins while the i2c-1 bus is utilized for reading EEPROMS on cape add-on boards and may interfere with that function when used for other digital I/O operations.

beaglebone black i2c pinouts

The i2c-2 bus is the one that is free for use so we'll be using that in this tutorial.

Linux I2C Tools

Thankfully, Linux has built-in i2c tools that make our lives easier (unlike with BBB PWM). To check which of the three buses are enabled we can use i2cdetect:

root@arm:~# i2cdetect -l
i2c-0   i2c             OMAP I2C adapter                        I2C adapter
i2c-2   i2c             OMAP I2C adapter                        I2C adapter

Mine's showing two i2c devices. But again we can't use i2c-0 so we'll go with i2c-2.

To detect the devices connected to i2c-2:

root@arm:~# 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] y
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- UU UU UU UU -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- 68 -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
root@arm:~#

Those addresses with UU are reserved addresses. Noticed there is a 68. That's because I connected a device with an I2C address of 68 to my Beaglebone Black.

Writing and Reading from the I2C Bus

Now, to write to the I2C bus, we can use:

i2cset -y 2 0x68 0xf4 0x34

The first hex number is the I2C device address followed by the specific data address and the byte to be written. You can read more about the i2cset at https://linux.die.net/man/8/i2cset.

To read the registers from the device connected to the I2C bus, the i2cdump command can be used:

root@arm:~# i2cdump -y 2 0x68 w
     0,8  1,9  2,a  3,b  4,c  5,d  6,e  7,f
00: 01ff ff01 2dff af2d 0faf 050f 9005 fb90
08: 0bfb 050b 4405 2844 7028 6e70 946e c694
10: 00c6 0000 0000 0000 0000 0000 0000 0000
18: 0000 0000 0000 0000 0000 0000 0000 0000
20: 0000 0000 0000 0000 0000 0000 0000 0000
28: 0000 0000 0000 0000 0000 0000 0000 0000
30: 0000 0000 0000 0000 0000 0000 0000 0000
38: 0000 0100 cd01 54cd 25e8 9825 04cc 4804
40: f454 70f4 ff50 d4ff 01de ca01 00be 8800
48: 0078 0000 0000 0000 0000 0000 0000 0000
50: 0000 0000 0000 0000 0000 0000 0000 0000
58: 0000 0000 0000 0000 0000 0000 0000 0000
60: 0000 0000 0000 0000 0000 0000 0000 0000
68: 0000 0000 0000 0000 0000 3000 2031 1307
70: 0000 0000 0000 0000 0000 0068 0000 0000
78: 0000 0000 0000 0000 0000 0000 0000 ff00
80: 01ff ff01 2dff af2d 0faf 050f 9005 fb90
88: 0bfb 050b 4405 2844 7028 6e70 946e c694
90: 00c6 0000 0000 0000 0000 0000 0000 0000
98: 0000 0000 0000 0000 0000 0000 0000 0000
a0: 0000 0000 0000 0000 0000 0000 0000 0000
a8: 0000 0000 0000 0000 0000 0000 0000 0000
b0: 0000 0000 0000 0000 0000 0000 0000 0000
b8: 0000 0100 cd01 00ce 2400 6824 04bc 9c04
c0: f4e8 70f4 ff50 bcff 01ae 7201 0072 8500
c8: 0084 0000 0000 0000 0000 0000 0000 0000
d0: 0000 0000 0000 0000 0000 0000 0000 0000
d8: 0000 0000 0000 0000 0000 0000 0000 0000
e0: 0000 0000 0000 0000 0000 0000 0000 0000
e8: 0000 0000 0000 0000 0000 3600 2137 a020
f0: 0000 0000 0000 0000 0000 0068 0000 0000
f8: 0000 0000 0000 0000 0000 0000 0000 ff00

Read more about i2cdump here: https://linux.die.net/man/8/i2cdump

Finally, we can acquire the data from a specific register on the I2C device using i2cget:

root@arm:~# i2cget -y 2 0x68 0x87
0xff

Here's more information for i2cget: https://linux.die.net/man/8/i2cget.

In the next part of this tutorial, we'll be reading data from the MPU6050 gyroscope + accelerometer and displaying it on the Beaglebone Black terminal. Follow this blog for updates!

0 0 votes
Article Rating
Subscribe
Notify of
guest
29 Comments
Oldest
Newest Most Voted
kripashree
kripashree
8 years ago

Hi,

I am facing one problem while doing i2cset and i2cget.But in different board.
I am using AMD MF bettong DDR4 board.
kernel version is : 4.4.11-158-amd+

I am doing i2cset works fine.
But i2cget reads 0xff all the time.

commands used is:
sudo i2cset -y 6 0x50 0x6c 00
sudo i2cget -y 6 0x50 0x6c

i2cdump also reads 0xff all the time irrespective of the value written!!!

cae@cae-Bettong:~$ sudo i2cdump 6 0x50
No size specified (using byte-data access)
WARNING! This program can confuse your I2C bus, cause data loss and worse!
I will probe file /dev/i2c-6, address 0x50, mode byte
Continue? [Y/n] y
0 1 2 3 4 5 6 7 8 9 a b c d e f 0123456789abcdef
00: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ................
10: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ................
20: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ................
30: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ................
40: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ................
50: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ................
60: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ................
70: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ................
80: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ................
90: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ................
a0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ................
b0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ................
c0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ................
d0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ................
e0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ................
f0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ................
cae@cae-Bettong:~$

Please let me know why i am not able to write to EEPROM?

I am using one i2c test application to receive i2c 1 or 2 bytes.After running which only i2c slave will be attached to i2c bus!

And also running the application changes the register values,which is read using printk() in the driver.

That time also i2cdump or i2cget reads 0xff !!!!

Why is this happening?? can anyone please let me know?

Thanks & Regards,
Kripashree

mahmoud saati
8 years ago

hello, im trying to scan the registry of for i2c address ("KSZ9897R" 7-Port Gigabit Ethernet Switch with Two RGMII/MII/RMII Interfaces) , on the schematic it's writing that the address is :0xBE which i didnt find it, and there is another address for the poe+ which is: 0x20 i already found it.

i use this commande i2cdetect -r 2 and its ok, but the issue that the range of this commande is " 0x03-0x77."

and the address that im looking for is 0xBE, which is obviously outside of this range, what i can do to have a bigger range to scan so i can catch the address im looking for.

thx you

mahmoud saati
8 years ago

debian@beaglebone:~$ 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] y
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: 20 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: 30 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: 50 -- -- -- UU UU UU UU -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --

mahmoud saati
8 years ago

hello. how i can enlarge the rang in the beagle bone to scan the registry from 0x03-0x77, to more than that till i reach the address 0xBE, because the address i'm searching for is 0xBE it's for an Ethernet switch "KSZ9897R"

mahmoud saati
8 years ago
Reply to  Roland Pelayo

hello,, thx for your reply, i tried this command but it seems that the beaglebone doesnt support this range, it says out of rang, this is the result of the commande

Last login: Mon Feb 5 15:33:33 UTC 2018 on ttyGS0
Linux beaglebone 4.4.9-ti-r25 #1 SMP Thu May 5 23:08:13 UTC 2016 armv7l

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
debian@beaglebone:~$ i2cdetect -r 2 0x00 0xBE
Error: FIRST argument out of range (0x03-0x77)!
Usage: i2cdetect [-y] [-a] [-q|-r] I2CBUS [FIRST LAST]
i2cdetect -F I2CBUS
i2cdetect -l
I2CBUS is an integer or an I2C bus name
If provided, FIRST and LAST limit the probing range.
debian@beaglebone:~$

Yasir
Yasir
8 years ago

What a great tutorial.
Did you have to pull up the I2C connection to be able to detect the device?

Yasir
Yasir
8 years ago
Reply to  Roland Pelayo

Thanks for that Roland, It seems as though my device isn't being picked up with i2cdetect and I was suspecting that it would require a pull up resistor but unsure at this stage. What would you do to test that?

Yasir
Yasir
8 years ago
Reply to  Roland Pelayo

Hi Roland,

I seem to have got the address successfully.

I am driving an LED array using an ISSI IS31FL3741 LED driver which is apart of their Evaluation Board. I am trying to hook up the BeagleBone to be able to send i2c commands to the uC onboard the evaluation board and toggle the LED's.

Yasir
Yasir
8 years ago
Reply to  Roland Pelayo

Hi Roland,

It still seems confusing as to how one can write a program to write to an I2C slave device and control. Command line is great but writing a script that could be run and looped is something that I am still looking into. Any advice?

Yasir
Yasir
8 years ago
Reply to  Roland Pelayo

Thanks for that Roland, I was not aware of that possibility and will start experimenting with it immediately.
How would you set the clock frequency with those commands? Since the slave would only operate at either 400kHz or 1Mhz. I assume real-time communication is not possible with this method on the BBB?

Yasir
Yasir
8 years ago
Reply to  Roland Pelayo

PRU's are definitly what caught my attention when selecting the beaglebone for their realtime capabilities and potential of using processor heavy tasks with linux to control the PRUSS is really promising. I hope it gets clearer as to how one could tap into the PRUSS as it does not seem to be similar to programming an AVR microcontroller at all.

mahmoud saati
8 years ago

hello, thank you for answering me, im using beagle bean green, does that make any difference?

i tried what you've told me to do, but it didnt work too.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
debian@beaglebone:~$ i2cdetect -r 2 0x03 0x5F
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-0x5f.
Continue? [Y/n]
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- 0c -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: 20 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: 30 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: 50 -- -- -- UU UU UU UU -- -- -- -- -- -- -- --
60:
70:
debian@beaglebone:~$ i2cdetect -r 2 0x03 0x5F
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-0x5f.
Continue? [Y/n]
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: 20 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: 30 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: 50 -- -- -- UU UU UU UU -- -- -- -- -- -- -- --
60:
70:

about the address of the ship as u said i found this in the datasheet of the device:

The management interface may be configured to be an I2C slave. In this mode, an I2C master has complete programming
access to the device's internal control and status registers, including all MIB counters, address lookup tables,
VLAN table and ACL table.
The 7-bit device address is fixed as 1011_111. Because of the fixed address, only one KSZ9897R may be on the I2C
bus at a time. The R/W control bit is then appended as the least significant bit to form these 8-bit address/control words:
1011_1110
1011_1111

mahmoud saati
8 years ago

hello Roland,

i have an evaluation board for this ship ( EVB-KSZ9897) i run the i2cdetect command and it gives me the address 0x5f.

on my board i have some different values for the resistors like 1k ohms for both scla and sda, and for the led3_1 i tested on the oscilloscope it give logic output 1 but i put already 10k to the vddio, and the led4-1 the resistor was 220 ohms i changed to 1k, than i ran the order again but nothing happen always the same result as before.

mahmoud saati
8 years ago

hello Rolland,

thx for you help, i found the problem last week, it was a crystal issue, but now i have another issue that the internet is intermittent when i want to use it as PoE, but when i use the data only it's good, im investigating about that, thx for your help 🙂

navi golen
navi golen
8 years ago

can anyone post c++ code for i2c. i am working with battery fuel gauge. my c++ does not work on it.

John
John
7 years ago

I built a system around a BeagleBone Black Rev some time ago with the I2C bus connected to Pins P9-19 (SCL) and P9-20 (SDA). I have three or four prototypes configured that way, they all work fine and and I have not touched the I2C code for quite some time.

I recently bought another BeagleBone Black Rev C from Mouser and it was manufactured by GHI. I plugged it into an existing system and installed the SD memory from a functioning system into it and could not see any activity on the I2C bus, nothing. I Swapped it with the BBB originally in the system and that BBB worked fine. I swapped again and the new one still would not communicate over the I2C bus. I tried the new one on two other systems with the same results. I contacted GHI and the sent a replacement. It doesn't work either. Everything on these two new BBB Rev C works fine except this bus.

Since the memory os POP right on top the processor I can't tell it the processor is the same between the old BBB and the new BBB. I suspect that TI may have rev'ed the silicon and this bus is no longer available on these pins.

Any one have any idea what is going on here.

thanks,
john

Raj Mehta
Raj Mehta
5 years ago

Aim: Work with three I2C Slave devices.

All three devices have the same address 0x29. so differentiate slave device address need different i2c address. How to set Slave Device Address in BeagleBone Black.

Mike
Mike
4 years ago

Trying to work with i2c device and i2c-tools on beaglebone.
Need to issue general call reset according NXP's I2C documentation (UM10204) which I understand is at address 0x00 with value 0x06.

Didn't work for me with i2cset -y -a 2 0x00 0x06

Is there a hint how to apply general reset with i2c-tools?

Thanks a lot

Index