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.
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
- Il Master invia sul bus un bit di start
- Il Master invia sul bus l’indirizzo dello slave con cui vuole comunicare
- Il Master decide se scrivere o leggere dal dispositivo
- 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.
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
Di seguito invece la trasmissione del Master
Related posts
15 Comments
Lascia un commento Annulla risposta
Questo sito usa Akismet per ridurre lo spam. Scopri come i tuoi dati vengono elaborati.
Articoli popolari
Sorry. No data so far.
.Net micro framework Arduino Arduino Webserver Domotica Flyport I2C IOT Netduino OpenPicus raspberry RTC Speed Test
Ottimo tutorial come sempre, complimenti!
Grazie!
troppo gentile!
Eccellente…adesso manca la trattazione del bus SPI !!!
Grazie
Grazie!
appena ho un po di tempo scriverò un tutorial anche sul bus SPI
a presto
Marco
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?
Ciao Alessansro
sono entrambi da 2.2K
a presto
Marco