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.

Prima di inserire un commento, per favore, leggi il regolamento

Permanent link to this article: http://www.mauroalfieri.it/elettronica/comunicazione-i2c-arduino-to-arduino.html

8 comments

Skip to comment form

    • armando on 27 Mar 2016 at 00:38
    • Reply

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

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

    • Francesco on 15 Ago 2016 at 18:07
    • Reply

    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:
      http://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 on 26 Apr 2017 at 15:51
    • Reply

    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 on 15 Giu 2017 at 12:45
    • Reply

    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

Lascia un commento

Your email address will not be published.

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