Software/Arduino Core/Basics

I2C with Wire

The Wire object, the shared I2C1 sensor bus, the on-board device addresses, and the bus locking functions.

beginner2 min read

Wire is the standard Arduino I2C master. Third-party sensor libraries that use Wire.beginTransmission, Wire.write, Wire.endTransmission, Wire.requestFrom and Wire.read work without modification.

cpp
#include <Wire.h>

void setup() {
  Serial.begin(115200);
  Wire.begin();
}

void loop() {
  int found = 0;
  for (byte address = 1; address < 127; address++) {
    Wire.beginTransmission(address);
    if (Wire.endTransmission() == 0) {
      Serial.print("  device at 0x");
      Serial.println(address, HEX);
      found++;
    }
  }
  if (found == 0) Serial.println("  no devices found");
  delay(5000);
}

This is the WireScanner example. The IMU and magnetometer on the Neuro N6 respond on every board; the camera responds when a module is fitted, and the time of flight sensor on the OV5640, TFT and STCam modules.

The bus

Wire drives the sensor bus, which the core's HAL handle names hi2c1. The IMU and magnetometer on the Neuro N6, the camera control interface, the time of flight sensor on the OV5640, TFT and STCam modules, the touch controller on the TFT carriers and the thermal camera's command interface share it. Any external device on this bus must use a free address.

The board has two I2C interfaces: one on the Feather header SDA and SCL pins (PD15 and PD14, 3.3 V, with pull-ups) and one on the 40-pin board-to-board connector to the camera module. A device on the header pins is verified with the WireScanner example before use.

Device7-bit address
OV5640 camera0x3C
VD66GY camera0x10
LSM6DSL IMU0x6A or 0x6B
MMC5603NJ magnetometer0x30
VL53L1CB time of flight0x29
GT911 touch controller0x5D or 0x14
FLIR Lepton0x2A

Addresses are 7-bit, following the Arduino convention.

Implementation

  • Master mode only.
  • Wire.begin() has no effect; the core initialises the bus before setup().
  • Wire.setClock() has no effect. The bus runs at a fixed timing suitable for all on-board devices.
  • The transaction buffer is 32 bytes, matching Arduino's BUFFER_LENGTH.
  • endTransmission() returns the standard codes: 0 on success, non-zero on NACK or timeout.

Bus sharing

The camera driver, the sensor libraries and the core's diagnostics all use I2C1, some from other FreeRTOS tasks. Every user brackets each transaction with a recursive mutex, so transactions from different tasks cannot interleave. Wire and the bundled libraries take the mutex internally.

Three lower-level functions, provided by Arduino.h, cover cases where per-transaction locking is insufficient.

Locking a transaction

n6_i2c_lock() and n6_i2c_unlock() are the functions Wire uses. They are needed only when calling the HAL directly:

cpp
n6_i2c_lock();
HAL_StatusTypeDef st = HAL_I2C_IsDeviceReady(&hi2c1, addr << 1, 2, 5);
n6_i2c_unlock();

Claiming the bus for a period

Some devices require the bus to be silent, not merely ordered. The FLIR Lepton fails if it observes traffic to other addresses during its boot window. n6_i2c_claim() blocks every other user until n6_i2c_release():

cpp
n6_i2c_claim();
thermal.powerOn();
delay(2500);
n6_i2c_release();

Claim and release must be called from the same task, and the claimed period must be bounded, since other users wait indefinitely.

Non-blocking acquisition

n6_i2c_trylock() returns 1 if the bus was acquired and 0 if it was busy, without waiting. A periodic publisher uses it to skip a reading rather than stall:

cpp
if (n6_i2c_trylock()) {
  imu.sendNS();
  mag.sendNS();
  n6_i2c_unlock();
}

Bundled sensor libraries

Each on-board sensor library follows the same pattern: declare an object, call begin(), read, and optionally call sendNS() to stream the reading to Neuro Studio. The libraries do not block: reads are bounded and return a sentinel value on failure. See On-board Sensors.

Address conflicts

A device whose address conflicts with an on-board part is normally reconfigured through its address select pin, or driven by a software I2C library on two spare digital pins.