V některých návodech se v sekci zapojení vyskytuje výraz I2C sběrnice. V tomto článku se vám pokusím vysvětlit, co to I2C sběrnice je, a hlavně si ukážeme, proč ji u Arduina využíváme. O teorii si nebudeme povídat příliš, spíše nás bude zajímat, jak všechno reálně použít. Přesto si alespoň základní teoretické minimum říct musíme.
Sběrnici si můžeme představit jako dálnici. Na této dálnici jsou připojeny různé vjezdy a výjezdy. Samotná dálnice představuje vodiče sběrnice, zatímco vjezdy a výjezdy odpovídají vodičům periferií.
V reálném světě to u I2C vypadá tak, že k Arduinu (master) stačí připojit pouze dva vodiče, které zajistí komunikaci s dalšími periferiemi (slave). Díky tomu nemusíme každou periferii připojovat zvlášť k desce – stačí ji připojit ke sběrnici. To nám umožní ušetřit spoustu vodičů i pinů na desce.
Pokud je to pro vás stále nejasné, snad vám pomůže obrázek.
Ve schématu vidíme rezistory pull-up sloužící k zajištění klidového potenciálu na sběrnici. Ty však často nemusíme samostatně připojovat, protože bývají již zabudované v modulech periferií. Pokud by je periferie neobsahovaly, pak stačí použít rezistory externí.
Technické specifikace sběrnice I2C
- Každé zařízení má unikátní I2C adresu (jak ji zjistit, si ukážeme níže).
- I2C sběrnice vyžaduje pouze dva vodiče:
- SDA – datový vodič
- SCL – taktovací vodič
- I2C sběrnice využívá 7bitové adresování, což umožňuje adresovat až 128 různých adres (0–127). Prakticky je však možné připojit až 112 zařízení, protože některé adresy jsou rezervovány pro speciální účely.
- Architektura podporuje režim multi-master (více řídicích zařízení).
- Množství přenášených dat není omezeno.
- Standardní rychlosti I2C sběrnice jsou 100 kHz (Standard Mode), 400 kHz (Fast Mode) a 1 MHz (Fast Mode Plus). Některá zařízení podporují až 3,4 MHz (High-Speed Mode). Rychlost 5 MHz není běžně podporována.
Průběh komunikace na I2C sběrnici (krok za krokem)
- Inicializace komunikace: Master (např. Arduino) zahájí komunikaci vysláním signálu START a zároveň pošle adresu konkrétní periferie (slave), se kterou chce komunikovat.
- Detekce adresy: Všechna zařízení na sběrnici obdrží tuto adresu. Pouze zařízení, jehož adresa odpovídá, na ni zareaguje. Ostatní zařízení komunikaci ignorují.
- Potvrzení připravenosti: Vybrané slave zařízení odešle potvrzení, že je připraveno přijímat data (ACK – acknowledge).
- Přenos dat: Master postupně posílá data, která slave zařízení přijímá.
- Ukončení komunikace: Po odeslání všech dat vyšle master signál STOP, čímž ukončí komunikaci a sběrnice se uvolní pro další použití.
Zapojení I2C do Arduina
Jak jsem již zmínil, I2C sběrnice vyžaduje pouze dva vodiče. Ty však nemůžeme zapojit do libovolných pinů na desce – je nutné je připojit ke speciálním pinům určeným právě pro I2C. Aby to bylo ještě zajímavější, tyto piny se liší podle typu desky. Níže najdete jednoduchý přehled.
Deska | SDA (datový) | SCL (taktovací) |
Arduino Uno | A4 | A5 |
Arduino Nano | A4 | A5 |
Arduino Mega 2560 | 20 | 21 |
Arduino Leonardo | 2 | 3 |
Arduino Due | 20 | 21 |
ESP8266 (např. NodeMCU) | D2 (GPIO4) | D1 (GPIO5) |
ESP32 | GPIO21 | GPIO22 |
Arduino Uno R4 Minima | A4 | A5 |
Arduino Uno R4 WiFi | A4 | A5 |
Poznámka: Na deskách Uno, Nano a Mega jsou piny SDA/SCL často navíc vyvedeny i na samostatné konektory poblíž napájecího konektoru (značené jako SDA/SCL).
I2C adresa
Konečně se dostáváme k adrese – právě pomocí ní Arduino pozná, se kterou periferií na sběrnici komunikuje. Tato adresa se následně zapisuje do programu.
Pokud používáme I2C sběrnici pouze s jednou periferií, není vždy nutné adresu do programu explicitně zapisovat. Jakmile však připojíme dvě nebo více periferií, je určení adresy nezbytné.
I2C adresu zjistíme velmi jednoduše
Stačí stáhnout jednoduchý skenovací kód, nahrát ho do Arduino desky, připojit periférii a otevřít sériový monitor. Adresa připojeného zařízení se zobrazí přímo v monitoru.
#include <Wire.h> 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 = 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.print(address,HEX); Serial.println(" !"); nDevices++; } else if (error==4) { Serial.print("Unknown 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); }
Výstup by měl vypadat nějak takte, adresa mého zařízení je tedy 0x27
Příklad pro I2C
Nakonec si ukážeme příklad. Z nějakého důvodu potřebujeme poslat zprávu z jedné Arduino desky do druhé – a k tomu použijeme I2C sběrnici. Z první desky, která bude v roli slave, budeme odesílat textovou zprávu. Druhá deska, nastavená jako master, tuto zprávu přijme a zobrazí. Nicméně v I2C komunikaci iniciuje přenos vždy master zařízení to znamená master nejprve vyslat požadavek na čtení.
Protože spolu komunikují pouze dvě zařízení, nemusíme řešit specifické adresování. Stačí desky správně propojit podle schématu.
Program pro master, tudíž přijímací desku bude vypadat takto:
// master - reader // importování knihovny #include <Wire.h> void setup() { // inicializace I2C komunikace Wire.begin(); // inicializace sériové komunikace Serial.begin(9600); } void loop() { // vyžádáme si 11 bytů z adresy 5 Wire.requestFrom(5, 11); // pokud slave něco pošle, tak zprávu znak po znaku přečteme while (Wire.available()) { // přečte se znak char c = Wire.read(); // a ten se vytiskne Serial.print(c); } delay(500); }
Program pro slave, tedy odesílatele bude vypadat následovně:
// slave - sender // imporotvání knihovny #include <Wire.h> void setup() { // připojení na I2C s adresou 5 Wire.begin(5); // pokud si slave vyžadá, tak se sepne funkce "request event" Wire.onRequest(requestEvent); } void loop() { delay(100); } // vlastní funkce, která když bude volaná, tak void requestEvent() { // pošle zprávu Wire.write("HW kitchen "); // z funkce se vlastně nedostaneme, proto bude běhat pořád dokola }
Závěr článku o I2C
Tímto jsme si představili základní principy fungování I2C sběrnice. Je velmi pravděpodobné, že se s ní dříve nebo později setkáte. Pokud máte jakékoli dotazy nebo něčemu nerozumíte, napište nám do komentářů. Můžete se také podívat na další návody z naší dílny.
Znalosti a zkušenosti se sběrnicí I2C můžete dále prohloubit například na následujících projektech:
- Využití I2C LCD displeje kde stačí na komunikaci jen 4 vodiče
- Projekty s tříosým akcelerometrem a gyroskopem MPU-6050
- Zobrazování na grafickém OLED 128x64
- Rozpoznávání hlasu s ASR modulem
- Zabezpečení přístupu s RFID modulem
- Další moduly a projekty I2C