Comunicazione tra Arduino tramite I2C

Come collegare due Arduino usando il bus I2C.

Una caratteristica che reputo molto interessante è la possibilità di espandere Arduino tramite l’uso di shield. La maggior parte di queste schede aggiuntive sono però progettate per compiere una funzione specifica, non programmabile.
Esistono alcuni metodi che permettono di comunicare con altri dispositivi utilizzando come canale di trasmissione dati i protocolli seriali (I2C, SPI o RS232). Questo rende possibile demandare ad una scheda slave funzioni di elaborazione gravose, che non vogliamo far eseguire alla scheda master. Ho realizzato questo piccolo tutorial usando il bus I2C per creare uno scambio dati tra un Arduino ed un chip ATmega328 standalone.

Bus i2c

Il bus I2C, basandosi su due fili, non permette la comunicazione contemporanea tra Master e Slave. Lo scambio dati deve essere gestito dal Master tramite gli indirizzi (univoci) degli slave. Il flusso può essere sintetizzato in questo modo

  1. Il Master invia sul bus un bit di start
  2. Il Master invia sul bus l’indirizzo dello slave con cui vuole comunicare
  3. Il Master decide se scrivere o leggere dal dispositivo
  4. Lo Slave legge o scrive in base alla richiesta del Master

La libreria Wire dispone di tutte le funzioni necessarie alla realizzazione Master-Slave tra due schede Arduino. Lo schema del circuito che ho realizzato è visibile nella figura seguente.

Collegamento Master Slave tra due Arduino UNO

Come detto precedentemente lo schema si basa su Arduino Uno impiegato come Master e con un ATmega328 impiegato come slave.

Il codice permette di inviare un dato numerico allo slave, che provvederà ad incrementarlo per poi rispedirlo al Master.

[c]
//MASTER
#include <Wire.h>

byte x = 0;
byte num = 0;

void setup()
{
//inizializzo la libreria Wire come Master
Wire.begin();

//init seiale
Serial.begin(9600);
//avviso che il programma è avviato
Serial.println("START");

}

void loop()
{
//invio sul bus I2C un byte al device
//che ha come indirizzo il valore 0x04
//start trasmissione
Wire.beginTransmission(0x04);
//invio un byte
Wire.write(x);
//fine trasmissione
Wire.endTransmission();

delayMicroseconds(500);

//richiedo un byte allo slave che ha indirizzo 0x04
Wire.requestFrom(0x04, 1);

//attendo la disponibilità di dati sul bus i2c
while(Wire.available())
{
//quando è presente un dato avvia
//la lettura
num = Wire.read();
}

//incrementa il valore del byte
x++;

//verifico che il byte letto dallo slave sia stato
//incrementato
if(num != x)
Serial.println("ERRORE");

delay(5);

}

[/c]

Il codice seguente è relativo allo Slave

[c]
//SLAVE
#include <Wire.h>

byte x = 0;

void setup()
{
//inizializzo la libreria
//imposto l’indirizzo dello slave
Wire.begin(0x04);

//eventi per la ricezione del dato
//e per la richiesta del dato
Wire.onReceive(receiveEvent);
Wire.onRequest(requestEvent);
}

void loop()
{
//esegui qualcosa
delay(1000);
}

void receiveEvent(int data)
{
//questo evento viene generato quando sul bus
//è presente un dato da leggere

//eseguo la lettura
x = Wire.read();

//elaboro il dato letto
x++;
}

void requestEvent()
{
//questo evento viene generato quando il master
//richiede ad uno specifico slave
//una richiesta di dati

//spedisco il dato al Master
Wire.write(x);

}

[/c]

I commenti presenti nel codice permettono di capire ciò che avviene tra i due dispositivi.

Di seguito uno screenshot dei dati scambiati sul bus

Scambio dati master slave su bus i2c

Di seguito invece la trasmissione del Master

Trasmissione i2c Master

15 risposte a Comunicazione tra Arduino tramite I2C

  • Ottimo tutorial come sempre, complimenti!

  • Eccellente…adesso manca la trattazione del bus SPI !!!

    Grazie

  • Ciao,
    complimenti anche da parte mia, ma che distanze riesce a coprire I2C?

    Saluti
    Pixel

  • Ciao,
    grazie al tuo tutorial mi è venuta l’idea per realizzare un progetto… vorrei fare comunicare 2 Atmega e un DS1307 (RTC). Il mio problema è che il primo Atmega comunicherà con l’RTC mentre l’altro comunicherà col primo per inviare comandi etc. ma nella rete ci può essere un solo master. Hai suggerimenti?

    Ciao Complimenti e Grazie

    • Ciao Pixel
      l’Arduino Master leggerà dall’RTC e poi invierà lui stesso i dato all’atmega slave. Praticamente è come descritto nel tutoria, devi solo aggiungere la parte di lettura dall’RTC e inviare i dati all’atmega slave

      a presto

  • Salve; nella linea 33 del master, viene inviata la richieste di un byte allo slave 0x04.
    Supponiamo di avere 3 slave: 0x04, 0x05, 0x06, e di fare la stessa richiesta ad ogniuno di loro in modo ricorsivo.
    Ad un certo punto, lo slave 0x05 per qualsiasi motivo non funziona più, che succede?
    C’è un modo per verificare, prima di un’eventuale richiesta, se lo slave chiamato risulta disponibile, in modo da saltare ed evitare possibili blocchi?
    Grazie.

    • Ciao Claudio
      in effetti la Wire.available() attende la risposta dello slave. se la risopsta non avviene bisogna indagare se sia un problema elettrico oppure software. Inoltre bisogna essere certi che lo slave non invii dati mentre ne stiamo spedendo con il master. Così non posso dirti cosa avviene nel tuo circuito, mi servirebbero i sorgenti e lo schema del tuo circuito per individuare il problema.

      per maggiori chiarimenti mandami una mail

      a presto

  • Ciao, lo scambio dati può avvenire anche se ho un sensore I2c già collegato ? Grazie e complimenti per i tuoi tutorial, per i neofiti come me rendono comprensibili argomenti prima sconosciuti

    • Ciao Maurizio,
      grazie per i complimenti! Non ho capito bene la tua domanda, lo scambio dati intendi ra il master e lo slave? il sensore già collegato cosa vuol dire?

      a presto

      • Scusami, mi spiego meglio. Ho un arduino che misura temperatura umidità ed altre cose ma utilizzo sia RTC che LCD su I2c. La domanda è se collego sempre in parallelo anche un altro arduino (con a bordo gsm shield) posso inviare dati tra i 2 senza che l’RTC o LCD smettano di funzionare ?
        Grazie ancora
        Maurizio

  • Ciao, complimenti per il post!!! una domanda proprio da ragazzo dilettante: qual’è lo schema per collegare altri N slave? potresti aiutarmi via mail? :)
    Grazie, Carlo

  • che valori hanno le 2 resistenze nello schema?

Rimani aggiornato

La mia lista dei prodotti
Compra su Amazon Italia

Compra su Amazon Italia
Sondaggi

Arduino.cc vs Arduino.org

Visualizza risultati

Loading ... Loading ...
Seguimi su Twitter