- Wat is het I2C-communicatieprotocol?
- Hoe I2C-communicatie werkt?
- Waar gebruik ik I2C-communicatie?
- I2C in Arduino
- Componenten vereist
- Schakelschema
- Werkende uitleg
- I2C-programmering in Arduino
- Master Arduino Programming Uitleg
- Slave Arduino Programmering Uitleg
In onze vorige tutorial geleerd over SPI-communicatie in Arduino. Vandaag maken we kennis met een ander serieel communicatieprotocol: I2C (Inter Integrated Circuits). Als I2C wordt vergeleken met SPI, heeft I2C slechts twee draden, terwijl SPI er vier gebruikt en I2C meerdere master en slaaf kan hebben, terwijl SPI slechts één master en meerdere slaves kan hebben. Er zijn dus meer dan één microcontroller in een project die meesters moeten zijn, dan wordt I2C gebruikt. I2C-communicatie wordt over het algemeen gebruikt om te communiceren met een gyroscoop, versnellingsmeter, luchtdruksensoren, LED-displays enz.
In deze Arduino I2C-tutorial zullen we I2C-communicatie gebruiken tussen twee Arduino-boards en (0 tot 127) waarden naar elkaar sturen met behulp van een potentiometer. Waarden worden weergegeven op het 16x2 LCD-scherm dat op elk van de Arduino is aangesloten. Hier zal een Arduino optreden als Master en een andere als Slave. Dus laten we beginnen met de introductie over I2C-communicatie.
Wat is het I2C-communicatieprotocol?
De term IIC staat voor " Inter Integrated Circuits ". Het wordt normaal gesproken aangeduid als I2C of I squared C of zelfs als 2-draads interfaceprotocol (TWI) op sommige plaatsen, maar het betekent allemaal hetzelfde. I2C is een synchroon communicatieprotocol, wat betekent dat beide apparaten die de informatie delen een gemeenschappelijk kloksignaal moeten delen. Het heeft slechts twee draden om informatie te delen, waarvan de ene wordt gebruikt voor het cocksignaal en de andere wordt gebruikt voor het verzenden en ontvangen van gegevens.
Hoe I2C-communicatie werkt?
I2C-communicatie werd voor het eerst geïntroduceerd door Phillips. Zoals eerder gezegd heeft het twee draden, deze twee draden worden over twee apparaten verbonden. Hier wordt het ene apparaat een master genoemd en het andere apparaat als slaaf. Communicatie moet en zal altijd plaatsvinden tussen twee een Master en een Slave. Het voordeel van I2C-communicatie is dat er meer dan één slaaf op een master kan worden aangesloten.
De volledige communicatie vindt plaats via deze twee draden, namelijk Serial Clock (SCL) en Serial Data (SDA).
Seriële klok (SCL): deelt het kloksignaal dat door de master wordt gegenereerd met de slave
Seriële gegevens (SDA): verzendt de gegevens van en naar tussen de master en slave.
Op elk moment kan alleen de master de communicatie starten. Omdat er meer dan één slave in de bus is, moet de master naar elke slave verwijzen met een ander adres. Wanneer hij wordt aangesproken, zal alleen de slaaf met dat specifieke adres antwoorden met de informatie terwijl de anderen stoppen. Op deze manier kunnen we dezelfde bus gebruiken om met meerdere apparaten te communiceren.
De spanningsniveaus van I2C zijn niet voorgedefinieerd. I2C-communicatie is flexibel, wat betekent dat het apparaat dat wordt gevoed door 5v volt, 5v kan gebruiken voor I2C en de 3.3v-apparaten 3v kunnen gebruiken voor I2C-communicatie. Maar wat als twee apparaten die op verschillende voltages werken, via I2C moeten communiceren? Een 5V I2C-bus kan niet worden aangesloten op een 3,3V-apparaat. In dit geval worden spanningsverschuivers gebruikt om de spanningsniveaus tussen twee I2C-bussen af te stemmen.
Er zijn een aantal voorwaarden die een transactie kaderen. De initialisatie van de verzending begint met een dalende flank van SDA, die wordt gedefinieerd als 'START'-voorwaarde in het onderstaande diagram, waarbij de master SCL hoog laat terwijl SDA laag wordt ingesteld.
Zoals weergegeven in het bovenstaande diagram hieronder, De neergaande flank van SDA is de hardwaretrigger voor de START-conditie. Hierna gaan alle apparaten op dezelfde bus in luistermodus.
Op dezelfde manier stopt de stijgende flank van SDA de transmissie die wordt weergegeven als 'STOP'-toestand in het bovenstaande diagram, waarbij de master SCL hoog laat en ook SDA vrijgeeft om HIGH te gaan. Dus stijgende flank van SDA stopt de verzending.
De R / W-bit geeft de transmissierichting van de volgende bytes aan, als het HOOG is, betekent dit dat de slaaf zal verzenden en als het laag is, betekent dit dat de master zal verzenden.
Elke bit wordt op elke klokcyclus verzonden, dus het duurt 8 klokcycli om een byte te verzenden. Na elke verzonden of ontvangen byte wordt de negende klokcyclus vastgehouden voor de ACK / NACK (bevestigd / niet bevestigd). Deze ACK-bit wordt gegenereerd door een slaaf of een master, afhankelijk van de situatie. Voor ACK bit, is SDA te laag ingesteld door de master of slave op 9 ste klokcyclus. Het is dus laag en wordt als ACK beschouwd, anders NACK.
Waar gebruik ik I2C-communicatie?
I2C-communicatie wordt alleen gebruikt voor communicatie op korte afstand. Het is zeker tot op zekere hoogte betrouwbaar omdat het een gesynchroniseerde klokpuls heeft om het slim te maken. Dit protocol wordt voornamelijk gebruikt om te communiceren met sensoren of andere apparaten die informatie naar een master moeten sturen. Het is erg handig wanneer een microcontroller moet communiceren met veel andere slavemodules met een minimum aan alleen draden. Als u op zoek bent naar langeafstandscommunicatie, moet u RS232 proberen en als u op zoek bent naar betrouwbaardere communicatie, moet u het SPI-protocol proberen.
I2C in Arduino
De onderstaande afbeelding toont de I2C-pinnen die aanwezig zijn in Arduino UNO.
I2C-lijn | Pin in Arduino |
SDA | A4 |
SCL | A5 |
Voordat we beginnen met het programmeren van I2C met behulp van twee Arduino. We moeten leren over de Wire-bibliotheek die wordt gebruikt in Arduino IDE.
De bibliotheek
1. Wire.begin (adres):
Gebruik: Deze bibliotheek wordt gebruikt voor het maken van communicatie met I2C-apparaten. Dit start de draadbibliotheek en sluit je aan bij de I2C-bus als een master of slave.
Adres: Het 7-bit slave-adres is optioneel en als het adres niet is gespecificeerd, wordt het op deze manier als master toegevoegd aan de bus.
2. Wire.read ():
Gebruik: Deze functie wordt gebruikt om een byte te lezen die is ontvangen van een master- of slave-apparaat, ofwel is verzonden van een slave-apparaat naar een master-apparaat na een oproep naar requestFrom () of is verzonden van een master naar een slave.
3. Wire.write ():
Gebruik: Deze functie wordt gebruikt om gegevens naar een slave- of masterapparaat te schrijven.
Slave to Master: Slave schrijft gegevens naar een master wanneer Wire.RequestFrom () wordt gebruikt in master.
Master to Slave: Voor verzending van een master naar een slave-apparaat wordt Wire.write () gebruikt tussen oproepen naar Wire.beginTransmission () en Wire.endTransmission ().
Wire.write () kan worden geschreven als:
- Wire.write (waarde)
waarde: een waarde om als een enkele byte te verzenden.
- Wire.write (tekenreeks):
string: een string om te verzenden als een reeks bytes.
- Wire.write (data, lengte):
data: een reeks gegevens die als bytes moeten worden verzonden
lengte: het aantal bytes dat moet worden verzonden.
4. Wire.beginTransmission (adres):
Gebruik: Deze functie wordt gebruikt om een verzending naar het I2C-apparaat te starten met het opgegeven slaafadres. Bouw vervolgens een wachtrij van bytes op voor verzending met de functie write () en verzend ze vervolgens door de functie endTransmission () aan te roepen. 7-bit adres van het apparaat wordt verzonden.
5. Wire.endTransmission ();
Gebruik: Deze functie wordt gebruikt om een verzending naar een slaafapparaat te beëindigen dat is begonnen met beginTransmission () en de bytes verzendt die in de wachtrij stonden door Wire.write ().
6. Wire.onRequest ();
Gebruik: Deze functie wordt aangeroepen wanneer een master gegevens opvraagt met behulp van Wire.requestFrom () van het slave-apparaat. Hier kunnen we de functie Wire.write () opnemen om gegevens naar de master te verzenden.
7. Wire.onReceive ();Gebruik: Deze functie wordt aangeroepen wanneer een slave-apparaat gegevens van een master ontvangt. Hier kunnen we Wire.read () opnemen; functie om de gegevens van de master te lezen.
8. Wire.requestFrom (adres, aantal);
Gebruik: Deze functie wordt in de master gebruikt om bytes op te vragen bij een slave-apparaat. De functie Wire.read () wordt gebruikt om de gegevens te lezen die vanaf het slave-apparaat zijn verzonden.
adres: het 7-bits adres van het apparaat waarvan de bytes moeten worden opgevraagd
hoeveelheid: het aantal bytes dat moet worden opgevraagd
Componenten vereist
- Arduino Uno (2-nummers)
- 16X2 LCD-weergavemodule
- 10K Potentiometer (4-Nos)
- Breadboard
- Verbindingsdraden
Schakelschema
Werkende uitleg
Hier voor het demonstreren van I2C-communicatie in Arduino, gebruiken we twee Arduino UNO met twee 16X2 LCD-schermen die aan elkaar zijn bevestigd en gebruiken we twee potentiometers op beide arduino om de verzendwaarden (0 tot 127) te bepalen van master naar slave en van slave naar master door de potentiometer.
We nemen de analoge ingangswaarde op arduino-pin A0 van (0 tot 5V) met behulp van een potentiometer en zetten deze om in analoge naar digitale waarde (0 tot 1023). Vervolgens worden deze ADC-waarden verder omgezet in (0 tot 127), omdat we alleen 7-bits gegevens kunnen verzenden via I2C-communicatie. De I2C-communicatie vindt plaats via twee draden op pin A4 en A5 van beide arduino.
Waarden op het LCD-scherm van Slave Arduino zullen worden gewijzigd door de POT aan de masterzijde te variëren en vice versa.
I2C-programmering in Arduino
Deze tutorial heeft twee programma's, een voor master Arduino en een voor slave Arduino. Aan het einde van dit project worden complete programma's voor beide kanten gegeven met een demonstratievideo.
Master Arduino Programming Uitleg
1. Allereerst moeten we de Wire-bibliotheek opnemen voor het gebruik van I2C-communicatiefuncties en de LCD-bibliotheek voor het gebruik van LCD-functies. Definieer ook LCD-pinnen voor 16x2 LCD. Lees hier meer over het koppelen van LCD met Arduino.
# omvatten
2. In ongeldige opstelling ()
- We starten seriële communicatie met een baudrate van 9600.
Serial.begin (9600);
- Vervolgens starten we de I2C-communicatie op pin (A4, A5)
Wire.begin (); // Begint I2C-communicatie op pin (A4, A5)
- Vervolgens initialiseren we de LCD-displaymodule in 16X2-modus en geven het welkomstbericht weer en wissen dit na vijf seconden.
lcd.begin (16,2); // Initialiseer LCD-scherm lcd.setCursor (0,0); // Stelt de cursor in op de eerste regel van Display lcd.print ("Circuit Digest"); // Drukt CIRCUIT DIGEST af in LCD lcd.setCursor (0,1); // Stelt de cursor in op de tweede regel van Display lcd.print ("I2C 2 ARDUINO"); // Drukt I2C ARDUINO af in LCD- vertraging (5000); // Vertraging gedurende 5 seconden lcd.clear (); // Wist LCD-scherm
3. In lege lus ()
- Eerst moeten we gegevens van de slaaf krijgen, dus gebruiken we requestFrom () met het slaafadres 8 en we vragen om één byte
Wire.requestFrom (8,1);
De ontvangen waarde wordt gelezen met Wire.read ()
byte MasterReceive = Wire.read ();
- Vervolgens moeten we de analoge waarde lezen van de master arduino POT die is aangesloten op pin A0
int potvalue = analogRead (A0);
We zetten die waarde om in termen van één byte van 0 naar 127.
byte MasterSend = map (potwaarde, 0,1023,0,127);
- Vervolgens moeten we die geconverteerde waarden verzenden, zodat we de verzending beginnen met slave arduino met 8 adressen
Wire.beginTransmission (8); Wire.write (MasterSend); Wire.endTransmission ();
- Vervolgens tonen we die ontvangen waarden van de slave-arduino met een vertraging van 500 microseconden en we ontvangen en tonen die waarden continu.
lcd.setCursor (0,0); // Zet Currsor op regel één van LCD lcd.print (">> Master <<"); // Prints >> Master << op LCD lcd.setCursor (0,1); // Stelt Cursor in op regel twee van LCD lcd.print ("SlaveVal:"); // Prints SlaveVal: in LCD lcd.print (MasterReceive); // Drukt MasterReceive af in LCD ontvangen van Slave Serial.println ("Master ontvangen van slaaf"); // Afdrukken in seriële monitor Serial.println (MasterReceive); vertraging (500); lcd.clear ();
Slave Arduino Programmering Uitleg
1. Hetzelfde als master, allereerst moeten we de Wire-bibliotheek opnemen voor het gebruik van I2C-communicatiefuncties en de LCD-bibliotheek voor het gebruik van LCD-functies. Definieer ook LCD-pinnen voor 16x2 LCD.
# omvatten
2. In ongeldige opstelling ()
- We starten seriële communicatie met een baudrate van 9600.
Serial.begin (9600);
- Vervolgens starten we de I2C-communicatie op pin (A4, A5) met het slave-adres als 8. Hier is het belangrijk om het slave-adres op te geven.
Wire.begin (8);
Vervolgens moeten we de functie aanroepen wanneer Slave waarde ontvangt van master en wanneer Master waarde opvraagt van Slave
Wire.onReceive (ontvangEvent); Wire.onRequest (requestEvent);
- Vervolgens initialiseren we de LCD-displaymodule in 16X2-modus en geven het welkomstbericht weer en wissen dit na vijf seconden.
lcd.begin (16,2); // Initialiseer LCD-scherm lcd.setCursor (0,0); // Stelt de cursor in op de eerste regel van Display lcd.print ("Circuit Digest"); // Drukt CIRCUIT DIGEST af in LCD lcd.setCursor (0,1); // Stelt de cursor in op de tweede regel van Display lcd.print ("I2C 2 ARDUINO"); // Drukt I2C ARDUINO af in LCD- vertraging (5000); // Vertraging gedurende 5 seconden lcd.clear (); // Wist LCD-scherm
3. Vervolgens hebben we twee functies, een voor verzoekgebeurtenis en een voor ontvanggebeurtenis
Voor aanvraag Evenement
Als de master een waarde opvraagt bij de slave, wordt deze functie uitgevoerd. Deze functie neemt de invoerwaarde van de Slave POT en converteert deze in termen van 7-bit en stuurt die waarde naar de master.
void requestEvent () { int potvalue = analogRead (A0); byte SlaveSend = map (potwaarde, 0,1023,0,127); Wire.write (SlaveSend); }
Voor ontvangen evenement
Als de master gegevens naar de slaaf verzendt met het slaafadres (8), wordt deze functie uitgevoerd. Deze functie leest de ontvangen waarde van master en slaat deze op in een variabele van het type byte .
void receEvent (int howMany { SlaveReceived = Wire.read (); }
4. In ongeldige lus ():
We geven de ontvangen waarde van master continu weer in de LCD-displaymodule.
void loop (void) { lcd.setCursor (0,0); // Zet Currsor op regel één van LCD lcd.print (">> Slave <<"); // Prints >> Slave << op LCD lcd.setCursor (0,1); // Stelt Cursor in op regel twee van LCD lcd.print ("MasterVal:"); // Prints MasterVal: in LCD lcd.print (SlaveReceived); // Drukt SlaveReceived-waarde af in LCD ontvangen van Master Serial.println ("Slave ontvangen van Master:"); // Afdrukken in seriële monitor Serial.println (SlaveReceived); vertraging (500); lcd.clear (); }
Door de Potentiometer aan de ene kant te draaien, kun je de variërende waarden op het LCD-scherm aan de andere kant zien:
Dus dit is hoe I2C-communicatie plaatsvindt in Arduino, hier hebben we twee Arduino's gebruikt om niet alleen het verzenden van gegevens te demonstreren, maar ook om de gegevens te ontvangen met behulp van I2C-communicatie. Dus nu kunt u elke I2C-sensor met Arduino verbinden.
De volledige codering voor Master en Slave Arduino wordt hieronder gegeven met een demonstratievideo