I2C-communicatie met microcontrollers

Wat is I2C?

I2C (Inter-Integrated Circuit) is een populair seriëel communicatieprotocol dat wordt gebruikt om verschillende apparaten, zoals sensoren, displays en microcontrollers, met elkaar te laten communiceren. Het is een eenvoudig en efficiënt protocol dat ideaal is voor communicatie tussen apparaten die zich in dezelfde printplaat bevinden of zich dicht bij elkaar bevinden. In dit artikel zullen we een stapsgewijze gids geven over hoe I2C werkt en hoe je het kunt gebruiken met populaire microcontrollers zoals Arduino, Raspberry Pi en ESP8266/ESP32.

Hoe werkt I2C?

Arduino I2C pins

I2C maakt gebruik van slechts twee signaallijnen: SDA (Serial Data) en SCL (Serial Clock). SDA wordt gebruikt voor het verzenden en ontvangen van gegevens tussen apparaten, terwijl SCL wordt gebruikt om de timing van de gegevensoverdracht te regelen.
Elk I2C-apparaat heeft een uniek adres waarmee het kan worden geïdentificeerd en aangesproken door andere apparaten op de bus.

I2C met Arduino of ESP

Om I2C met Arduino of ESP32/ESP8266 te gebruiken, moet je ervoor zorgen dat je hij is uitgerust met een I2C-interface. De meeste Arduino- en ESP-boards hebben hiervoor specifieke pinnen. Voor I2C-communicatie kun je de 'Wire' bibliotheek gebruiken, die standaard is ingebouwd in de Arduino IDE.

Voorbeeld met een I2C BMP280 sensor op een Arduino

Om de BMP280-sensor op een Arduino aan te sluiten, heb je twee I2C-pinnen nodig: SDA (Serial Data) en SCL (Serial Clock). Deze pinnen zijn meestal gemarkeerd op je Arduino-board. Vervolgens moet je de BMP280-sensor aansluiten volgens het volgende schema:

BMP280 VCC --> Arduino 5V (of 3.3V, afhankelijk van de sensor)
BMP280 GND --> Arduino GND
BMP280 SDA --> Arduino SDA (A4 op de meeste Arduino-boards)
BMP280 SCL --> Arduino SCL (A5 op de meeste Arduino-boards) 

Om de BMP280-sensor uit te lezen, moeten we de "Adafruit_BMP280" bibliotheek gebruiken. Als je deze bibliotheek nog niet hebt geïnstalleerd, ga dan naar "Sketch" -> "Include Library" -> "Manage Libraries" in de Arduino IDE en zoek naar "Adafruit BMP280 Library" om deze te installeren.

Onderstaande sketch leest de BMP280-sensor (op I2C-adres 0x76) uit en print elke seconde de temperatuur en luchtdruk:

#include <Wire.h> 
#include <Adafruit_Sensor.h>
#include <Adafruit_BMP280.h>

Adafruit_BMP280 bmp;

void setup() {
  Serial.begin(115200);
  if (!bmp.begin(0x76)) {
    Serial.println("BMP280 not found!");
    while (1);
  }
}

void loop() {
  float temperature = bmp.readTemperature();
  float pressure = bmp.readPressure() / 100.0;

  Serial.print("Temperature: ");
  Serial.print(temperature);
  Serial.println(" °C");

  Serial.print("Pressure: ");
  Serial.print(pressure);
  Serial.println(" hPa");

  delay(1000);
}

Meerdere I2C-devices tegelijk aansluiten

I2C Master-Slave example

Eén van de grootste voordelen van I2C is dat je meerdere I2C-devices op dezelfde bus kunt aansluiten. Elk I2C-device heeft een uniek adres, waardoor het mogelijk is om ze afzonderlijk aan te spreken. De meeste I2C-devices hebben hun eigen vaste adres, maar sommige kunnen worden geconfigureerd om verschillende adressen te hebben.

Om meerdere I2C-devices aan te sluiten, verbind je gewoon de SDA- en SCL-pinnen van elk device met dezelfde SDA- en SCL-pinnen van de Arduino of ESP. Zorg ervoor dat elk device een uniek adres heeft. De microcontroller (Arduino, Raspberry Pi of ESP) is in dit geval de I2C master. De andere devices op de I2C-bus worden slaves genoemd (zie afbeelding).

De signaallijnen SDA en SCL moeten voorzien zijn van pull-up weerstanden (van 4,7kOhm) naar VCC  (de plus van je voeding). Lees hier meer over pull-up- en pull-down-weerstanden.

Checken of alles goed is aangesloten en welke I2C-addressen je apparaten hebben

Het aansluiten van I2C-apparaten kan soms wat lastig zijn, zeker als je er meerdere tegelijk gaat gebruiken.
Met behulp van onderstaande sketch 'scan' je de hele I2C-bus en worden de addressen van aangesloten apparaten geprint. Zo weet je of alle apparaten het doen en op welk adres ze zitten.

I2C-scan sketch:

#include <Wire.h> 

void setup() {
  Serial.begin(9600);
  Serial.println();
  Serial.println("I2C scanner. Scanning ...");
  byte count = 0;
  
  Wire.begin();
  
  for( byte i = 1; i < 120; i++ )
  {
    Wire.beginTransmission (i);
    if (Wire.endTransmission () == 0)
    {
      Serial.print ("Found address: ");
      Serial.print (i, DEC);
      Serial.print (" (0x");
      Serial.print (i, HEX);
      Serial.println (")");
      count++;
    } // end of good responsea
    
    delay (5);  // give devices time to recover
	
  } // end of for loop
  
  Serial.println("Done.");
  Serial.print("Found ");
  Serial.print(count, DEC);
  Serial.println(" device(s).");
}  // end of setup

void loop() {}

Je kunt deze sketch ook downloaden.

Conclusie

I2C is een eenvoudig en efficiënt seriëel communicatieprotocol dat veel wordt gebruikt in verschillende elektronische apparaten en microcontrollers. Het biedt een gestructureerde manier om gegevens uit te wisselen tussen apparaten op een printplaat of in een nabije omgeving. Met de juiste bibliotheekondersteuning en de juiste aansluitingen kun je I2C gebruiken om je Arduino, Raspberry Pi of ESP8266/ESP32 te laten communiceren met andere I2C-compatibele apparaten en zo complexe IoT-toepassingen te bouwen.