-
Notifications
You must be signed in to change notification settings - Fork 9
I2C
Note: the Raspi chip has hardware bugs related to clock stretching and repeated start conditions. If you need those features, use a I2C implementation in software ("bit-banging"):
- i2c-gpio device tree overlay, or
- bbI2CZip from pigpio.
Sparkfun has a nice tutorial on I2C: https://learn.sparkfun.com/tutorials/i2c
You also might want to try the sense hat which contains a number of interesting i2c peripherals.
Check that local.conf contained a line
ENABLE_I2C = "1"
when the image was bitbaked. This ensures that the following settings are present. Otherwise you have to change the manually (which is okay unless you go to production)
On the running RasPi: check/enable I2C in the config.txt file (reboot needed after change)
dtparam=i2c_arm=on dtparam=i2c_arm_baudrate=100000
dmesg | grep -i i2c
should show a line like
[ 1.998278] bcm2708_i2c 3f804000.i2c: BSC1 Controller at 0x3f804000 (irq 83) (baudrate 100000)
lsmod
should show that kernel module i2c_bcm2708
is loaded.
To use the i2c-tools, load kernel module i2c-dev
:
modprobe i2c-dev
And check for i2c devices on i2c bus 1, the i2c bus available on the expansion header:
root@raspberrypi3:~# i2cdetect -y 1 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- --
No i2c devices are connected in this example, but you may see i2c probing by using a scope.
Now, a InvenSense 9-axis sensor MPU-9250 was connected, using its default address 0x68:
root@raspberrypi3:~# i2cdetect -y 1 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- 68 -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- --
Dump the content of all registers:
root@raspberrypi3:~# i2cdump -y 1 0x68 b 0 1 2 3 4 5 6 7 8 9 a b c d e f 0123456789abcdef 00: bc c7 df 23 9c 02 f4 e0 07 e2 08 01 00 60 5b 67 ???#????????.`[g 10: d8 d6 d0 00 00 00 00 00 00 00 00 00 00 00 00 00 ???............. 20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 30: 00 00 00 00 00 00 00 00 00 00 01 ff bc 05 00 c2 ..........?.??.? 40: 50 07 b0 fe ae 00 a7 00 75 00 00 00 00 00 00 00 P????.?.u....... 50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 60: 00 00 00 00 00 00 00 00 00 00 00 01 00 00 18 71 ...........?..?q 70: 00 00 00 00 00 71 00 e6 20 00 e6 d8 00 23 b2 00 .....q.? .??.#?.
- 9-axis sensor: 3-axis gyroscope, 3-axis accelerometer and 3-axis compass
- on-chip µC capable of processing sensor fusion algorithms
Available on a convenient SparkFun IMU Breakout - MPU-9250 board: https://learn.sparkfun.com/tutorials/mpu-9250-hookup-guide
By default, the chip uses I2C address 0x68. After reset, register 0x75 ("WHO_AM_I") contains a unique value: 0x71. lets check that out: connect the breakout board to the RasPi.
root@raspberrypi3:~# vi mpu9250.c
#include <stdio.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <string.h>
int main()
{
int file = open( "/dev/i2c-1", O_RDWR);
if (file < 0) perror("open"); //TODO: error handling
unsigned char inbuf[1];
unsigned char outbuf[1];
struct i2c_rdwr_ioctl_data packets;
struct i2c_msg msg[2];
// prepare the first i2c request (a write)
msg[0].addr = 0x68; // device address
msg[0].flags = 0; // type of request: 0=write
msg[0].len = sizeof(outbuf); // number of bytes to write
msg[0].buf = outbuf; // pointer to the first data byte
outbuf[0] = 0x75; // first data byte: register to read
msg[1].addr = 0x68; // device address
msg[1].flags = I2C_M_RD | I2C_M_NOSTART; // read request without an intermediate start condition
msg[1].len = sizeof(inbuf); // number of bytes to read
msg[1].buf = inbuf; // // pointer to the first byte to read
// send both requests to the device
packets.msgs = msg;
packets.nmsgs = 2;
if(ioctl(file, I2C_RDWR, &packets) < 0) perror("ioctl"); //TODO: error handling
close(file);
printf("reg[0x%02x]=0x%02x\n", outbuf[0], inbuf[0] );
return 0;
}
root@raspberrypi3:~# gcc -o mpu9250 mpu9250.c
root@raspberrypi3:~# ./mpu9250
reg[0x75]=0x71
see http://www.netzmafia.de/skripten/hardware/RasPi/Projekt-RTC/
see Method 2: Instantiate the devices explicitly in https://www.kernel.org/doc/Documentation/i2c/instantiating-devices
https://gist.github.com/jnewc/f8b668c41d7d4a68f6e46f46e8c559c2
https://github.com/raspberrypi/linux/blob/rpi-4.9.y/drivers/pwm/pwm-pca9685.c
driver: https://github.com/raspberrypi/linux/blob/rpi-4.9.y/drivers/rtc/rtc-ds1307.c