A Circular Reference

Adventures of a vagabond electron.

I2C Wrappers for the Arduino Wire Library

| Comments

Motivation

The current (v1.6.7) Arduino Wire library doesn’t seem to have a convinent API to read/write from/to I2C devices. All the pieces are available but what’s lacking is a wrapper around Wire that makes it straight forward to talk to I2C slaves. I wrote one similar to the PIC code I’ve used in the past, and it’s posted here.

Initialization

The Wire interface can be initialized by calling begin(). The default speed is 100kbps, which can be increased by calling SetClock().

1
2
  Wire.begin();
  Wire.setClock(400000L); // Set clock to 400kbps

Read

Reading from a slave typically consists of first sending the register ID you want to read out from followed by a repeated start condition [using endTransmission(false)]. Then you set the read bit and clock out the data [via requestFrom()].

1
2
3
4
5
6
7
8
9
10
11
12
void i2c_read(byte seven_bit_address, byte reg, byte* pData, byte len ) {
  byte i = 0;
  Wire.beginTransmission(seven_bit_address);
  Wire.write(reg);
  Wire.endTransmission(false);     // send a repreated start
  Wire.requestFrom(seven_bit_address, len, true); // read N bytes and send a stop bit
  while (Wire.available() && (i < len)) // Copy the already read out data into our buffer
  {
    *pData++ = Wire.read();
    i++;
  }
}

Write

Write is self explanatory.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void i2c_write(byte seven_bit_address, byte reg, byte* pData, byte len ) {

  Wire.beginTransmission(seven_bit_address);
  Wire.write(reg);
  for (int i = 0; i < len; i++) {
    Wire.write(*pData++);
  }
  Wire.endTransmission();     // send a stop
}

// An even simpler interface to write a byte
void i2c_write(byte seven_bit_address, byte reg, byte value ) {
  Wire.beginTransmission(seven_bit_address);
  Wire.write(reg);
  Wire.write(value);
  Wire.endTransmission();     // send a stop
}

Example Usage

The code below shows how to read/write some data from/to the MAX30100 Pulse Oximetry sensor [I2C address = 0x57].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
  Serial.begin(230400);
  // Initialize
  Wire.begin();
  Wire.setClock(400000L);

  // Do stuff..

  // Read
  byte id;
  i2c_read(0x57, 0xFF, &id, 1);         // Part ID register = 0xFF
  Serial.println("Part ID:");
  Serial.print(id, HEX);                // expected value is 0x11

  // Write
  byte data;
  data = (byte)0xA << 4 | (byte)0xB;    // Set the LED config register to 0xAB
  i2c_write(0x57, 0x09, &data, 1);      // LED config register = 0x09 
// OR i2c_write(0x57, 0x09, data);

  // Read back and check
  i2c_read(0x57, 0x09, &data, 1);
  Serial.println("LED Config = ");
  Serial.print(data, HEX);

Comments