- Kaj je komunikacijski protokol I2C?
- Kako deluje komunikacija I2C?
- Kje uporabiti komunikacijo I2C?
- I2C v Arduinu
- Potrebne komponente
- Shema vezja
- Delovna razlaga
- Programiranje I2C v Arduinu
- Pojasnilo glavnega programiranja Arduino
- Pojasnilo programiranja slave Arduino
V prejšnji vadnici smo spoznali komunikacijo SPI v Arduinu. Danes bomo spoznali še en protokol serijske komunikacije: I2C (Inter Integrated Circuits). Če primerjamo I2C s SPI, ima I2C samo dve žici, medtem ko SPI uporablja štiri in I2C ima lahko več glavnih in podrejenih, SPI pa lahko samo enega glavnega in več podrejenih. Torej je v projektu več kot en mikrokrmilnik, ki mora biti glavni, potem pa se uporablja I2C. Komunikacija I2C se običajno uporablja za komunikacijo z žiroskopom, merilnikom pospeška, barometričnimi senzorji tlaka, LED zasloni itd.
V tej vadnici za Arduino I2C bomo uporabili komunikacijo I2C med dvema ploščama arduino in si s potenciometrom medsebojno pošiljali vrednosti (od 0 do 127). Vrednosti bodo prikazane na 16x2 LCD-ju, priključenem na vsak Arduino. Tu bo en Arduino deloval kot mojster, drugi pa kot suženj. Začnimo torej z uvodom o komunikaciji I2C.
Kaj je komunikacijski protokol I2C?
Izraz IIC pomeni " Inter integrirana vezja ". Običajno je označen kot I2C ali I na kvadrat C ali celo kot dvožični vmesniški protokol (TWI), ponekod pa vseeno pomeni enako. I2C je sinhroni komunikacijski protokol, kar pomeni, da morata obe napravi, ki si delita informacije, deliti skupen signal ure. Ima le dve žici za izmenjavo informacij, od katerih se ena uporablja za signal petelina, druga pa za pošiljanje in sprejemanje podatkov.
Kako deluje komunikacija I2C?
Komunikacijo I2C je prvi predstavil Phillips. Kot že rečeno, ima dve žici, ti dve žici bosta povezani med dvema napravama. Tu se ena naprava imenuje master, druga pa kot slave. Komunikacija bi morala in bo vedno potekala med dvema Master in Sužnjem. Prednost komunikacije I2C je v tem, da je na glavno enoto mogoče povezati več kot eno pomožno enoto.
Popolna komunikacija poteka prek teh dveh žic, in sicer serijske ure (SCL) in serijskih podatkov (SDA).
Serijska ura (SCL): deli urni signal, ki ga generira poveljnik, s pomožnim
Zaporedni podatki (SDA): pošlje podatke med glavno in pomožno enoto in med njimi.
Kadar koli bo komunikacijo lahko sprožil samo poveljnik. Ker je v vodilu več podrejenih naprav, se mora poveljnik sklicevati na vsakega podrejenega z drugim naslovom. Ko je naslovljen samo suženj s tem naslovom, bo odgovoril s podatki, medtem ko bodo ostali nehali. Na ta način lahko z istim vodilom komuniciramo z več napravami.
Na ravni napetosti v I2C niso vnaprej določene. I2C komunikacija je prilagodljiva, pomeni napravo, ki jo napaja 5v voltov, lahko uporablja 5v za I2C, naprave 3.3v pa 3v za komunikacijo I2C. Kaj pa, če morata dve napravi, ki delujeta na različne napetosti, komunicirati s pomočjo I2C? 5V I2C ni mogoče povezati z 3,3 napravo. V tem primeru se napetostni preklopniki uporabljajo za usklajevanje ravni napetosti med dvema vodiloma I2C.
Obstaja nekaj pogojev, ki določajo transakcijo. Inicializacija prenosa se začne s padajočim robom SDA, ki je v spodnjem diagramu opredeljen kot pogoj 'START', kjer glavni pusti SCL visoko, medtem ko SDA nastavi nizko.
Kot je prikazano na zgornjem diagramu spodaj, Spodnji rob SDA je sprožilec strojne opreme za stanje START. Po tem vse naprave na istem vodilu preidejo v način poslušanja.
Na enak način naraščajoči rob SDA ustavi prenos, ki je v zgornjem diagramu prikazan kot pogoj 'STOP', kjer glavni pusti SCL visoko in prav tako spusti SDA, da gre VISOKO. Torej naraščajoči rob SDA ustavi prenos.
R / W bit označuje smer prenosa naslednjih bajtov, če je VISOK, pomeni, da bo podrejeni podrejen in če je nizek, pomeni, da bo prenašal glavni.
Vsak bit se prenese v vsakem taktnem ciklu, zato je za prenos bajta potrebnih 8 urnih ciklov. Po vsakem poslanem ali prejetem bajtu se izvede deveti takt za ACK / NACK (potrjen / nepriznan). Ta bit ACK generira podrejeni ali glavni, odvisno od situacije. Za bit ACK je SDA glavni ali pomožni nastavljen na nizko vrednost pri 9. taktnem ciklu. Torej je nizka, šteje se za ACK, sicer NACK.
Kje uporabiti komunikacijo I2C?
Komunikacija I2C se uporablja samo za komunikacijo na kratke razdalje. Vsekakor je zanesljiv do neke mere, saj ima sinhroniziran urni impulz, da postane pameten. Ta protokol se v glavnem uporablja za komunikacijo s senzorjem ali drugimi napravami, ki morajo informacije pošiljati glavnemu. Zelo priročno je, kadar mora mikrokrmilnik komunicirati s številnimi drugimi pomožnimi moduli z najmanj samo žicami. Če iščete komunikacijo na dolge razdalje, poskusite RS232, če pa iščete bolj zanesljivo komunikacijo, poskusite s protokolom SPI.
I2C v Arduinu
Spodnja slika prikazuje zatiče I2C, ki so prisotni v Arduino UNO.
Linija I2C | Pripnite v Arduino |
SDA | A4 |
SCL | A5 |
Preden začnemo s programiranjem I2C z uporabo dveh Arduino. Spoznati moramo knjižnico Wire, ki se uporablja v Arduino IDE.
knjižnica
1. Wire.begin (naslov):
Uporaba: Ta knjižnica se uporablja za komunikacijo z napravami I2C. S tem zaženite knjižnico Wire in se priključite vodilu I2C kot glavni ali podrejeni.
Naslov: 7-bitni podrejeni naslov ni obvezen in če naslov ni podan, se vodilu pridruži kot glavni, kot je ta.
2. Wire.read ():
Uporaba: Ta funkcija se uporablja za branje bajta, ki je bil prejet iz glavne ali podrejene naprave, bodisi ta, ki je bil poslan iz podrejene naprave v glavno napravo po klicu requestFrom () ali pa je bil prenesen iz glavne enote v podrejeno.
3. Wire.write ():
Uporaba: Ta funkcija se uporablja za zapisovanje podatkov v pomožno ali glavno napravo.
Slave to Master: Slave zapisuje podatke v master, ko se v masteru uporablja Wire.RequestFrom () .
Master to Slave: Za prenos iz glavne v slave napravo Wire.write () se uporablja vmes med klicema Wire.beginTransmission () in Wire.endTransmission ().
Wire.write () lahko zapišemo kot:
- Wire.write (vrednost)
vrednost: vrednost, ki jo pošljete v enem bajtu.
- Wire.write (niz):
niz: niz, ki ga pošljete kot niz bajtov.
- Wire.write (podatki, dolžina):
podatki: niz podatkov za pošiljanje v bajtih
dolžina: število bajtov za prenos.
4. Wire.beginTransmission (naslov):
Uporaba: Ta funkcija se uporablja za začetek prenosa na napravo I2C z danim podrejenim naslovom. Nato zgradite čakalno vrsto bajtov za prenos s funkcijo write () in jih nato pošljite s klicem funkcije endTransmission () . Prenese se 7-bitni naslov naprave.
5. Wire.endTransmission ();
Uporaba: Ta funkcija se uporablja za zaključek prenosa na podrejeno napravo, ki se je začel z beginTransmission (), in prenaša bajte, ki jih je Wire.write () postavil v čakalno vrsto.
6. Wire.onRequest ();
Uporaba: Ta funkcija se pokliče, ko poveljnik od podrejene naprave zahteva podatke z uporabo Wire.requestFrom () . Tu lahko vključimo funkcijo Wire.write () za pošiljanje podatkov glavnemu.
7. Wire.onReceive ();Uporaba: Ta funkcija se pokliče, ko podrejena naprava prejme podatke od glavne enote. Tu lahko vključimo Wire.read (); funkcija za branje podatkov, poslanih iz glavne enote.
8. Wire.requestFrom (naslov, količina);
Uporaba: Ta funkcija se v glavni enoti uporablja za zahtevanje bajtov od podrejene naprave. Funkcija Wire.read () se uporablja za branje podatkov, poslanih iz podrejene naprave.
address: 7-bitni naslov naprave za zahtevanje bajtov
količina: število bajtov, ki jih je treba zahtevati
Potrebne komponente
- Arduino Uno (2 št.)
- Zaslonski modul LCD 16X2
- 10K potenciometer (4-št.)
- Breadboard
- Povezovanje žic
Shema vezja
Delovna razlaga
Tukaj za prikaz komunikacije I2C v Arduinu uporabljamo dva Arduino UNO z dvema LCD zaslonoma 16X2, ki sta pritrjena drug na drugega, in z dvema potenciometroma na obeh arduino določamo vrednosti pošiljanja (od 0 do 127) od glavnega do pomožnega in suženjskega do glavnega, tako da spremenimo potenciometer.
Z uporabo potenciometra vzamemo vhodno analogno vrednost na arduino pin A0 od (0 do 5V) in jih pretvorimo v analogno v digitalno vrednost (0 do 1023). Nato se te vrednosti ADC nadalje pretvorijo v (0 do 127), saj lahko prek komunikacije I2C pošljemo samo 7-bitne podatke. Komunikacija I2C poteka prek dveh žic na zatičih A4 in A5 obeh arduino.
Vrednosti na LCD-ju Slave Arduino se bodo spremenile s spreminjanjem vrednosti POT na glavni strani in obratno.
Programiranje I2C v Arduinu
Ta vadnica ima dva programa, enega za master Arduino in drugega za slave Arduino. Celotni programi za obe strani so podani na koncu tega projekta z demonstracijskim videom.
Pojasnilo glavnega programiranja Arduino
1. Najprej moramo vključiti knjižnico Wire za uporabo komunikacijskih funkcij I2C in knjižnico LCD za uporabo funkcij LCD. Določite tudi zatiče LCD za LCD 16x2. Več o povezovanju LCD-ja z Arduinom lahko preberete tukaj.
#include
2. V void setup ()
- Začnemo serijsko komunikacijo s hitrostjo prenosa 9600.
Serial.begin (9600);
- Nato začnemo komunikacijo I2C na pin (A4, A5)
Wire.begin (); // Začne komunikacijo I2C na pin (A4, A5)
- Nato modul LCD zaslona inicializiramo v načinu 16X2 in po petih sekundah prikažemo pozdravno sporočilo in počistimo.
lcd.begin (16,2); // Inicializiramo LCD zaslon lcd.setCursor (0,0); // Nastavi kazalec v prvo vrstico zaslona lcd.print ("Circuit Digest"); // natisne CIRCUIT DIGEST v LCD lcd.setCursor (0,1); // Nastavi kazalec v drugi vrstici zaslona lcd.print ("I2C 2 ARDUINO"); // natisne I2C ARDUINO z zakasnitvijo LCD (5000); // Zamuda za 5 sekund lcd.clear (); // Počisti LCD zaslon
3. V void zanki ()
- Najprej moramo dobiti podatke od podrejenega, zato uporabimo requestFrom () z podrejenim naslovom 8 in zahtevamo en bajt
Wire.requestFrom (8,1);
Prejeto vrednost preberemo z uporabo Wire.read ()
bajt MasterReceive = Wire.read ();
- Nato moramo prebrati analogno vrednost iz glavne arduino POT, pritrjene na pin A0
int potvalue = analogRead (A0);
To vrednost pretvorimo v en bajt kot 0 na 127.
bajt MasterSend = map (potvalue, 0,1023,0,127);
- Nato moramo te pretvorjene vrednosti poslati, tako da začnemo prenos s podrejenim arduinom z naslovom 8
Wire.beginTransmission (8); Wire.write (MasterSend); Wire.endTransmission ();
- Nato prikažemo tiste prejete vrednosti iz podrejenega arduina z zakasnitvijo 500 mikrosekund in te vrednosti neprekinjeno sprejemamo in prikazujemo.
lcd.setCursor (0,0); // nastavi kurzor v prvi vrstici LCD lcd.print (">> Master <<"); // Natisne >> Master << na LCD lcd.setCursor (0,1); // Nastavi kazalec v drugi vrstici LCD lcd.print ("SlaveVal:"); // Natisne SlaveVal: v LCD lcd.print (MasterReceive); // Natisne MasterReceive na LCD-ju, prejetem od Slave Serial.println ("Master Received From Slave"); // Natisne v Serial Monitor Serial.println (MasterReceive); zamuda (500); lcd.clear ();
Pojasnilo programiranja slave Arduino
1. Enako kot master, najprej moramo vključiti knjižnico Wire za uporabo komunikacijskih funkcij I2C in knjižnico LCD za uporabo funkcij LCD. Določite tudi zatiče LCD za LCD 16x2.
#include
2. V void setup ()
- Začnemo serijsko komunikacijo s hitrostjo prenosa 9600.
Serial.begin (9600);
- Nato začnemo komunikacijo I2C na pin (A4, A5) s pomožnim naslovom 8. Tu je pomembno, da določimo naslov pomožnega.
Wire.begin (8);
Nato moramo poklicati funkcijo, ko podrejeni prejme vrednost od glavne in ko glavni zahteva vrednost od podrejene
Wire.onReceive (receiveEvent); Wire.onRequest (requestEvent);
- Nato modul LCD zaslona inicializiramo v načinu 16X2 in po petih sekundah prikažemo pozdravno sporočilo in počistimo.
lcd.begin (16,2); // Inicializiramo LCD zaslon lcd.setCursor (0,0); // Nastavi kazalec v prvo vrstico zaslona lcd.print ("Circuit Digest"); // natisne CIRCUIT DIGEST v LCD lcd.setCursor (0,1); // Nastavi kazalec v drugi vrstici zaslona lcd.print ("I2C 2 ARDUINO"); // natisne I2C ARDUINO z zakasnitvijo LCD (5000); // Zamuda za 5 sekund lcd.clear (); // Počisti LCD zaslon
3. Nato imamo dve funkciji, eno za dogodek zahteve in drugo za dogodek prejema
Za zahtevo Dogodek
Ko se vrednost glavne zahteve iz podrejenega izvede, se ta funkcija izvede. Ta funkcija vzame vhodno vrednost iz podrejenega POT-a in jo pretvori v 7-bitno in jo pošlje masterju.
void requestEvent () { int potvalue = analogRead (A0); bajt SlaveSend = map (potvalue, 0,1023,0,127); Wire.write (SlaveSend); }
Za dogodek prejema
Ko Master pošlje podatke podrejenemu s podrejenim naslovom (8), se ta funkcija izvede. Ta funkcija prebere prejeto vrednost iz glavne in shrani v spremenljivko bajta tipa.
void receiveEvent (int howMany { SlaveReceived = Wire.read (); }
4. V zanki Void ():
Prejeto vrednost od masterja neprekinjeno prikazujemo v modulu LCD zaslona.
void loop (void) { lcd.setCursor (0,0); // nastavi kurzor v prvi vrstici LCD lcd.print (">> Slave <<"); // Natisne >> Slave << na LCD lcd.setCursor (0,1); // Nastavi kazalec v drugi vrstici LCD lcd.print ("MasterVal:"); // Natisne MasterVal: v LCD lcd.print (SlaveReceived); // Natisne vrednost SlaveReceived na LCD, prejeto od Master Serial.println ("Slave Received From Master:"); // Natisne v Serial Monitor Serial.println (SlaveReceived); zamuda (500); lcd.clear (); }
Z vrtenjem potenciometra na eni strani lahko na LCD-ju na drugi strani vidite različne vrednosti:
Torej, tako poteka komunikacija I2C v Arduinu, tukaj imamo dva Arduinosa, da dokažemo ne le pošiljanje podatkov, temveč tudi sprejemanje podatkov s pomočjo komunikacije I2C. Zdaj lahko na Arduino povežete kateri koli senzor I2C.
Popolno kodiranje za Master in Slave Arduino je prikazano spodaj s predstavitvenim videoposnetkom