- Cos'è il protocollo di comunicazione I2C?
- Come funziona la comunicazione I2C?
- Dove utilizzare la comunicazione I2C?
- I2C in Arduino
- Componenti richiesti
- Schema elettrico
- Spiegazione di lavoro
- Programmazione I2C in Arduino
- Master Arduino Programming Explanation
- Spiegazione della programmazione di Arduino slave
Nel nostro precedente tutorial abbiamo imparato a conoscere la comunicazione SPI in Arduino. Oggi impareremo a conoscere un altro protocollo di comunicazione seriale: I2C (Inter Integrated Circuits). Confrontando I2C con SPI, I2C ha solo due fili mentre SPI ne usa quattro e I2C può avere più Master e Slave, mentre SPI può avere solo un master e più slave. Quindi ci sono più microcontrollori in un progetto che devono essere master, quindi viene utilizzato I2C. La comunicazione I2C viene generalmente utilizzata per comunicare con giroscopio, accelerometro, sensori di pressione barometrica, display a LED ecc.
In questo tutorial Arduino I2C useremo la comunicazione I2C tra due schede arduino e invieremo valori (da 0 a 127) l'uno con l'altro usando il potenziometro. I valori verranno visualizzati sull'LCD 16x2 collegato a ciascuno degli Arduino. Qui un Arduino fungerà da Master e un altro fungerà da Slave. Quindi iniziamo con l'introduzione sulla comunicazione I2C.
Cos'è il protocollo di comunicazione I2C?
Il termine IIC sta per " Inter Integrated Circuits ". Normalmente è indicato come I2C o I al quadrato C o anche come protocollo di interfaccia a 2 fili (TWI) in alcuni punti, ma significa tutto lo stesso. I2C è un protocollo di comunicazione sincrono che significa che entrambi i dispositivi che condividono le informazioni devono condividere un segnale di clock comune. Ha solo due fili per condividere le informazioni di cui uno viene utilizzato per il segnale del rubinetto e l'altro viene utilizzato per inviare e ricevere dati.
Come funziona la comunicazione I2C?
La comunicazione I2C è stata introdotta per la prima volta da Phillips. Come detto in precedenza, ha due fili, questi due fili saranno collegati tra due dispositivi. Qui un dispositivo è chiamato master e l'altro dispositivo è chiamato slave. La comunicazione dovrebbe e avverrà sempre tra due un Master e uno Slave. Il vantaggio della comunicazione I2C è che più di uno slave può essere collegato a un Master.
La comunicazione completa avviene attraverso questi due fili, ovvero Serial Clock (SCL) e Serial Data (SDA).
Serial Clock (SCL): condivide il segnale di clock generato dal master con lo slave
Dati seriali (SDA): invia i dati da e verso il master e lo slave.
In qualsiasi momento solo il master potrà avviare la comunicazione. Poiché nel bus è presente più di uno slave, il master deve fare riferimento a ciascuno slave utilizzando un indirizzo diverso. Quando viene indirizzato solo lo slave con quel particolare indirizzo risponderà con le informazioni mentre gli altri continuano a smettere. In questo modo possiamo utilizzare lo stesso bus per comunicare con più dispositivi.
I livelli di tensione di I2C non sono predefiniti. La comunicazione I2C è flessibile, significa che il dispositivo che è alimentato da 5v volt, può usare 5v per I2C ei dispositivi 3.3v possono usare 3v per la comunicazione I2C. Ma cosa succede se due dispositivi che funzionano con tensioni diverse, devono comunicare utilizzando I2C? Un bus I2C 5V non può essere collegato con 3.3V dispositivo. In questo caso vengono utilizzati i variatori di tensione per abbinare i livelli di tensione tra due bus I2C.
Esistono alcune serie di condizioni che inquadrano una transazione. L'inizializzazione della trasmissione inizia con un fronte di discesa di SDA, che è definita come condizione di 'AVVIO' nel diagramma sottostante in cui il master lascia SCL alto mentre imposta SDA basso.
Come mostrato nel diagramma qui sotto, Il fronte di discesa di SDA è il trigger hardware per la condizione START. Dopodiché tutti i dispositivi sullo stesso bus entrano in modalità di ascolto.
Allo stesso modo, il fronte di salita di SDA arresta la trasmissione che è indicata come condizione di "STOP" nel diagramma sopra, dove il master lascia SCL alto e rilascia anche SDA per andare ALTO. Quindi il fronte di salita di SDA interrompe la trasmissione.
Il bit R / W indica la direzione di trasmissione dei byte successivi, se è HIGH significa che lo slave trasmetterà e se è basso significa che il master trasmetterà.
Ogni bit viene trasmesso ad ogni ciclo di clock, quindi sono necessari 8 cicli di clock per trasmettere un byte. Dopo ogni byte inviato o ricevuto, il nono ciclo di clock viene mantenuto per ACK / NACK (riconosciuto / non riconosciuto). Questo bit ACK viene generato dallo slave o dal master a seconda della situazione. Per il bit ACK, SDA è impostato su basso dal master o dallo slave al 9 ° ciclo di clock. Quindi è basso considerato come ACK altrimenti NACK.
Dove utilizzare la comunicazione I2C?
La comunicazione I2C viene utilizzata solo per comunicazioni a breve distanza. È certamente affidabile in una certa misura poiché ha un impulso di clock sincronizzato per renderlo intelligente. Questo protocollo viene utilizzato principalmente per comunicare con sensori o altri dispositivi che devono inviare informazioni a un master. È molto utile quando un microcontrollore deve comunicare con molti altri moduli slave utilizzando un minimo di soli fili. Se stai cercando una comunicazione a lungo raggio dovresti provare RS232 e se stai cercando una comunicazione più affidabile dovresti provare il protocollo SPI.
I2C in Arduino
L'immagine sotto mostra i pin I2C presenti in Arduino UNO.
Linea I2C | Pin in Arduino |
SDA | A4 |
SCL | A5 |
Prima di iniziare a programmare I2C usando due Arduino. Dobbiamo conoscere la libreria Wire utilizzata nell'IDE di Arduino.
La biblioteca
1. Wire.begin (indirizzo):
Uso: questa libreria viene utilizzata per comunicare con i dispositivi I2C. Questo avvia la libreria Wire e unisciti al bus I2C come master o slave.
Indirizzo: L'indirizzo slave a 7 bit è opzionale e se l'indirizzo non è specificato, si unisce al bus come master in questo modo.
2. Wire.read ():
Uso: questa funzione viene utilizzata per leggere un byte ricevuto dal dispositivo master o slave, che è stato trasmesso da un dispositivo slave a un dispositivo master dopo una chiamata a requestFrom () o è stato trasmesso da un master a uno slave.
3. Wire.write ():
Uso: questa funzione viene utilizzata per scrivere dati su un dispositivo slave o master.
Slave to Master: Slave scrive i dati su un master quando Wire.RequestFrom () viene utilizzato in master.
Da Master a Slave: per la trasmissione da un dispositivo master a slave Wire.write () viene utilizzato tra le chiamate a Wire.beginTransmission () e Wire.endTransmission ().
Wire.write () può essere scritto come:
- Wire.write (valore)
valore: un valore da inviare come un singolo byte.
- Wire.write (stringa):
stringa: una stringa da inviare come una serie di byte.
- Wire.write (dati, lunghezza):
dati: un array di dati da inviare come byte
lunghezza: il numero di byte da trasmettere.
4. Wire.beginTransmission (indirizzo):
Uso: questa funzione viene utilizzata per iniziare una trasmissione al dispositivo I2C con l'indirizzo slave specificato. Successivamente, crea una coda di byte per la trasmissione con la funzione write () e poi trasmettili chiamando la funzione endTransmission () . Viene trasmesso l'indirizzo a 7 bit del dispositivo.
5. Wire.endTransmission ();
Uso: questa funzione viene utilizzata per terminare una trasmissione a un dispositivo slave che è stata iniziata da beginTransmission () e trasmette i byte che sono stati accodati da Wire.write ().
6. Wire.onRequest ();
Uso: questa funzione viene chiamata quando un master richiede dati utilizzando Wire.requestFrom () dal dispositivo slave. Qui possiamo includere la funzione Wire.write () per inviare dati al master.
7. Wire.onReceive ();Uso: questa funzione viene chiamata quando un dispositivo slave riceve un dato da un master. Qui possiamo includere Wire.read (); funzione per leggere i dati inviati dal master.
8. Wire.requestFrom (indirizzo, quantità);
Uso: questa funzione viene utilizzata nel master per richiedere byte da un dispositivo slave. La funzione Wire.read () viene utilizzata per leggere i dati inviati dal dispositivo slave.
indirizzo: l'indirizzo a 7 bit del dispositivo da cui richiedere i byte
quantità: il numero di byte da richiedere
Componenti richiesti
- Arduino Uno (2-Nos)
- Modulo display LCD 16X2
- Potenziometro 10K (4-Nos)
- Breadboard
- Collegamento dei cavi
Schema elettrico
Spiegazione di lavoro
Qui per dimostrare la comunicazione I2C in Arduino, utilizziamo due Arduino UNO con due display LCD 16X2 collegati l'uno all'altro e utilizziamo due potenziometri su entrambi arduino per determinare i valori di invio (da 0 a 127) da master a slave e da slave a master variando il potenziometro.
Prendiamo il valore analogico in ingresso al pin arduino A0 da (0 a 5 V) utilizzando il potenziometro e lo convertiamo in valore analogico in digitale (da 0 a 1023). Quindi questi valori ADC vengono ulteriormente convertiti in (da 0 a 127) poiché possiamo inviare solo dati a 7 bit tramite la comunicazione I2C. La comunicazione I2C avviene tramite due fili ai pin A4 e A5 di entrambi arduino.
I valori sull'LCD di Slave Arduino verranno modificati variando il POT sul lato master e viceversa.
Programmazione I2C in Arduino
Questo tutorial ha due programmi uno per master Arduino e l'altro per slave Arduino. I programmi completi per entrambe le parti sono forniti alla fine di questo progetto con un video dimostrativo.
Master Arduino Programming Explanation
1. Prima di tutto dobbiamo includere la libreria Wire per l'utilizzo delle funzioni di comunicazione I2C e la libreria LCD per l'utilizzo delle funzioni LCD. Definire anche i pin LCD per LCD 16x2. Scopri di più sull'interfacciamento dell'LCD con Arduino qui.
#includere
2. In void setup ()
- Iniziamo la comunicazione seriale al baud rate 9600.
Serial.begin (9600);
- Successivamente iniziamo la comunicazione I2C sul pin (A4, A5)
Wire.begin (); // Inizia la comunicazione I2C sul pin (A4, A5)
- Successivamente inizializziamo il modulo display LCD in modalità 16X2 e visualizziamo il messaggio di benvenuto e cancelliamo dopo cinque secondi.
lcd.begin (16,2); // Inizializza il display LCD lcd.setCursor (0,0); // Imposta il cursore sulla prima riga di Display lcd.print ("Circuit Digest"); // Stampa CIRCUIT DIGEST in LCD lcd.setCursor (0,1); // Imposta il cursore sulla seconda riga di Display lcd.print ("I2C 2 ARDUINO"); // Stampa I2C ARDUINO in ritardo LCD (5000); // Ritardo di 5 secondi lcd.clear (); // Cancella il display LCD
3. In void loop ()
- Per prima cosa dobbiamo ottenere i dati dallo Slave quindi usiamo requestFrom () con l'indirizzo dello slave 8 e chiediamo un byte
Wire.requestFrom (8,1);
Il valore ricevuto viene letto utilizzando Wire.read ()
byte MasterReceive = Wire.read ();
- Successivamente dobbiamo leggere il valore analogico dal POT arduino master collegato al pin A0
int potvalue = analogRead (A0);
Convertiamo quel valore in termini di un byte da 0 a 127.
byte MasterSend = map (potvalue, 0,1023,0,127);
- Successivamente dobbiamo inviare quei valori convertiti in modo da iniziare la trasmissione con arduino slave con indirizzo 8
Wire.beginTransmission (8); Wire.write (MasterSend); Wire.endTransmission ();
- Successivamente visualizziamo quei valori ricevuti dall'arduino slave con un ritardo di 500 microsecondi e riceviamo e visualizziamo continuamente quei valori.
lcd.setCursor (0,0); // Imposta Currsor alla prima riga di LCD lcd.print (">> Master <<"); // Stampa >> Master << su LCD lcd.setCursor (0,1); // Imposta il cursore alla riga due di LCD lcd.print ("SlaveVal:"); // Stampa SlaveVal: in LCD lcd.print (MasterReceive); // Stampa MasterReceive sul display LCD ricevuto da Slave Serial.println ("Master Received From Slave"); // Stampa in Serial Monitor Serial.println (MasterReceive); ritardo (500); lcd.clear ();
Spiegazione della programmazione di Arduino slave
1. Come il master, prima di tutto dobbiamo includere la libreria Wire per l'utilizzo delle funzioni di comunicazione I2C e la libreria LCD per l'utilizzo delle funzioni LCD. Definire anche i pin LCD per LCD 16x2.
#includere
2. In void setup ()
- Iniziamo la comunicazione seriale al baud rate 9600.
Serial.begin (9600);
- Successivamente iniziamo la comunicazione I2C sul pin (A4, A5) con indirizzo slave come 8. Qui è importante specificare l'indirizzo slave.
Wire.begin (8);
Successivamente dobbiamo chiamare la funzione quando lo Slave riceve il valore dal master e quando il Master richiede il valore dallo Slave
Wire.onReceive (receiveEvent); Wire.onRequest (requestEvent);
- Successivamente inizializziamo il modulo display LCD in modalità 16X2 e visualizziamo il messaggio di benvenuto e cancelliamo dopo cinque secondi.
lcd.begin (16,2); // Inizializza il display LCD lcd.setCursor (0,0); // Imposta il cursore sulla prima riga di Display lcd.print ("Circuit Digest"); // Stampa CIRCUIT DIGEST in LCD lcd.setCursor (0,1); // Imposta il cursore sulla seconda riga di Display lcd.print ("I2C 2 ARDUINO"); // Stampa I2C ARDUINO in ritardo LCD (5000); // Ritardo di 5 secondi lcd.clear (); // Cancella il display LCD
3. Successivamente abbiamo due funzioni una per l'evento di richiesta e una per l'evento di ricezione
Per richiesta Evento
Quando il Master richiede un valore dallo slave, questa funzione verrà eseguita. Questa funzione prende il valore in ingresso dal POT Slave e lo converte in termini di 7 bit e invia quel valore al master.
void requestEvent () { int potvalue = analogRead (A0); byte SlaveSend = map (potvalue, 0,1023,0,127); Wire.write (SlaveSend); }
Per ricevere evento
Quando il Master invia dati allo slave con indirizzo slave (8), questa funzione verrà eseguita. Questa funzione legge il valore ricevuto dal master e lo memorizza in una variabile di tipo byte .
void receiveEvent (int howMany { SlaveReceived = Wire.read (); }
4. In Void loop ():
Visualizziamo continuamente il valore ricevuto dal master nel modulo display LCD.
void loop (void) { lcd.setCursor (0,0); // Imposta Currsor alla prima riga di LCD lcd.print (">> Slave <<"); // Stampa >> Slave << su LCD lcd.setCursor (0,1); // Imposta il cursore alla riga due di LCD lcd.print ("MasterVal:"); // Prints MasterVal: in LCD lcd.print (SlaveReceived); // Stampa il valore SlaveReceived nell'LCD ricevuto da Master Serial.println ("Slave Received From Master:"); // Stampa in Serial Monitor Serial.println (SlaveReceived); ritardo (500); lcd.clear (); }
Con ruotando il potenziometro da un lato, è possibile vedere i valori variabili sul display LCD su un altro lato:
Quindi è così che avviene la comunicazione I2C in Arduino, qui abbiamo usato due Arduino per dimostrare non solo l'invio di dati ma anche la ricezione dei dati utilizzando la comunicazione I2C. Quindi ora puoi interfacciare qualsiasi sensore I2C ad Arduino.
La codifica completa per Master e Slave Arduino è fornita di seguito con un video dimostrativo