Collegare dispositivi I2C

Da raspibo.

I2C e' un bus composto da due fili (oltre il filo di massa): il filo dati e il filo clock. Possiamo dire che I2C e' una rete per circuiti integrati.

Il nostro Raspberry PI ha due bus I2C, uno e' disponibile sul pettine di contatti per i nostri giochi.

Fra la revisione A e la revisione B del Raspberry PI hanno invertito i bus:

  • Nella revisione A: il bus 0 e' per le sperimentazioni.
  • Nella revisione B: il bus 1 e' per le sperimentazioni (il bus 0 sarebbe disponibile sul bus P5, occorre saldare un pettine per i contatti).

Il mio consiglio per fare esperimenti sul bus (o sui bus) I2C e' di installare il pacchetto con gli strumenti (tool) per I2C.

sudo apt-get install i2c-tools

Occorre poi caricare i moduli per usare I2C a livello utente:

$ sudo bash
# modprobe i2c_dev
# modprobe i2c_bcm2708

Se tutto va bene si puo' usare il comando i2cdetect per controllare le unita' collegate:

# i2cdetect -y 1
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- --

(per le schede rev.A usare -y 0 al posto di -y 1 in tutti i comandi da qui in poi).

Il sistema non vede nessun integrato collegato al bus, infatti non abbiamo ancora collegato nulla.

A questo punto basta collegare gli integrati I2C in modo che:

  • Il pin di massa dell'integrato sia attaccato alla massa del Raspberry PI (Pin. 6)
  • Il pin di alimentazione sia collegato a +3.3v (Pin. 1 del Raspberry PI o in qualche modo sia alimentato a 3.3v)
  • Il pin SDA (dati) dell'integrato sia collegato al pin 3
  • Il pin SCK (clock) dell'integrato sia collegato al pin 5.

E' comodo collegare per esempio le schede di JeeLabs in questo modo:

  • PWR (indicato con P sul circuito stampato) al PIN 2 del Raspberry PI, +5v
  • DIO (indicato con D sul circuito stampato, per le unita' I2C e' SDA) al PIN 3 del Raspberry PI
  • GND (indicato con G sul circuito stampato) e' la massa, collegatela al PIN 6
  • +3v (indicato con + sul circuito stampato),e' la tensione 3.3v, va collegata al PIN 1
  • AIO (indicato con A sul circuito stampato, per le unita' I2C e' SCK) al PIN 5 del Raspberry PI
  • IRQ (indicato con I sul circuito stampato), serve per segnali di interruzione, per applicazioni evolute si puo' collegare a un gpio libero per fare in modo che l'unita' I2C attiri l'attenzione del Raspberry PI nel caso di un evento. Per ora si puo' lasciare scollegato.

NOTA IMPORTANTE: I2C e' uno standard di segnalazione (protocollo di comunicazione liv. 1 e 2) ma non stabilisce la tensione di lavoro. Esistono schede (e.g. per il vecchio arduino) che funzionano a 5V. NON SI POSSONO COLLEGARE AL RASPBERRY PI se non tramite un circuito di conversione della tensione di segnalazione. Attaccate solo circuiti che usano I2C a 3.3v altrimenti potete danneggiare il vostro Raspberry PI

Piu' schede I2C possono essere collegate in parallelo. Occorre fare due considerazioni:

  • Se volete usare il pin IRQ, quello deve essere portato a un GPIO diverso per ogni scheda
  • Se mettete molti integrati attacati al bus I2C la corrente fornita dal Raspberry PI potrebbe non essere sufficiente, occorre studiare un circuito alternativo per l'alimentazione.

Se per esempio mettete opportuni ponticelli in modo che 6 colonne consecutive corrispondano alla piedinatura voluta dalle schede di Jeelabs, potete collegare piu' schede JeeLabs una di fianco all'altra.

Io ho provato le seguenti schede:

Nell'esperimento che segue ho collegato un sensore di pressione e una scheda di espansione di output:

# i2cdetect -y 1
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: -- -- -- -- -- -- 26 -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- 77

(sempre -y 0 se avete un Raspberry PI di primo tipo)

26 e' la scheda si espansione di output, 77 il sensore di pressione.

E' possibile anche collegare al bus piu' schede dello stesso tipo ma occorre fare in modo che usino indirizzi diversi. Per fare questo sulle schede sono presenti contatti da saldare per cambiare l'inidirizzo (per esempio la scheda di espansione di output puo' assumere l'indirizzo 26 o 27, quindi se ne possono collegare due).

A questo punto siete in grado di collegare unita' (circuiti integrati) che comunicano via I2C. Quali richieste sono in grado di gestire le singole unita' o schede dipende dalle caratteristiche/specifiche dell'integrato usato, pertanto scrivero' una pagina per ogni scheda.

I2C prevede che gli integrati comunichino tramite registri, ogni registro ha un indirizzo. In semplici casi e' possibile usare i comandi i2cget/i2cset per scrivere o leggere i registri. (per casi piu' complessi e' piu' pratico scrivere programmi in grado di gestire in modo piu' efficiente il protocollo). Per esempio l'espansione di output, ma anche l'interfaccia per display LCD e l'espansione di I/O. usano l'integrato MCP23008. Se si leggono le specifiche si vede che il registro a indirizzo 0 contiene la direzione della comunicazione (per ogni pin, 0=output, 1=input) e il registro all'indirizzo 0x9 l'attuale stato degli 8 pin.

Se vogliamo pilotare da command line gli 8 output digitali della scheda di espansione (collegata all'indirizzo 0x26) possiamo scrivere i seguenti comandi:

  • indichiamo all'interfaccia che i pin sono tutti di output:
# i2cset -y 1 0x26 0x00 0x00
  • vediamo lo stato attuale leggendo il registro 0x09
# i2cget -y 1 0x26 0x09
0x00

ci mostra che gli output sono tutti spenti

  • Accendiamo l'output IO0:
# i2cset -y 1 0x26 0x09 0x01

Se avete un utilizzatore (o il tester) collegato al pin IO0 sulla scheda potete vedere che e' ora a 5v.

  • controlliamo lo stato dei pin
# i2cget -y 1 0x26 0x09
0x01
  • Accendiamo anche IO2, controlliamo, spegniamo tutto, controlliamo.
# i2cset -y 1 0x26 0x09 0x05
# i2cget -y 1 0x26 0x09
0x05
# i2cset -y 1 0x26 0x09 0x00
# i2cget -y 1 0x26 0x09
0x00

I2cdetect lento

Improvvisamente (probabilmente dopo un aggiornamento) il mio raspberry ha iniziato ad impiegare tanto a rispondere al comando i2cdetect. Non ho indagato tanto, ma ho trovato un consiglio su questa pagina che nel mio caso ha funzionato alla grande.

sudo rmmod i2c_bcm2708
sudo rmmod i2c_dev
sudo modprobe i2c_dev
sudo modprobe i2c_bcm2708

il comando

journalctl 

mostra questi errori

 i2c i2c-1: transfer timed out
Strumenti personali
Namespace

Varianti
Azioni
Navigazione
Strumenti