Подключение устройств по i2c к различным платформам
Шпаргалка по подключению устройств по i2c к Raspberry PI, роутеру с openWRT и arduino совместимых устройств.
Инициализация i2c на роутере с OpenWRT:
подключаем к пинам 19-SDA, 18-SCL
# opkg update
# opkg install kmod-i2c-gpio-custom i2c-tools
# insmod i2c-gpio-custom bus0=0,19,18
, где 19 - SDA, 18- SCL
Проблема отсутствия i2c-tools в . Забираем из предыдущих репозиториев:
cd /tmp
opkg install libi2c_2013-12-15-1_ar71xx.ipk i2c-tools_2013-12-15-1_ar71xx.ipk
reboot
ls /dev | grep i2c
# i2cdetect -y 0
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- 27 -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- 38 -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: 50 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- 68 -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
Инициализация i2c на Rasberry PI:
Подключаем к пинам 3-SDA,5-SCL.
sudo apt-get install i2c-tools
ls /dev | grep i2c
Часы реального времени и EEPROM на Raspberry PI
Открываем файл sudo nano /etc/modules, добавляем к имеющемуся тексту и сохраняем следующие строки:
i2c-bcm2708
i2c-dev
rtc-ds1307
Открываем файл sudo nano /etc/modprobe.d/raspi-blacklist.conf и закомментируем в нем все строки
# reboot
Записать в /etc/rc.local перед end или запустить вручную:
echo ds1307 0x68 > /sys/class/i2c-adapter/i2c-1/new_device
Считать время # sudo hwclock –r
Записать системное время # sudo hwclock –w
Синхронизировать системное время # sudo hwclock –s
Пример записи и чтения в EEPROM:
#!/bin/sh
#set BUS to an appropriate I2C bus number
BUS=1
# покажем устройства
i2cdetect -y $BUS
# the following sets the memory pointer to the beginning address of the eeprom.
# установка адреса чтения
i2cset -y $BUS 0x50 0x00 0x00
#write some bytes .Запись
i2cset -y $BUS 0x50 0x9 0x0 0xab i
i2cset -y $BUS 0x50 0x9 0x1 0xbc i
i2cset -y $BUS 0x50 0x9 0x2 0xcd i
i2cset -y $BUS 0x50 0x9 0x3 0xde i
i2cset -y $BUS 0x50 0x9 0x4 0x9a i
#set pointer to start. Установка адреса чтения
i2cset -y $BUS 0x50 0x9 0x0
#every read will increment the pointer. Читаем
i2cget -y $BUS 0x50
i2cget -y $BUS 0x50
i2cget -y $BUS 0x50
i2cget -y $BUS 0x50
i2cget -y $BUS 0x50
i2cget -y $BUS 0x50
i2cget -y $BUS 0x50
i2cget -y $BUS 0x50
Часы реального времени и EEPROM на OpenWRT
Работа с EEPROM аналогична с Raspberry PI, но с часами возникли проблемы. Дело в том что в репозиториях chaos_calmer / 15.05.1 generic отсутствует пакет kmod-rtc-ds1307_3.18.23-1_ar71xx.ipk, а из nand он не устанавливается.
Есть вариант работы с часами через i2c-tools:
# i2cdump -y -f -r 0-6 0 0x68 c
0 1 2 3 4 5 6 7 8 9 a b c d e f 0123456789abcdef 00: 46 09 10 03 17 09 17 F??????
Первые 7 байт вывода - это секунды, минуты, часы,ХЗ, день, месяц,год (17 Sep 2017 10:09:46)
Первоначальный запуск часов:
i2cset -y 0 0x68 0x00 0x00
Установка времении:
i2cset -y 1 0x68 0 0x00 №секунды
i2cset -y 1 0x68 1 0x12 №минуты
i2cset -y 1 0x68 2 0x22 №часы
Чтение времени
i2cget -y 1 0x68 0 №секунды
i2cget -y 1 0x68 1 №минуты
i2cget -y 1 0x68 2 №часы
Часы реального времени и EEPROM на arduino
Установить библиотеку RTClib в arduinoIDE:
https://github.com/adafruit/RTClib/archive/master.zip
https://learn.adafruit.com/ds1307-real-time-clock-breakout-board-kit/understanding-the-code
Расширитель портов на pcf8574
Расширитель портов на pcf8574

echo pcf8574 0x38 > /sys/bus/i2c/devices/i2c-0/new_device
cat /sys/kernel/debug/gpio
GPIOs 56-63, i2c/0-0038, pcf8574, can sleep:
gpio-60 (sysfs ) out lo
echo 60 > /sys/class/gpio/export
echo out > /sys/class/gpio/gpio60/direction
echo 0 > /sys/class/gpio/gpio60/value
root@ZEON-TBR:~# i2cdetect 0
WARNING! This program can confuse your I2C bus, cause data loss and worse!
I will probe file /dev/i2c-0.
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: -- -- -- -- -- -- -- 27 -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- 38 -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
root@ZEON-TBR:~# i2cset -y 0 0x38 0x01
root@ZEON-TBR:~# i2cset -y 0 0x38 0x00
root@ZEON-TBR:~# i2cset -y 0 0x38 0x08
root@ZEON-TBR:~# i2cset -y 0 0x38 0x0f
root@ZEON-TBR:~# i2cset -y 0 0x38 0x00 0x10
root@ZEON-TBR:~# i2cset -y 0 0x38 0x00 0x00
root@ZEON-TBR:~# i2cset -y 0 0x38 0x00 0x10
root@ZEON-TBR:~# i2cset -y 0 0x38 0x00 0x11
root@ZEON-TBR:~# i2cset -y 0 0x38 0x00 0x00
Управление и считывание порта В: (27 - атмега8)
# i2cset -y 0 0x27 0xB0 0xff
# i2cset -y 0 0x27 0xB2 0xff
# i2cset -y 0 0x27 0xB2 0x00
# i2cset -y 0 0x27 0xB2 0x01
# i2cget -y 0 0x27 0xB2
0x01
# i2cset -y 0 0x27 0xB2 0x03
# i2cget -y 0 0x27 0xB2
0x03
... to be continued
Esp8266 (Wifikit 8)
Подключение к шине OLED согласно pinout. (0x3C занят дисплеем)
Сканер портов:
#include void setup(){ Wire.begin(); Serial.begin(9600); while (!Serial); Serial.println("\nI2C Scanner"); } void loop(){ byte error, address; int nDevices; Serial.println("Scanning..."); nDevices = 0; for(address = 8; address < 127; address++ ){ Wire.beginTransmission(address); error = Wire.endTransmission(); if (error == 0){ Serial.print("I2C device found at address 0x"); if (address<16) Serial.print("0"); Serial.print(address,HEX); Serial.println(" !"); nDevices++; } else if (error==4) { Serial.print("Unknow error at address 0x"); if (address<16) Serial.print("0"); Serial.println(address,HEX); } } if (nDevices == 0) Serial.println("No I2C devices found\n"); else Serial.println("done\n"); delay(5000); }
Чтение/запись:
#include "PCF8574.h" // https://github.com/xreef/PCF8574_library // Set i2c address PCF8574 pcf8574(0x3F); void setup() { // Set pinMode to OUTPUT for(int i=0;i<8;i++) { pcf8574.pinMode(i, OUTPUT); } pcf8574.begin(); } void loop() { static int pin = 0; pcf8574.digitalWrite(pin, HIGH); delay(1000); pcf8574.digitalWrite(pin, LOW); delay(1000); pin++; if (pin > 1) pin = 0; }