Doorgaan naar hoofdcontent

Arduino: Interchip communicatie 2: I2C

I2C, uitgesproken als I-kwadraat-C (persoonlijk noem ik het uit gemak I-twee-C en schrijf ik vaak I2C) is een communicatiemethode tussen meerdere IC's. Het is ontwikkeld door Philips in de jaren 70, als goedkope inter-IC-bus. I2C gebruikt een bus-topologie, meerdere IC's kunnen hierop worden aangesloten. Zie ook http://nl.wikipedia.org/wiki/I2C.

De eerste stap.


Als eerste heb ik een eerdere schakeling van stal gehaald, namelijk de ATMega8/LCD-schakeling. Wat deze schakeling doet: de informatie die serieel wordt ontvangen, weergeven op het LCD-scherm.
Zie de Arduino-website voor details omtrent deze schakeling.

Deze schakeling is ook gebruikt in "Interchip communicatie 1: Seriële communicatie". De code die op de ATMega8 draait is eigenlijk gelijk aan het SerialDisplay-voorbeeld dat bij de Arduino-software wordt geleverd:

#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
void setup(){
  lcd.begin(16, 2);
  Serial.begin(9600);
}

void loop()
{
  if (Serial.available()) {
    delay(100);
    lcd.clear();
    while (Serial.available() > 0) {
      lcd.write(Serial.read());
    }
  }
}

of als de LCD zelf ook een I2C-chip heeft (er vanuitgaande dat de LCD een eigen verbinding heeft met de ATMega8):

#include <Wire.h> 
#include <LiquidCrystal_I2C.h>

// set the LCD address to 0x27 for a 16 chars and 2 line display
LiquidCrystal_I2C lcd(0x27,16,2); void setup() {   lcd.init(); // initialize the lcd   lcd.backlight();   Serial.begin(9600); } void loop() {   if (Serial.available()) {     delay(100);     lcd.clear();     while (Serial.available() > 0) {       lcd.write(Serial.read());     }   } }
(De LiquidCrystal_I2C-libary kan je hier vinden.)

De tweede stap.


Op een breadboard zet ik een schakeling op die de meeste functionaliteiten van een Arduino biedt. Zie hiervoor ook "Setting up an Arduino on a breadboard". Hiervoor heb ik een extern 16MHz kristal, een inductor en een ATMega328 gebruikt. De schakeling ziet er ongeveer uit zoals in onderstaand figuur.



Op de ATMega328 zet ik de code die geinspireerd is op het slave_receiver voorbeeld. Wat deze schakeling doet: Via I2C informatie ontvangen en deze serieel doorsturen naar de ATMega8-schakeling.

#include <Wire.h>
void setup()
{
  Wire.begin(4);                // join i2c bus with address #4
  Wire.onReceive(receiveEvent); // register event
  Serial.begin(9600);           // start serial for output
}

void loop()
{
  delay(100);
}

void receiveEvent(int howMany)
{
  while(1 < Wire.available()) // loop through all but the last
  {
    char c = Wire.read(); // receive byte as a character
    Serial.print(c);         // print the character
  }
  int x = Wire.read();    // receive byte as an integer
  Serial.println(x);         // print the integer
}

 De derde stap.

 De derde stap doe ik gewoon op de Arduino UNO. Hierop zetten we de master_writer code:

#include <Wire.h>

void setup()
{
  Wire.begin(); // join i2c bus (address optional for master)
}

byte x = 0;

void loop()
{
  Wire.beginTransmission(4); // transmit to device #4
  Wire.write(x);              // sends one byte  
  Wire.endTransmission();    // stop transmitting

  x++;
  delay(500);
}

De Arduino wordt aangelosten op de I2C-bus met poorten A4(SCK) en A5(SDA). De Arduino stuurt nu getallen over de I2C-bus naar de I2C-slave. Deze stuurt ze door middel van seriële communicatie naar de ATMega8, die ze vervolgens weergeeft op het LCD-scherm.

Uitbreiden


Omdat de I2C een bustopologie gebruikt, kunnen meerdere schakelingen aan de bus worden toegevoegd. Zo is het denkbaar om met een vierde schakeling te maken en ook deze te laten reageren op informatie van de I2C-master. Voorbeelden kunnen zijn:
  • een ATMega-schakeling met een sketch o.b.v de Wire-library
  • een ATTiny-schakeling met een sketch o.b.v. de TinyWire-library
  • een PCF8575 of MCP23016 I2C-pin expander met daarachter weer andere mogelijkheden