Het populaire I2C-protocol maakt het mogelijk om twee of meer Arduino-kaarten te laten communiceren. Ontdek hoe u ze kunt verbinden en coderen.
Hoewel een enkele Arduino veel taken kan uitvoeren, kunnen sommige projecten het gebruik van meer dan één bord vereisen om verschillende functionaliteiten aan te kunnen. Om gegevensoverdracht tussen de twee microcontrollers mogelijk te maken, moet dus een communicatieprotocol zoals CAN, SPI, I2C of UART worden ingesteld.
In deze gids behandelen we de basisprincipes van hoe I2C werkt, de hardwareverbindingen en de software-implementatie die nodig is om twee Arduino-kaarten in te stellen als I2C-master- en slave-apparaten.
Wat is I2C?
Inter-Integrated Circuit (I2C) is een veelgebruikt communicatieprotocol in ingebedde systemen en microcontrollers om gegevensoverdracht tussen elektronische apparaten mogelijk te maken. In tegenstelling tot SPI (Serial Peripheral Interface), kunt u met I2C meer dan één master-apparaat aansluiten op een bus met enkele of meerdere slave-apparaten. Het werd voor het eerst gebruikt door Philips en staat ook bekend als het Two Wire Interface (TWI) communicatieprotocol.
Hoe werkt I2C-communicatie?
I2C gebruikt twee bidirectionele lijnen: Serial Data (SDA) en Serial Clock (SCL) om gegevens over te dragen en de communicatie tussen apparaten te synchroniseren. Elk apparaat dat op de I2C-bus is aangesloten, heeft een uniek adres dat het tijdens de communicatie identificeert. Dankzij het I2C-protocol kunnen meerdere apparaten dezelfde bus delen en elk apparaat kan als master of als slave fungeren.
De communicatie wordt geïnitieerd door het masterapparaat en onjuiste adressering van slaveapparaten kan overdrachtsfouten veroorzaken. Bekijk onze uitgebreide gids op hoe UART, SPI en I2C seriële communicatie werken om je wat context te geven.
Een belangrijk voordeel van I2C-communicatie dat het vermelden waard is, is de flexibiliteit die het biedt als het gaat om energiebeheer. Apparaten die op verschillende spanningsniveaus werken, kunnen nog steeds effectief communiceren met behulp van spanningsverschuivers. Dit betekent dat apparaten die werken op 3,3V spanningsverschuivers nodig hebben om verbinding te maken met een 5V I2C-bus.
De draadbibliotheek
De Wire-bibliotheek is een ingebouwde Arduino-bibliotheek die functies biedt om via I2C te communiceren. Het gebruikt twee pinnen - SDA en SCL - op het Arduino-bord voor I2C-communicatie.
I2C-pinnen op de Arduino Uno:
Arduino Nano I2C-pinnen:
Om de bibliotheek te gebruiken, moet u de Draad.h header-bestand aan het begin van uw Arduino-schets.
#erbij betrekken
De Wire-bibliotheek biedt functies om communicatie met een I2C-apparaat te initiëren, gegevens te verzenden en gegevens te ontvangen. Enkele belangrijke functies die u moet kennen, zijn:
- Draad.begin(): gebruikt om lid te worden van de I2C-bus en communicatie te initiëren.
- Wire.beginTransmission(): wordt gebruikt om het slave-adres op te geven en een verzending te starten.
- Draad.schrijven(): gebruikt om gegevens naar het I2C-apparaat te sturen.
- Wire.endTransmission(): wordt gebruikt om de verzending te beëindigen en op fouten te controleren.
- Wire.requestFrom(): gebruikt om gegevens van het I2C-apparaat op te vragen.
- Draad.beschikbaar(): gebruikt om te controleren of er gegevens beschikbaar zijn om te lezen van het I2C-apparaat.
- Draad.lezen(): gebruikt om gegevens van het I2C-apparaat te lezen.
Gebruik de Wire.beginTransmission() functie om het adres van de sensor in te stellen, dat als argument wordt ingevoegd. Als het adres van de sensor bijvoorbeeld is 0x68, zou je gebruiken:
Draad.beginVerzending(0x68);
Arduino I2C hardware-installatie
Om twee Arduino-kaarten met I2C te verbinden, hebt u de volgende hardwarecomponenten nodig:
- Twee Arduino-kaarten (master en slave)
- Broodplank
- Jumper draden
- Twee pull-up weerstanden van 4,7 kΩ
Verbind de SDA En SCL pinnen van beide Arduino-boards op een breadboard. Sluit de pull-up weerstanden tussen de SDA En SCL pinnen en de 5V stroomrail op het breadboard. Verbind ten slotte de twee breadboards met behulp van hulpdraden.
Arduino Uno-circuit
Arduino Nano-circuit
De Arduino-kaarten instellen als I2C Master- en Slave-apparaten
Gebruik de Wire.requestFrom() functie om het adres op te geven van het slave-apparaat waarmee we willen communiceren. Gebruik dan de Draad.lezen() functie om gegevens van het slaafapparaat te krijgen.
Master-apparaatcode:
#erbij betrekken
leegteopgericht(){
Draad.beginnen(); // sluit je aan bij de i2c-bus
Serieel.beginnen(9600); // start serieel voor uitvoer
}
leegteontvang data(){
int adres = 8;
int bytesToRead = 6;
Draad.aanvraag van(adres, bytesToRead);
terwijl (Draad.beschikbaar()) {
char gegevens = Draad.lezen();
Serieel.afdrukken(gegevens);
}
vertraging(500);
}
leegtelus(){
ontvang data();
}
De Wire.onReceive() functie wordt gebruikt om aan te geven wat er moet gebeuren als de slave gegevens ontvangt van het masterapparaat. In de bovenstaande code is de Draad.beschikbaar() functie controleert of gegevens beschikbaar zijn, en de Draad.lezen() functie leest de gegevens die door het masterapparaat zijn verzonden.
Slave-apparaatcode:
#erbij betrekken
leegteopgericht(){
Draad.beginnen(8); // sluit je aan bij de I2C-bus met adres 8
Draad.opOntvangen(gebeurtenis ontvangen); // bel ontvangEvent wanneer gegevens worden ontvangen
}
leegtelus(){
vertraging(100);
}
leegteontvangstgebeurtenis(int bytes){
Draad.schrijven("Hallo "); // reageer met bericht van 6 bytes zoals verwacht door master
}
Gegevens verzenden en ontvangen met I2C
Laten we in dit voorbeeld de temperatuur lezen van een DHT11-temperatuursensor die is gekoppeld aan de slave-Arduino en deze afdrukken op de seriële monitor van de master-Arduino.
Laten we de code die we eerder hebben geschreven aanpassen om de temperatuurmeting op te nemen die we vervolgens via de I2C-bus naar het masterboard sturen. Het hoofdbord kan dan de verzonden waarde lezen en deze vervolgens weergeven op de seriële monitor.
Master-apparaatcode:
#erbij betrekken
leegteopgericht(){
Draad.beginnen();
Serieel.beginnen(9600);
Serieel.println("Master geïnitialiseerd!");
}
leegtelus(){
Draad.aanvraag van(8, 1); // Temperatuurgegevens van slave opvragen
als (Draad.beschikbaar()) {
byte temperatuur = Draad.lezen(); // Lees temperatuurgegevens van slave
Serieel.afdrukken("Temperatuur: ");
Serieel.afdrukken(temperatuur);
Serieel.println("°C");
}
vertraging(2000); // Wacht 2 seconden voordat u opnieuw de temperatuur opvraagt
}
Slave-apparaatcode:
#erbij betrekken
#erbij betrekken#definiëren DHTPIN 4 // Pin aangesloten op DHT-sensor
#definiëren DHTTYPE DHT11 // DHT-sensortype
DHT dht(DHTPIN, DHTTYPE);
byte temperatuur;leegteopgericht(){
Draad.beginnen(8); // Slave-adres is 8
Draad.op verzoek(verzoekEvent);
dht.beginnen();
}leegtelus(){
vertraging(2000); // Wacht 2 seconden totdat DHT is gestabiliseerd
temperatuur = dht.leesTemperatuur(); // Lees de temperatuur van de DHT-sensor
}
leegterequestEvenement(){
Draad.schrijven(temperatuur); // Stuur temperatuurgegevens naar master
}
U kunt deze code aanpassen aan de sensoren die u in uw project heeft, of zelfs de sensorwaarden op een displaymodule weergeven om maak je eigen kamerthermometer en vochtigheidsmeter.
Slave-adressering met I2C op Arduino
Om waarden te lezen van componenten die in een dergelijk project aan een I2C-bus zijn toegevoegd, is het belangrijk dat u het juiste slave-adres opneemt bij het coderen. Gelukkig biedt Arduino een scannerbibliotheek die het identificeren van slaves vereenvoudigt adressen, waardoor het niet meer nodig is om lange sensorgegevensbladen te doorzoeken en verwarrend online te zijn documentatie.
Gebruik de volgende code om het adres van een slave-apparaat op de I2C-bus te identificeren.
#erbij betrekken
// Voeg de Wire-bibliotheek toe voor I2C-communicatie leegteopgericht(){
Draad.beginnen(); // Initialiseer de I2C-communicatie
Serieel.beginnen(9600); // Initialiseer de seriële communicatie met een baudrate van 9600
terwijl (!Serieel); // Wacht tot de seriële verbinding tot stand is gebracht
Serieel.println("\nI2C-scanner"); // Druk een bericht af dat het begin van I2C-scannen aangeeft
}leegtelus(){
byte fout, adres; // Declareer variabelen om fouten en apparaatadressen op te slaan
int nApparaten; // Declareer een variabele om het aantal gevonden apparaten op te slaanSerieel.println("Scannen..."); // Druk een bericht af dat het begin van I2C-scannen aangeeft
nApparaten = 0; // Stel het aantal gevonden apparaten in op 0
voor (adres = 1; adres < 127; adres++) { // Herhaal alle mogelijke I2C-adressen
Draad.beginVerzending(adres); // Start een verzending naar het huidige adres
fout = Draad.eindtransmissie(); // Beëindig de verzending en sla eventuele fouten opals (fout == 0) { // Als er geen fouten zijn gevonden
Serieel.afdrukken("I2C-apparaat gevonden op adres 0x"); // Druk een bericht af dat aangeeft dat er een apparaat is gevonden
als (adres < 16) Serieel.afdrukken("0"); // Als het adres kleiner is dan 16, voeg dan een voorloop 0 toe voor formatteringsdoeleinden
Serieel.afdrukken(adres, HEX); // Druk het adres af in hexadecimaal formaat
Serieel.println(" !"); // Druk een bericht af dat aangeeft dat er een apparaat is gevonden
nApparaten++; // Verhoog het aantal gevonden apparaten
}
andersals (fout == 4) { // Als er een fout is gevonden
Serieel.afdrukken("Onbekende fout op adres 0x"); // Druk een bericht af dat aangeeft dat er een fout is gevonden
als (adres < 16) Serieel.afdrukken("0"); // Als het adres kleiner is dan 16, voeg dan een voorloop 0 toe voor formatteringsdoeleinden
Serieel.println(adres, HEX); // Druk het adres af in hexadecimaal formaat
}
}
als (nApparaten == 0) { // Als er geen apparaten zijn gevonden
Serieel.println("Geen I2C-apparaten gevonden\n"); // Druk een bericht af dat aangeeft dat er geen apparaten zijn gevonden
}
anders { // Als er apparaten zijn gevonden
Serieel.println("klaar\n"); // Druk een bericht af dat het einde van de I2C-scan aangeeft
}
vertraging(5000); // Wacht 5 seconden voordat u de volgende scan start
}
Breid uw project vandaag nog uit
Het koppelen van twee Arduino-kaarten met behulp van het I2C-communicatieprotocol biedt een flexibele en efficiënte manier om complexe taken uit te voeren die niet door een enkel bord kunnen worden afgehandeld. Met behulp van de Wire-bibliotheek wordt de communicatie tussen de twee boards met behulp van I2C eenvoudig gemaakt, waardoor u meer componenten aan uw project kunt toevoegen.