Comunicazione I2C arduino to arduino

La Comunicazione I2C arduino to arduino è un argomento che spesso mi è stato richiesto nei commenti e sul quale la documentazione che ho trovato in rete è tanta ma spesso confusionaria.

Comunicazione I2C arduino to arduino

Da qualche giorno con un amico, Paolo, abbiamo deciso di fare dei test in merito alla possibilità di sfruttare l’I2C per trasmettere messaggi da un arduino ad un altro.

Paolo è un fisico ed è l’autore del conduttimetro, utilizzato nell’orto idroponico, per cui le prime trasmissioni abbiamo deciso di eseguirle con dei valori numerici interi in modo da poter utilizzare come test successivo il conduttimetro di Paolo.

Accenni di teoria

In una comunicazione I2C deve essere presente un Master ed uno, o più Slave, ossia un nodo principale ( Master I2C ) ed uno, o più nodi, secondario ( Slave I2C )

Il compito del Master è di gestire tutta la comunicazione I2C sia inviando i messaggi a tutti gli slave connessi, sia richiedendo a ciascun slave di inviargli un messaggio.

Per eseguire il test puoi usare, come abbiamo fatto noi, due arduino uno.

Schema per la Comunicazione I2C arduino to arduino

Per i test puoi usare due Arduino uno collegandoli come nello schema:

Comunicazione I2C arduino to arduino diagram

nei test che abbiamo eseguito l’alimentazione di ciascun arduino è avvenuta con il cavo USB e per rendere l’esperimento allo stesso tempo divertente e ricco di suspence ad alimentare l’arduino usato come Master c’era il Pc di Paolo e per l’alimentazione dell’arduino usato come slave ho usato il mio Mac, più variabili non potevamo introdurle; ecco perché nella foto che mostra i collegamenti non c’è il cavo positivo ( +5v ) ad unire i due arduino:

Comunicazione I2C arduino to arduino collegamenti

Lo sketch Master

lo sketch Master si preoccupa di inviare allo slave 3 messaggi distinti da un carattere prima di ciascun messaggio:

  • $ per un messaggio da 12 byte
  • W per un messaggio simile al 12 ma con funzionalità Slave differenti
  • M per un messaggio da 13 byte e valori differenti dai precedenti

Lo scopo dell’esperimento è finalizzato alla realizzazione di un progetto più complesso di cui questo scketch rappresenta solo il primo passo relativo alla Comunicazione I2C arduino to arduino.

#include <Wire.h>

int ECHO = 1;
byte header=0;
byte i = 0;
word CSspec = 0;  //  Conducibilità corretta
word Temp = 0;  // Temperatura acqua
word Vcc = 0;  // alimentazione in mV
byte vettore[12] = {0,0,0,0,0,0,0,0,0,0};
byte flag;
word RS;
word CS;

void setup() {
   Serial.begin(9600);
   delay(1000);
   Wire.begin();           

}

void loop() {

     flag = '$';
     header = 14;    //ID nodo
     RS = 1230;      // resistenza acqua  ohm
     CS = 4589;      // Conducibilità a 20°  uS
     CSspec = 3250;  // Conducibilità specifica uS/cm
     Temp =  2734;  // Temperatura in 0,1 °K
     Vcc  =  3300;  // Alimentazione in mV

     vettore[0] = highByte(RS);
     vettore[1] = lowByte(RS);
     vettore[2] = highByte(CS);
     vettore[3] = lowByte(CS);        
     vettore[4] = highByte(CSspec);
     vettore[5] = lowByte(CSspec);
     vettore[6] = highByte(Temp);
     vettore[7] = lowByte(Temp);
     vettore[8] = highByte(Vcc);
     vettore[9] = lowByte(Vcc);
              
     Wire.beginTransmission(8); // transmit to device #8
     Wire.write(flag);
     Serial.print(flag,HEX); Serial.print(" ");
     Serial.print(header,HEX); Serial.print(" ");
     Wire.write(header);
     for(i=0; i < 10; i++){
       Wire.write(vettore[i]);
       Serial.print(vettore[i],HEX);Serial.print(" ");
     }
     Wire.endTransmission();    // stop transmitting
     Serial.println();

     flag = 'W';
     Wire.beginTransmission(8); // transmit to device #8
     Wire.write(flag);
     Serial.print(flag,HEX); Serial.print(" ");
     Serial.print(header,HEX); Serial.print(" ");
     Wire.write(header);
     for(i=0; i < 10; i++){
       Wire.write(vettore[i]);
       Serial.print(vettore[i],HEX);Serial.print(" ");
     }
     Wire.endTransmission();    // stop transmitting
     Serial.println();

     flag = 'M';
     word M1 = 4760;      // Conducibilità specifica uS/cm media nodo 1
     word M2 = 3440;      // Conducibilità specifica uS/cm media nodo 2
     word M3 = 2160;      // Conducibilità specifica uS/cm media nodo 3
     word T1 =  2734;  // Temperatura in 0,1 °K  media nodo 1
     word T2 =  2823;  // Temperatura in 0,1 °K  media nodo 21
     word T3 =  2947;  // Temperatura in 0,1 °K  media nodo 3

     vettore[0] = highByte(M1);
     vettore[1] = lowByte(M1);
     vettore[2] = highByte(M2);
     vettore[3] = lowByte(M2);        
     vettore[4] = highByte(M3);
     vettore[5] = lowByte(M3);
     vettore[6] = highByte(T1);
     vettore[7] = lowByte(T1);
     vettore[8] = highByte(T2);
     vettore[9] = lowByte(T2);
     vettore[10] = highByte(T3);
     vettore[11] = lowByte(T3);
      
     Wire.beginTransmission(8); // transmit to device #8
     Wire.write(flag);
     Serial.print(flag,HEX); Serial.print(" ");
     for(i=0; i < 12; i++){
       Wire.write(vettore[i]);
       Serial.print(vettore[i],HEX);Serial.print(" ");
     }
     Wire.endTransmission();    // stop transmitting
     Serial.println();
 delay(2000);
}

leggendo lo sketch linea per linea noti che alla linea 01: includi la libreria Wire.h necessaria per la gestione della Comunicazione I2C arduino to arduino;

linee 03-12: definisci le variabili che ti serviranno nello sketch per memorizzare i dati da trasmettere;

linee 15-17: inizializza la comunicazione seriale a 9600 baud, attendi 1 secondo ( 1000 millisecondi ) ed inizializza la comunicazione I2C con il metodo begin() della libreria Wire;

linee 23-29: imposta i valori da inviare via I2C, osserva in particolare il valore della variabile flag e della variabile header che saranno identificativi in funzione dei quali lo Slave deciderà dove destinare il messaggio che riceve. Le restanti variabili contengono i dati che trasmetterai;

linee 31-40: definisci un array di tipo byte in cui ciascun elemento contiene un byte da trasferire allo slave I2C. Se osservi le linee 31 e 32 noti che il valore RS è scomposto in 2 byte, in quanto sappiamo che sono sufficienti 2 byte per rappresentare il dato numerico contenuto nella variabile RS, ed in particolare il byte più alto lo inseriamo nell’indice 0 del vettore mentre il byte più basso nell’indice 1. Nelle linee successive, fino alla 40, scomponi e inserisci i restanti valori negli altri elementi del vettore;

linea 42: con il metodo beginTransmission() inizi una trasmissione verso l’indirizzo contenuto tra parentesi, abbiamo deciso di utilizzare il valore 8 che troverai anche in altri numerosi esempi su internet.

linea 43: con il metodo write() invii allo Slave 8, l’altro arduino in questo esempio, il valore contenuto tra parentesi, in questa linea il valore flag;

linee 44-45: scrivi sul monitor seriale i valori relativi a flagheader;

linea 46: così come fatto alla linea 43, invia il valore di header;

linee 47-50: crea un ciclo for per tutta la lunghezza del vettore, in questo esempio da 0 a 9, e per ciascun valore di i invia il dato contenuto nell’elemento del vettore corrispondente, scrivendolo anche sul monitor seriale;

linee 51-52: indica la conclusione della trasmissione I2C con il metodo endTransmission() della libreria Wire;

linee 54-65: sono identiche alle linee 42-52 a parte la linea 54 che ridefinisce il valore di flag cambiandone il valore in “W”;

linea 67: ridefinisci nuovamente il valore per la variabile flag in modo che l’ultima sequenza inviata inizi con il valore “M”

linee 68-73: definisci 6 variabili di tipo word in ciascuna delle quali inserisci i nuovi valori da inviare;

linee 75-86: scomponi le variabili definite alle linee 68-73 in un vettore simile a quello creato alle linee 31-40 scomponendo ciascuno dei sei valori in due elementi;

linee 88-96: trasmetti il flag via I2C allo slave con indirizzo 8 e successivamente i 12 byte in sequenza;

linea 97: attendi 2 secondi prima di ripetere il loop() e quindi l’invio.

Nel prossimo articolo leggerai il codice che abbiamo usato per ricevere i dati sull’arduino slave I2C.

  • Questo sito ed i suoi contenuti è fornito "così com'è" e Mauro Alfieri non rilascia alcuna dichiarazione o garanzia di alcun tipo, esplicita o implicita, riguardo alla completezza, accuratezza, affidabilità, idoneità o disponibilità del sito o delle informazioni, prodotti, servizi o grafiche correlate contenute sul sito per qualsiasi scopo.
  • Ti chiedo di leggere e rispettare il regolamento del sito prima di utilizzarlo
  • Ti chiedo di leggere i Termini e Condizioni d'uso del sito prima di utilizzarlo
  • In qualità di Affiliato Amazon io ricevo un guadagno dagli acquisti idonei qualora siano presenti link al suddetto sito.

Permalink link a questo articolo: https://www.mauroalfieri.it/elettronica/comunicazione-i2c-arduino-to-arduino.html

13 commenti

Vai al modulo dei commenti

    • armando il 27 Marzo 2016 alle 00:38
    • Rispondi

    Dove e’ la seconda parte ? lo sketch con indirizzo 08 ?

    1. Ciao Armando,
      fossi in te io proverei a cercare nel blog.

    • Francesco il 15 Agosto 2016 alle 18:07
    • Rispondi

    Ciao, ho provato a cercare sul blog ma non ho trovato l’articolo con lo sketch dello slave.
    Sono interessato a questo articolo per un progetto che prevede Raspberry e Arduino per un dolly computerizzato ed estendibile.
    Scusa il disturbo e buone vacanze

    1. Ciao Francesco,
      come esempio per comprendere la descrizione di uno sketch i2c slave con arduino puoi utilizzare quello descritto in questo articolo:
      https://www.mauroalfieri.it/elettronica/attiny85-encoder-arduino-slave.html
      ovviamente dovrai adattarlo alle tue esigenze, ti serve solo per comprendere come funziona il discorso master-slave i2c.

    • marco il 26 Aprile 2017 alle 15:51
    • Rispondi

    Tutto molto interessante. Suggerirei di ampliare la descrizione del codice, e di definire più precisamente i fattori.

    1. Ciao Marco,
      grazie per il suggerimento, mi descrivi meglio cosa intendi per “definire più precisamente i fattori” ?

    • Matteo il 15 Giugno 2017 alle 12:45
    • Rispondi

    Ciao,
    devo fare una comunicazione I2C tra un Arduino UNO e un Arduino Mega.
    Quali sono i collegamenti?
    Grazie

    1. Ciao Matteo,
      sulla uno sono quelli che vedi nello schema di questo articolo, sulla Mega puoi consultare il datasheet pubblico sul sito arduino.cc

    • andrea pasqualin il 10 Novembre 2020 alle 08:14
    • Rispondi

    splendido articolo mi piacerebbe provarlo ma non trovo il link alla parte slave

    1. Ciao Andrea,
      hai ragione, forse me lo sono perso, per ovviare puoi adattare uno degli articoli simili al seguente ( https://www.mauroalfieri.it/elettronica/i2c-attiny85-slave-adc.html ) in cui al posto dell’arduino ho usato un Attiny85.
      I concetti sono i medesimi e cambiano solo le librerie che per l’Attiny85 sono più leggere mentre per Arduino puoi usare la Wire come per il Master.

    • Luigi il 9 Dicembre 2020 alle 21:52
    • Rispondi

    Ciao Mauro.
    Intanto complimenti per il sito e per i tantissimi tutorial, chiari e semplici.
    Non riesco però a trovare la seconda puntata de “Comunicazione I2C arduino to arduino” (quella dello slave)
    Mi potresti dare il link diretto?
    Grazie infinite e complimenti ancora
    Luigi

    1. Ciao Luigi,
      non sei il primo che mi segnala la cosa, in realtà mi sono accorto di non averlo mai pubblicato e lo farò appena possibile.
      Nell’attesa se vuoi puoi leggere gli articoli dedicati alla comunicazione I2C con Attiny85 ed adattare la parte slave di uno di quei progetti.

    • Luigi il 14 Gennaio 2021 alle 10:19
    • Rispondi

    Ciao Mauro
    Complimenti per il tuo sito e per i tuoi chiarissimi articoli.
    Non riesco a trovare il link alla seconda parte (relativa allo slave) di questo articolo (Comunicazione I2C arduino to arduino).
    Saresti così gentile da dirmelo?
    Grazie
    Luigi

Lascia un commento

Il tuo indirizzo email non sarà pubblicato.

Questo sito usa Akismet per ridurre lo spam. Scopri come i tuoi dati vengono elaborati.