- Ce este protocolul de comunicare I2C?
- Cum funcționează comunicarea I2C?
- Unde se utilizează comunicarea I2C?
- I2C în Arduino
- Componente necesare
- Diagrama circuitului
- Explicație de lucru
- Programare I2C în Arduino
- Explicație despre programarea Master Arduino
- Explicație despre programarea Slave Arduino
În tutorialul nostru anterior am aflat despre comunicarea SPI în Arduino. Astăzi vom afla despre un alt protocol de comunicare în serie: I2C (circuite integrate). Comparând I2C cu SPI, I2C are doar două fire, în timp ce SPI folosește patru, iar I2C poate avea mai multe Master și Slave, în timp ce SPI poate avea un singur master și mai mulți sclavi. Deci, există mai mult de un microcontroler într-un proiect care trebuie să fie master, atunci se utilizează I2C. Comunicarea I2C este utilizată în general pentru a comunica cu giroscopul, accelerometrul, senzorii de presiune barometrică, afișajele LED etc.
În acest tutorial Arduino I2C vom folosi comunicarea I2C între două plăci arduino și vom trimite (0 la 127) valori reciproc folosind potențiometru. Valorile vor fi afișate pe ecranul LCD de 16x2 conectat la fiecare dintre Arduino. Aici un Arduino va acționa ca Maestru și altul va acționa ca Sclav. Deci, să începem cu introducerea despre comunicarea I2C.
Ce este protocolul de comunicare I2C?
Termenul IIC înseamnă „ Circuite integrate integrate ”. În mod normal este notat ca I2C sau I pătrat C sau chiar ca protocol de interfață cu 2 fire (TWI) în unele locuri, dar totul înseamnă același lucru. I2C este un protocol de comunicație sincron, ceea ce înseamnă că ambele dispozitive care partajează informațiile trebuie să partajeze un semnal de ceas comun. Are doar două fire pentru a partaja informații, dintre care unul este utilizat pentru semnalul cock și celălalt este utilizat pentru trimiterea și primirea de date.
Cum funcționează comunicarea I2C?
Comunicarea I2C a fost introdusă pentru prima dată de Phillips. Așa cum am spus mai devreme, are două fire, aceste două fire vor fi conectate pe două dispozitive. Aici un dispozitiv este numit master și celălalt este numit slave. Comunicarea ar trebui și va avea loc întotdeauna între doi un Maestru și un Sclav. Avantajul comunicației I2C este că mai mult de un sclav poate fi conectat la un Master.
Comunicarea completă are loc prin intermediul acestor două fire și anume Serial Clock (SCL) și Serial Data (SDA).
Serial Clock (SCL): Partajează semnalul de ceas generat de master cu sclavul
Serial Data (SDA): Trimite datele către și de la Master și slave.
În orice moment, numai comandantul va putea iniția comunicarea. Deoarece există mai mult de un sclav în autobuz, comandantul trebuie să se refere la fiecare sclav folosind o adresă diferită. Când este adresat, numai sclavul cu acea adresă particulară va răspunde cu informațiile în timp ce ceilalți continuă să renunțe. Astfel putem folosi același autobuz pentru a comunica cu mai multe dispozitive.
La nivelurile de tensiune de I2C nu sunt predefinite. Comunicarea I2C este flexibilă, înseamnă că dispozitivul care este alimentat de 5V volt, poate folosi 5v pentru I2C, iar dispozitivele de 3,3v pot folosi 3v pentru comunicarea I2C. Dar dacă două dispozitive care funcționează cu tensiuni diferite, trebuie să comunice folosind I2C? O magistrală I2C de 5V nu poate fi conectată cu dispozitivul de 3.3V. În acest caz, schimbătoarele de tensiune sunt utilizate pentru a se potrivi nivelurilor de tensiune dintre două autobuze I2C.
Există câteva seturi de condiții care încadrează o tranzacție. Inițializarea transmisiei începe cu o margine descendentă a SDA, care este definită ca starea „START” în diagrama de mai jos, în care masterul lasă SCL înalt în timp ce setează SDA scăzut.
După cum se arată în diagrama de mai sus, Marginea descendentă a SDA este declanșatorul hardware pentru starea START. După aceasta, toate dispozitivele din același autobuz intră în modul de ascultare.
În același mod, marginea ascendentă a SDA oprește transmisia, care este prezentată ca stare „STOP” în diagrama de mai sus, unde masterul lasă SCL înalt și eliberează și SDA pentru a merge HIGH. Deci, marginea ascendentă a SDA oprește transmisia.
Bitul R / W indică direcția de transmisie a următoarelor octeți, dacă este HIGH înseamnă că sclavul va transmite și dacă este scăzut înseamnă că masterul va transmite.
Fiecare bit este transmis pe fiecare ciclu de ceas, deci este nevoie de 8 cicluri de ceas pentru a transmite un octet. După fiecare octet trimis sau primit, al nouălea ciclu de ceas este ținut pentru ACK / NACK (confirmat / nerecunoscut). Acest bit ACK este generat fie de slave, fie de master, în funcție de situație. Pentru bitul ACK, SDA este setat la scăzut de către master sau slave la cel de-al 9- lea ciclu de ceas. Deci, este scăzut, considerat ACK altfel NACK.
Unde se utilizează comunicarea I2C?
Comunicarea I2C este utilizată numai pentru comunicarea pe distanțe scurte. Cu siguranță, este sigur într-o anumită măsură, deoarece are un impuls de ceas sincronizat pentru a-l face inteligent. Acest protocol este utilizat în principal pentru a comunica cu senzori sau alte dispozitive care trebuie să trimită informații unui master. Este foarte la îndemână atunci când un microcontroler trebuie să comunice cu multe alte module slave folosind un minim de numai fire. Dacă sunteți în căutarea unei comunicații pe termen lung, ar trebui să încercați RS232 și dacă căutați o comunicare mai fiabilă, ar trebui să încercați protocolul SPI
I2C în Arduino
Imaginea de mai jos prezintă pinii I2C prezenți în Arduino UNO.
Linia I2C | Pin în Arduino |
SDA | A4 |
SCL | A5 |
Înainte de a începe programarea I2C folosind două Arduino. Trebuie să aflăm despre biblioteca Wire utilizată în Arduino IDE.
biblioteca
1. Wire.begin (adresa):
Utilizare: Această bibliotecă este utilizată pentru comunicarea cu dispozitivele I2C. Aceasta inițiază biblioteca Wire și se alătură autobuzului I2C ca master sau slave.
Adresă: Adresa slave de 7 biți este opțională și dacă adresa nu este specificată, se alătură autobuzului ca un master ca acesta.
2. Wire.read ():
Utilizare: Această funcție este utilizată pentru a citi un octet care a fost primit de la dispozitivul master sau slave, fie care a fost transmis de la un dispozitiv slave la un dispozitiv master după un apel pentru a solicita De la () sau a fost transmis de la un master la un slave.
3. Wire.write ():
Utilizare: Această funcție este utilizată pentru a scrie date pe un dispozitiv slave sau master.
Slave to Master: Slave scrie date unui master atunci când Wire.RequestFrom () este utilizat în master.
Master to Slave: pentru transmiterea de la un dispozitiv master la slave Wire.write () este utilizat între apeluri către Wire.beginTransmission () și Wire.endTransmission ().
Wire.write () poate fi scris ca:
- Wire.write (valoare)
valoare: o valoare de trimis ca un singur octet.
- Wire.write (șir):
șir: un șir de trimis ca o serie de octeți.
- Wire.write (date, lungime):
date: o serie de date de trimis sub formă de octeți
lungime: numărul de octeți de transmis.
4. Wire.beginTransmission (adresa):
Utilizare: Această funcție este utilizată pentru a începe o transmisie către dispozitivul I2C cu adresa sclavă dată. Ulterior, construiți coada de octeți pentru transmisie cu funcția write () și apoi transmiteți-le apelând funcția endTransmission () . Se transmite adresa de 7 biți a dispozitivului.
5. Wire.endTransmission ();
Utilizare: Această funcție este utilizată pentru a termina o transmisie către un dispozitiv sclav care a fost început de beginTransmission () și transmite octeții care au fost în coadă de Wire.write ().
6. Wire.onRequest ();
Utilizare: Această funcție este apelată atunci când un comandant solicită date folosind Wire.requestFrom () de pe dispozitivul slave. Aici putem include funcția Wire.write () pentru a trimite date către master.
7. Wire.onReceive ();Utilizare: Această funcție este apelată atunci când un dispozitiv slave primește date de la un master. Aici putem include Wire.read (); funcție pentru a citi datele trimise de la master.
8. Wire.requestFrom (adresă, cantitate);
Utilizare: Această funcție este utilizată în master pentru a solicita octeți de la un dispozitiv slave. Funcția Wire.read () este utilizată pentru a citi datele trimise de pe dispozitivul slave.
adresa: adresa de 7 biți a dispozitivului de la care se solicită octeți
cantitate: numărul de octeți de solicitat
Componente necesare
- Arduino Uno (2 numere)
- Modul afișaj LCD 16X2
- Potențiometru 10K (4 numere)
- Breadboard
- Conectarea firelor
Diagrama circuitului
Explicație de lucru
Aici, pentru a demonstra comunicarea I2C în Arduino, folosim Two Arduino UNO cu două afișaje LCD 16X2 atașate unul la altul și folosim două potențiometre la ambele arduino pentru a determina valorile de trimitere (0 la 127) de la master la slave și de la slave la master, variind potențiometru.
Luăm valoarea analogică de intrare la pinul arduino A0 de la (0 la 5V) folosind potențiometrul și le convertim în valoare analogică la digitală (0 la 1023). Apoi, aceste valori ADC sunt în continuare convertite în (0 la 127), deoarece putem trimite doar date pe 7 biți prin intermediul comunicației I2C. Comunicarea I2C are loc prin două fire la pinul A4 și A5 ale ambelor arduino.
Valorile de pe ecranul LCD al Slave Arduino vor fi modificate prin modificarea POT la partea master și invers.
Programare I2C în Arduino
Acest tutorial are două programe, unul pentru master Arduino și altul pentru Arduino slave. Programe complete pentru ambele părți sunt oferite la sfârșitul acestui proiect cu un videoclip demonstrativ.
Explicație despre programarea Master Arduino
1. În primul rând trebuie să includem biblioteca Wire pentru utilizarea funcțiilor de comunicație I2C și biblioteca LCD pentru utilizarea funcțiilor LCD. De asemenea, definiți pinii LCD pentru 16x2 LCD. Aflați mai multe despre interfața LCD cu Arduino aici.
#include
2. În configurare nulă ()
- Începem comunicarea în serie la rata Baud 9600.
Serial.begin (9600);
- Apoi începem comunicarea I2C la pin (A4, A5)
Wire.begin (); // Începe comunicarea I2C la pin (A4, A5)
- Apoi inițializăm modulul de afișare LCD în modul 16X2 și afișăm mesajul de întâmpinare și ștergem după cinci secunde.
lcd.inceput (16,2); // Inițializați afișajul LCD lcd.setCursor (0,0); // Setează cursorul la prima linie a afișajului lcd.print ("Circuit Digest"); // Tipărește CIRCUIT DIGEST în LCD lcd.setCursor (0,1); // Setează cursorul la a doua linie a afișajului lcd.print ("I2C 2 ARDUINO"); // Tipărește I2C ARDUINO în întârziere LCD (5000); // Întârziere timp de 5 secunde lcd.clear (); // Șterge afișajul LCD
3. În bucla nulă ()
- Mai întâi trebuie să obținem date de la Slave, așa că folosim requestFrom () cu adresa slave 8 și solicităm un octet
Wire.requestFrom (8,1);
Valoarea primită este citită folosind Wire.read ()
octet MasterReceive = Wire.read ();
- În continuare, trebuie să citim valoarea analogică din arduino master POT atașat pinului A0
int potvalue = analogRead (A0);
Convertim acea valoare în termeni de un octet ca 0 la 127.
octet MasterSend = hartă (potvalue, 0,1023,0,127);
- În continuare, trebuie să trimitem acele valori convertite, astfel încât să începem transmisia cu arduino slave cu 8 adrese
Wire.beginTransmission (8); Wire.write (MasterSend); Wire.endTransmission ();
- Apoi afișăm valorile primite de la arduino-ul slave cu o întârziere de 500 de microsecunde și primim și afișăm în mod continuu acele valori.
lcd.setCursor (0,0); // Setează Currsor la prima linie a LCD lcd.print (">> Master <<"); // Imprimă >> Master << la LCD lcd.setCursor (0,1); // Setează cursorul la linia a doua a LCD lcd.print ("SlaveVal:"); // Tipărește SlaveVal: în LCD lcd.print (MasterReceive); // Imprimă MasterReceive în LCD primit de la Slave Serial.println ("Master primit de la Slave"); // Imprimă în Serial Monitor Serial.println (MasterReceive); întârziere (500); lcd.clear ();
Explicație despre programarea Slave Arduino
1. La fel ca masterul, în primul rând trebuie să includem biblioteca Wire pentru utilizarea funcțiilor de comunicație I2C și biblioteca LCD pentru utilizarea funcțiilor LCD. De asemenea, definiți pinii LCD pentru 16x2 LCD.
#include
2. În configurare nulă ()
- Începem comunicarea în serie la rata Baud 9600.
Serial.begin (9600);
- Apoi începem comunicarea I2C la pin (A4, A5) cu adresa slave ca 8. Aici este important să specificați adresa slave.
Wire.begin (8);
Apoi, trebuie să apelăm funcția atunci când Slave primește valoare de la master și când Master solicită valoare de la Slave
Wire.onReceive (receiveEvent); Wire.onRequest (requestEvent);
- Apoi inițializăm modulul de afișare LCD în modul 16X2 și afișăm mesajul de întâmpinare și ștergem după cinci secunde.
lcd.inceput (16,2); // Inițializați afișajul LCD lcd.setCursor (0,0); // Setează cursorul la prima linie a afișajului lcd.print ("Circuit Digest"); // Tipărește CIRCUIT DIGEST în LCD lcd.setCursor (0,1); // Setează cursorul la a doua linie a afișajului lcd.print ("I2C 2 ARDUINO"); // Tipărește I2C ARDUINO în întârziere LCD (5000); // Întârziere timp de 5 secunde lcd.clear (); // Șterge afișajul LCD
3. În continuare avem două funcții, una pentru evenimentul de solicitare și una pentru evenimentul de primire
Pentru cerere Eveniment
Când valoarea solicitării Master de la sclav această funcție va fi executată. Această funcție preia valoarea de intrare din Slave POT și o convertește în termeni de 7 biți și trimite această valoare către master.
void requestEvent () { int potvalue = analogRead (A0); octet SlaveSend = hartă (potvalue, 0,1023,0,127); Wire.write (SlaveSend); }
Pentru a primi eveniment
Când Maestrul trimite date către sclav cu adresă de sclav (8) această funcție va fi executată. Această funcție citește valoarea primită de la master și stochează într-o variabilă de tip octet .
void receiveEvent (int howMany { SlaveReceived = Wire.read (); }
4. În bucla Void ():
Afișăm valoarea primită de la master în mod continuu în modulul de afișaj LCD.
bucla void (void) { lcd.setCursor (0,0); // Setează Currsor la prima linie a LCD lcd.print (">> Slave <<"); // Imprimă >> Slave << la LCD lcd.setCursor (0,1); // Setează cursorul la linia a doua a LCD lcd.print ("MasterVal:"); // Printează MasterVal: în LCD lcd.print (SlaveReceived); // Tipărește valoarea SlaveReceived în LCD primit de la Master Serial.println ("Slave Received From Master:"); // Imprimă în Serial Monitor Serial.println (SlaveReceived); întârziere (500); lcd.clear (); }
Prin rotirea potențiometru la o parte, puteți vedea valorile variind de pe ecranul LCD pe o altă latură:
Așadar, așa are loc comunicarea I2C în Arduino, aici folosim două Arduino pentru a demonstra nu numai trimiterea de date, ci și primirea datelor folosind comunicarea I2C. Deci, acum puteți interfața orice senzor I2C cu Arduino.
Codificarea completă pentru Master și Slave Arduino este prezentată mai jos cu un videoclip demonstrativ