Il bus I²C
Che cosa è il bus I²C e come funziona
l’I²C (si legge “I-quadro-C”) è uno dei bus più importanti e diffusi nei microcontrollori come Arduino o ESP32.
Vediamolo passo passo, in modo semplice ma completo 👇
🔹 1. Cos’è l’I²C
I²C (Inter-Integrated Circuit) è un bus di comunicazione seriale sincrono a due fili, inventato da Philips negli anni ’80 per collegare dispositivi elettronici su una stessa scheda.
Serve per far comunicare più dispositivi — sensori, display, EEPROM, RTC, ecc. — usando solo due linee di segnale più la massa comune.
🔹 2. Le due linee principali
| Linea |
Nome |
Funzione |
| SDA |
Serial Data |
Trasporta i dati |
| SCL |
Serial Clock |
Trasporta il segnale di clock (sincronizza la comunicazione) |
Entrambe sono open-drain: i dispositivi non spingono mai il segnale a “1”, ma solo a “0”.
Serve quindi una resistenza di pull-up (di solito 4.7 kΩ) per riportare la linea a “1” quando nessuno la abbassa.
🔹 3. Come funziona la comunicazione
🧭 a) Struttura del bus
- Tutti i dispositivi condividono le stesse linee SDA e SCL.
- Uno solo fa da Master (di solito l’Arduino o l’ESP32).
- Gli altri sono Slave (sensori, memorie, moduli vari).
🕹️ b) Indirizzi
Ogni Slave ha un indirizzo univoco a 7 bit (o 10 in alcuni casi).
Esempio:
- RTC DS3231 → indirizzo 0x68
- EEPROM 24C32 → indirizzo 0x50
- Display OLED SSD1306 → indirizzo 0x3C
🔹 4. Sequenza di comunicazione
Quando il Master (Arduino) vuole dialogare:
- Manda un segnale di start.
- Invia l’indirizzo dello Slave + 1 bit che indica se vuole scrivere (0) o leggere (1).
- Lo Slave risponde con un ACK (acknowledge = conferma).
- Il Master invia o riceve i dati.
- Manda un segnale di stop per chiudere la trasmissione.
Tutto avviene sincronizzato con l’orologio SCL.
🔹 5. Velocità tipiche
| Modalità |
Frequenza massima |
Note |
| Standard |
100 kHz |
Default per Arduino |
| Fast |
400 kHz |
Molto usata, compatibile con quasi tutti i moduli |
| Fast+ |
1 MHz |
Solo con dispositivi recenti |
| High-Speed |
3.4 MHz |
Raro nei microcontrollori |
Nell’IDE Arduino puoi impostare la velocità, ad esempio:
Wire.begin(SDA_pin, SCL_pin, 400000); // 400 kHz |
🔹 6. Vantaggi
✅ Solo 2 fili per collegare molti dispositivi
✅ Indirizzi univoci, quindi basta un unico bus
✅ Librerie già pronte (Wire.h)
✅ Fino a ~10 dispositivi senza problemi (se il bus non è troppo lungo)
🔹 7. Svantaggi
⚠️ Lunghezza massima del cavo limitata (~50 cm tipici)
⚠️ Tutti i dispositivi devono condividere la stessa tensione logica (3.3 V o 5 V)
⚠️ Se due dispositivi hanno lo stesso indirizzo, serve un trucco (pin di selezione o multiplexer)
🔹 8. Esempio pratico
#include <Wire.h>
void setup() {
Wire.begin(); // usa i pin I2C di default (A4=A SDA, A5=SCL su Nano ESP32)
Serial.begin(115200);
Wire.beginTransmission(0x68); // DS3231
Wire.write(0x00); // registro da cui iniziare
Wire.endTransmission();
Wire.requestFrom(0x68, 1); // leggo 1 byte
if (Wire.available()) {
byte valore = Wire.read();
Serial.println(valore);
}
} |
🔹 9. Curiosità
-
Su ESP32 puoi avere fino a 2 bus I²C indipendenti, ciascuno con propri pin SDA/SCL.
-
È compatibile anche con dispositivi a 5 V se le linee sono ben adattate (pull-up su 3.3 V o con convertitori di livello).
Il Bus I²C su Arduino Nano ESPP32
🧩 1️⃣ Cosa mostra Arduino
Sul pinout ufficiale Arduino, vengono indicati:
-
A4 → SDA (I²C data)
-
A5 → SCL (I²C clock)
➡️ Questo è il bus I²C predefinito usato da Wire.begin()
(quello che le librerie standard — sensori, display, EEPROM — usano di default).
Quindi sì: a livello Arduino, se non specifichi niente, il Nano ESP32 ha un solo bus I²C “attivo”, su A4/A5.
🧠 2️⃣ Ma a livello ESP32-S3 (hardware)
Il chip ESP32-S3 ha due controller I²C hardware indipendenti:
👉 E ciascuno può essere assegnato a qualunque coppia di GPIO (tramite la matrice interna).
Non ci sono pin fissi!
Arduino sceglie A4/A5 solo per compatibilità con il “vecchio Nano”.
⚙️ 3️⃣ Come usarne un secondo (o cambiare pin)
Puoi creare un secondo bus I²C o spostare i pin dove vuoi, così:
#include <Wire.h>
// Primo bus I2C standard (già su A4/A5)
TwoWire I2C_1 = Wire;
// Secondo bus I2C personalizzato
TwoWire I2C_2 = TwoWire(1); // Usa il controller I2C1
void setup() {
Serial.begin(115200);
// Avvia bus standard
I2C_1.begin(A4, A5); // SDA, SCL
// Avvia secondo bus su altri pin (esempio D4 e D5)
I2C_2.begin(7, 8); // SDA=GPIO7, SCL=GPIO8 (puoi scegliere altri)
Serial.println("Due bus I2C attivi!");
} |
➡️ In questo modo puoi:
- avere due dispositivi con stesso indirizzo I²C su bus diversi;
- isolare moduli “rumorosi” (come display e sensori);
- mantenere librerie standard senza conflitti.
Nota: ci sono due modi di chiamare i pin: modo tradizionale Ax e Dx (es A0, A1... o D2, D3 ...) e l'altro GPIOx. Quest'ultimo è particolarmente legato all'hardware. Attenzione non c'è una corrispondenza tra i due: A4 non corrisponde a GPIO4, Arduino fa una sua mappatura e li associa a modo suo vedi qui. Se nelle impostazioni della scheda nell'IDE abbiamo scelto: Pin Numbering: "By Arduino pin (Default)" allora potremmo chiamare i pin es A0 se invece scegliamo: By GPIO number (Legacy) allora potremmo utilizzare solo la notazione GPIOx. Questo significa che con la Default poi utilizzare solo i pin da A0 a A7 e D0 a D16 e se scrivi solo un numero verrà interpretato come digitale. Se invece utilizzi la legacy puoi utilizzare solo numeri che verranno interpretati come GPIO reali. Nella modalità Default se scrivi ad es A4 arduino in realtà lo converte in GPIO11 ha una sua mappatura particolare non vi è corrispondenza tipo A4 ->GPIO4.
📘 4️⃣ In sintesi
| Livello |
Bus I²C disponibili |
Pin predefiniti |
Puoi cambiare pin? |
| Arduino (default) |
1 (Wire) |
SDA=A4, SCL=A5 |
✅ Sì |
| ESP32-S3 hardware |
2 (I2C0, I2C1) |
Nessuno fisso |
✅ Sì, su quasi ogni GPIO |
🔧 Consiglio pratico
Nel 99% dei casi basta il bus su A4/A5.
Usa un secondo bus solo se:
- hai conflitti d’indirizzo;
- vuoi tenere separati dispositivi con velocità diverse;
- vuoi testare dispositivi “on-the-fly” (es. hot-plug del BoxSetter 😉).
|