I2C jest protokołem komunikacyjnym, wynalezionym w 1982 roku przez firmę Philips. Służy on do komunikowania się z takimi urządzeniami jak wyświetlacze, czy czujniki ciśnienia. W odróżnieniu do protokołów SPI oraz UART, I2C obsługuje Multi-Master. Dane przesyłane są bit po bicie jednym przewodem. Częstotliwość komunikacji wynosi 100 lub 400 kHz.
Do komunikacji potrzebne są dwa piny:
SDA – kanał przesyłania danych, odpowiada za nadawanie i odbieranie,
SLC – urządzenie główne, odpowiada za dzielenie sygnału zegara między urządzeniami nadrzędnymi, a podrzędnymi.
Maksymalna długość ramki wynosi 8 bitów. Protokół może korzystać z sześciu trybów transmisji. Zapewniają one szybkość od 10 kb/s do 5 Mb/s.
W przypadku urządzeń o tym samy adresie, konieczne jest wykorzystanie Multiplekser’a I2C. Przykładowo multiplekser PCF8574 pozwala na komunikację nawet z ośmioma urządzeniami o tym samym adresie przez pojedynczą magistralę I2C.
Skaner I2C
W przypadku korzystania z części urządzeń urządzeń wykorzystujących komunikacje I2C konieczny jest adres HEX. W tym celu należy podciąć do płytki np. Wyświetlacz 2X16. Następnie wgrać poniższy kod. Pozwoli to na uzyskanie kodu HEX potrzebnego do komunikacji z wyświetlaczem.
Schemat podłaczenia wyświetlacza 16X2.
Kod programu skaner I2C.
Następnie należy wgrać poniższy kod i uruchomić monitor portu szeregowego.
#include <Wire.h>
void setup() {
Wire.begin();
Serial.begin(9600);
Serial.println("I2C Scanner");
//SLC - D1
//SLA - D2
//VCC - 3V
//GND - G
}
void loop() {
byte error, address;
int nDevices;
Serial.println("Scanning...");
nDevices = 0;
for(address = 1; 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.println(address,HEX);
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(10000);
}
Monitor portu szeregowego
W rezultacie otrzymujemy kod wyświetlacza.
Obsługa wyświetlacza
Podstawowe komendy
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE) - Ustawienie adresu ukladu na 0x27
lcd.backlight() - Uruchomienie podświetlania ekranu
lcd.noBacklight() - Wyłączenie podświetlania ekranu
lcd.begin(16,2) - Deklarowanie rozmiaru wyświetlacza
lcd.setCursor(0,0) - Ustawienie kursora na znaku początkowym
Kod programu
//SCL -> D1
//SDA -> D2
#include <Wire.h> // standardowa biblioteka Arduino
#include <LiquidCrystal_I2C.h> // dolaczenie pobranej biblioteki I2C dla LCD
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
void setup()
{
lcd.begin(16,2); //Deklarowanie rozmiaru wyświetlacza
lcd.backlight();
lcd.setCursor(0,0); //Ustawuenie kursora na znaku początkowym
lcd.print("ESP2866");//Wypisanie tekstu od zanku początkowego
lcd.setCursor(0,1);
lcd.print("SENSOR BMP180");
delay(1000);
}
void loop() {}
Obsługa BMP180
Schemat podłączenia.
Kod programu
#include <Wire.h>
#include <Adafruit_BMP085.h>
Adafruit_BMP085 bmp;
void setup() {
Serial.begin(9600);
if (!bmp.begin()) {
Serial.println("Nie znaleziono sensora BMP180!");
while (1) {}
}
}
void loop() {
Serial.print("Temperatura = ");
Serial.print(bmp.readTemperature()); // Odczyt temperatury
Serial.println(" ^C");
Serial.print("Ciśnienie = ");
Serial.print(bmp.readPressure()); // Odczyt ciśnienia
Serial.println(" Pa");
Serial.print("Wysokość = ");
Serial.print(bmp.readAltitude()); // odczyt wysokości
Serial.println(" m");
Serial.println();
delay(1000);
}
Wynik pracy programu.
Program z I2C Odczyt temp. i ciśnienia z BMP180
Schemat podłączenia.
Kod programu.
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Adafruit_BMP085.h>
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); // Ustawienie adresu ukladu na 0x27
Adafruit_BMP085 bmp;
void setup() {
lcd.begin(16,2);
lcd.backlight();
lcd.setCursor(0,0);
lcd.print("ESP2866");
lcd.setCursor(0,1);
lcd.print("SENSOR BMP180");
delay(1000);
Serial.begin(9600);
if (!bmp.begin()) {
Serial.println("Nie znaleziono sensora BMP180!");
while (1) {}
}
}
void loop() {
lcd.setCursor(0,0);
lcd.print("Temp = ");
lcd.print(bmp.readTemperature());
lcd.print(" C");
lcd.setCursor(0,1);
lcd.print("Pres = ");
lcd.print(bmp.readPressure());
lcd.print(" Pa");
Serial.println();
delay(1000);
}