Appena si va oltre il LED e il pulsante, ci si imbatte in sigle che compaiono su ogni scheda tecnica: il sensore di temperatura parla I2C, il display parla SPI, il modulo GPS manda dati su UART. Sono tre modi diversi di far dialogare chip vicini sulla stessa scheda o a pochi centimetri di distanza. Capire come funzionano evita ore passate a cercare un errore che sta in un filo invertito o in una resistenza mancante.
Il quadro d'insieme
| UART | I2C | SPI | |
|---|---|---|---|
| Fili di segnale | 2 (TX, RX) | 2 (SDA, SCL) | 4 (clock, due dati, selezione) |
| Clock condiviso | no | sì | sì |
| Dispositivi | due, punto a punto | molti sullo stesso bus | molti, uno per linea di selezione |
| Indirizzamento | nessuno | indirizzo nel messaggio | linea di selezione dedicata |
| Velocità tipica | bassa-media | bassa-media | alta |
A tutti va aggiunta una massa in comune: senza quella, nessun segnale ha un riferimento.
UART: la seriale asincrona
UART è il più antico e il più semplice. Due dispositivi si scambiano byte su due linee: ciascuno trasmette sul proprio TX e riceve sul proprio RX. Non esiste un clock condiviso: entrambi devono essere impostati sulla stessa velocità, il baud rate, e sullo stesso formato (di solito 8 bit di dati, nessuna parità, un bit di stop, abbreviato 8N1). Valori come 9600 o 115200 baud sono comuni.
I due errori più frequenti:
- TX collegato a TX: i fili vanno incrociati, il TX di uno sul RX dell'altro;
- baud rate diverso: i dati arrivano, ma come caratteri senza senso.
UART è perfetto per moduli che inviano flussi di testo, come molti ricevitori GPS, per le console di debug di router e schede, e per la comunicazione tra un microcontrollore e un computer tramite un adattatore USB-seriale.
I2C: due fili, tanti dispositivi
I2C usa una linea dati (SDA) e una linea di clock (SCL). Il dispositivo che comanda, detto controller, genera il clock e avvia ogni scambio indicando l'indirizzo del dispositivo a cui si rivolge, di solito a 7 bit. Tutti i sensori stanno sugli stessi due fili e rispondono solo quando sentono il proprio indirizzo.
Due caratteristiche da conoscere:
- Le resistenze di pull-up sono obbligatorie. Le linee I2C sono «a collettore aperto»: i dispositivi possono solo portarle a livello basso, il livello alto lo garantiscono le resistenze verso l'alimentazione. Molti moduli le hanno già montate; se si collegano tanti moduli, i pull-up in parallelo possono diventare troppo forti.
- Gli indirizzi possono entrare in conflitto. Due sensori identici hanno lo stesso indirizzo. Alcuni permettono di cambiarlo con un ponticello; altrimenti serve un multiplexer I2C.
Il primo passo di diagnosi è sempre una scansione del bus: un piccolo programma che prova tutti gli indirizzi e segnala quali rispondono. Su Raspberry Pi c'è il comando i2cdetect -y 1; per Arduino esistono sketch di scansione pronti. Se il sensore non compare, il problema è nei collegamenti o nell'alimentazione, non nel codice.
I2C è pensato per distanze brevi, sulla stessa scheda o con cavi corti: allungare troppo i fili aumenta la capacità della linea e i fronti del segnale si arrotondano fino a renderlo illeggibile.
SPI: veloce e semplice
SPI usa un clock, una linea per i dati in uscita dal controller, una per i dati in ingresso e una linea di selezione (chip select) per ogni dispositivo. Le sigle storiche sono MOSI, MISO, SCK e SS; nelle documentazioni più recenti si trovano nomi come COPI, CIPO e CS, o SDO e SDI.
Non ci sono indirizzi: il controller abbassa la linea di selezione del dispositivo con cui vuole parlare, e solo quello ascolta. Trasmissione e ricezione avvengono contemporaneamente. Il risultato è un bus molto più veloce di I2C, adatto a display, schede di memoria, convertitori rapidi.
Il prezzo è il numero di fili: ogni dispositivo in più richiede un'altra linea di selezione. E bisogna impostare la modalità corretta, cioè su quale fronte del clock si leggono i dati: è indicata nella scheda tecnica, e sbagliarla produce dati spostati o casuali.
I livelli logici
Prima ancora del protocollo conta la tensione. Molti sensori moderni lavorano a 3,3 volt, l'Arduino Uno a 5 volt, il Raspberry Pi a 3,3 volt. Collegare un'uscita a 5 volt a un ingresso che non li tollera può danneggiarlo in modo permanente. Le soluzioni:
- scegliere moduli dichiarati compatibili con entrambe le tensioni;
- usare un convertitore di livello bidirezionale, indispensabile per I2C;
- per una linea che va solo da 5 a 3,3 volt, anche un semplice partitore resistivo può bastare.
Quale scegliere
Spesso non si sceglie: decide il componente. Quando c'è scelta, una regola pratica:
- I2C per molti sensori lenti con pochi fili;
- SPI quando servono velocità e grandi quantità di dati;
- UART per collegare due dispositivi, o per una console di debug.
In sintesi
- Tutti e tre i bus richiedono una massa in comune.
- UART: TX e RX incrociati, stesso baud rate su entrambi i lati.
- I2C: pull-up obbligatori, indirizzi unici, scansione del bus come primo test.
- SPI: più fili, nessun indirizzo, alta velocità; attenzione alla modalità.
- Verifica sempre i livelli logici prima di collegare dispositivi a 5 V e 3,3 V.