Laboratorio: I2C

Arduino e LM75A

Questa pagina mostra come utilizzare un bus I2C in laboratorio dal punto di vista del progettista elettronico; in particolare sarà sperimentato come analizzare i segnali presenti usando un oscilloscopio digitale. Negli esempi è utilizzato un Picoscope 2205A MSO, sia in modalità analogica che digitale, ma vanno benissimo anche altri strumenti purché dotati di capacità di decodifica dei segnali seriali I2C. Per chi non dispone di un tale strumento, a fondo pagina sono presenti alcuni esempi.

Molti degli esempi fanno riferimento a due sensori di temperatura (TC74 e LM75A) scelti per il semplice motivo che... li avevo nel cassetto.

Nel sito potete trovare anche una pagina con simili contenuti che utilizza ESP8266 e BMP280.

Arduino

Arduino gestisce i dispositivi I2C per mezzo della libreria Wire che contiene i metodi per leggere e scrivere messaggi generici secondo questo protocollo. Ovviamente sono disponibili anche molte librerie specializzate che rendono semplice l'uso di una miriade di dispositivi.

Arduino può essere configurato per comportarsi come Master I2C oppure come Slave I2C, ovviamente in momenti e contesti diversi.

L'hardware

L'hardware da realizzare è piuttosto semplice, soprattutto se si utilizza un circuito stampato che contiene già alcuni degli elementi necessari al funzionamento del circuito. Lo schema seguente mostra un Master (normalmente Arduino, Raspberry Pi, un PIC o un altro dispositivo programmabile) e due Slave (in numero variabile tra 1 e qualche decina):

Schema di collegamento I2C

I collegamenti necessari sono:

Il valore delle due resistenze non è critico ed in genere si sceglie di qualche kΩ, in funzione della velocità di comunicazione e del consumo di corrente.

La fotografia di apertura mostra una possibile realizzazione in cui Arduino usa il circuito PIC-WL-Sen, dopo aver tolto il processore a bordo, la batteria ed il modulo radio. In alternativa è possibile usare A2B oppure realizzare il circuito su breadboard.

Arduino come Master I2C

In genere la prima operazione da fare è quella di individuare gli indirizzi degli Slave I2C connessi, verificando così anche la funzionalità complessiva del circuito.

Questa operazione è fatta semplicemente iniziando una trasmissione verso ciascuno dei 127 indirizzi possibili, da 0x00 a 0x7F, senza poi trasmettere nulla (nota 1):

L'output tipico potrebbe essere qualcosa di simile alla seguente schermata che mostra la presenza di quattro dispositivi con indirizzo (esadecimale) 0x48, 0x4A, 0x4D e 0x4F:

I2C scan

Nell'esempio si tratta di quattro sensori di temperatura (tre TC74 e un LM75A), ma questa informazione è deducibile solo osservando direttamente circuito fisico.

(approfondimento, da riprendere al termine delle attività descritte in questa pagina) Un errore tipico è le presenza di due Slave con lo stesso indirizzo. La scansione con la metodologia precedente rileva semplicemente la presenza di almeno uno Slave con quell'indirizzo e quindi non segnala nulla di anomalo. Cosa potrebbe succedere durante l'uso? Un suggerimento: un tempo i collegamenti diretti di più porte logiche con una resistenza di pull-up erano indicati con il termine AND cablato...

Collegando un oscilloscopio ai due segnali SDA (D1) e SCL (D0) si vede come gli indirizzi riscontrati (ACK = 0) sono quelli degli Slave presenti nel dettaglio del diagramma temporale:

Usare TC74

TC74 è un sensore di temperatura con modeste caratteristiche: risoluzione di 1 °C, accuratezza a temperatura ambiente di ± 2 °C.

Questo circuito può utilizzare un solo indirizzo I2C, scelto dal produttore e stampato sul contenitore. La documentazione è riportata al termine del foglio tecnico (nota 5).

Il codice per leggere la temperatura è piuttosto semplice: basta semplicemente leggere il contenuto del registro 0x00. Di seguito un esempio:

#include <Arduino.h>
#include <Wire.h>

#define TC_ADDRESS 0x4F
#define T_REGISTER 0x00

void setup() {
 Wire.begin();
 Serial.begin(9600);
 Serial.println( "" );
 Serial.println("Start");
}

void loop() {
 Wire.beginTransmission( TC_ADDRESS );
 Wire.write( T_REGISTER );
 Wire.endTransmission( false );
 Wire.requestFrom( TC_ADDRESS, 1);
 int T = Wire.read();
 Serial.print(T,DEC);
 Serial.println(" °C");

 delay(1000);
}

Uso di LM75A senza librerie

LM75A è un sensore di temperatura piuttosto diffuso, semplice da utilizzare anche senza librerie specifiche. Per esempio il seguente codice legge dal registro 0x00 i due byte che contengono la parte intera e quella frazionaria della temperatura, stampandola sul monitor seriale. Per i dettagli è necessario leggere i fogli tecnici del componente utilizzato, per esempio il paragrafo 7.4.3 del data sheet NXP.

#include <Arduino.h>
#include <Wire.h>

#define LM_ADDRESS 0x48
#define T_REGISTER 0x00

void setup() {
 Wire.begin();
 Serial.begin(9600);
 Serial.println( "" );
 Serial.println("Start");
}

void loop() {
 Wire.beginTransmission( LM_ADDRESS );
 Wire.write( T_REGISTER );
 Wire.endTransmission( false );
 Wire.requestFrom( LM_ADDRESS, 2);
 int H = Wire.read();
 int L = Wire.read();
 Serial.print ( H*256 + L, HEX );
 Serial.print (" ");
 float T = (float) L / 256 + H ;
 Serial.print(T);
 Serial.println(" °C");
 delay(1000);

Utile osservare con l'oscilloscopio i dati presenti sul bus durante l'esecuzione del programma. Di seguito un esempio:

Usare le librerie per LM75A

Ovviamente l'uso di una libreria specifica semplifica l'uso di LM75A ed evita la presenza di errori, come quello presente nel codice sopra mostrato (nota 3).

Di seguito l'output del programma di esempio BasicUsage.ino fornito con la libreria M2M_LM75A:

Arduino come Slave

Arduino può essere programmato anche per funzionare come Slave e poter così creare una rete tra un Arduino configurato come Master ed uno o più Arduino configurati come Slave.

Scrivere il codice corrispondente, utilizzando (almeno) due Arduino. Il problema nasce dal fatto che il non funzionamento (certo...) potrebbe derivare da un errore nel codice del Master, un errore nel codice dello Slave, un errore di collegamento oppure tutte queste cose messe insieme: in questo l'analisi delle forme d'onda riveste un ruolo essenziale!

Raspberry PI

Raspberry Pi 4 come default rende disponibile all'utente un bus I2C sui pin del GPIO (nota 4). Esso supporta solo la modalità Master, fino al fast mode (sebbene in genere il clock sia usato solo a 100 kHz).

Per l'utilizzo è necessario configurare I2C.

Utile inoltre l'uso di RPi demo che ospita, tra le altre periferiche, un sensore di temperatura I2C.

Segnali esemplificativi

Il file i2c.zip contiene tre diversi esempi da utilizzare con la versione demo di Picoscope:

  1. Ricerca delle periferiche, mostrata solo in parte. Sono presenti tre periferiche con indirizzo 0x4A, 0x4D, 0x4F
  2. Lettura del registro 0 del dispositivo 0x4F, 1 byte
  3. Lettura del registro 0 del dispositivo 0x4F, 2 byte
  4. Serie di sei frame, alcuni di lettura ed altri di scrittura, di uno o due byte; l'indirizzo del dispositivo è sempre 0x48

Note

  1. Ovviamente è possibile scrivere da sé tale sketch, ma la ricerca di qualcosa di già scritto è estremamente più... comoda
  2. A volte tale resistenza non è facilmente visibile nei circuiti stampati pronti per l'uso (breakout board), ma deve comunque essere aggiunta se già non presente
  3. Quale è l'errore presente nel codice? Un suggerimento: si manifesta con le temperature negative...
  4. I fogli tecnici del processore BCM2711 contiene sei Broadcom Serial Control (BSC) che possono essere usati come controller I2C. Due sono riservati all'interfaccia HDMI, gli altri sono accessibili configurando uno degli Alternate Mode del GPIO
  5. La convenzione tipografica adottata dal produttore potrebbe indurvi in errore...


Pagina creata nell'aprile 2021
Ultima modifica: 25 marzo 2023


Licenza "Creative Commons" - Attribuzione-Condividi allo stesso modo 3.0 Unported


Pagina principaleAccessibilitàNote legaliPosta elettronicaXHTML 1.0 StrictCSS 3

Vai in cima