A lot of sensors, displays, and devices can connect over I2C. I2C is a 2-wire 'bus' that allows multiple devices to all connect on one set of pins so it's very convenient for wiring!
When using your board, you'll probably want to connect up I2C devices, and it can be a little tricky the first time. The best way to debug I2C is go through a checklist and then perform an I2C scan
Common I2C Connectivity Issues
- Have you connected four wires (at a minimum) for each I2C device? Power the device with whatever is the logic level of your microcontroller board (probably 3.3V), then a ground wire, and a SCL clock wire, and and a SDA data wire.
- If you're using a STEMMA QT board - check if the power LED is lit. It's usually a green LED to the left side of the board.
- Does the STEMMA QT/I2C port have switchable power or pullups? To reduce power, some boards have the ability to cut power to I2C devices or the pullup resistors. Check the documentation if you have to do something special to turn on the power or pullups.
- If you are using a DIY I2C device, do you have pullup resistors? Many boards do not have pullup resistors built in and they are required! We suggest any common 2.2K to 10K resistors. You'll need two: one each connects from SDA to positive power, and SCL to positive power. Again, positive power (a.k.a VCC, VDD or V+) is often 3.3V
- Do you have an address collision? You can only have one board per address. So you cannot, say, connect two AHT20's to one I2C port because they have the same address and will interfere. Check the sensor or documentation for the address. Sometimes there are ways to adjust the address.
- Does your board have multiple I2C ports? Historically, boards only came with one. But nowadays you can have two or even three! This can help solve the "hey, but what if I want two devices with the same address" problem: just put one on each bus.
- Are you hot-plugging devices? I2C does not support dynamic re-connection, you cannot connect and disconnect sensors as you please. They should all be connected on boot and not change. (Only exception is if you're using a hot-plug assistant but that'll cost you).
- Are you keeping the total bus length reasonable? I2C was designed for maybe 6" max length. We like to push that with plug-n-play cables, but really please keep them as short as possible! (Only exception is if you're using an active bus extender).
The Feather ESP32-S3 only has one I2C port, Wire
, that is on pins SDA and SCL and shared with the STEMMA QT connector.
It does have a built in battery monitor that is listening on address 0x0B
, so that address cannot be used by other devices.
Perform an I2C scan!
Install TestBed Library
To scan I2C, the Adafruit TestBed library is used. This library and example just makes the scan a little easier to run because it takes care of some of the basics. You will need to add support by installing the library. Good news: it is very easy to do it. Go to the Arduino Library Manager.
Search for TestBed and install the Adafruit TestBed library
Now open up the I2C Scan example
// SPDX-FileCopyrightText: 2023 Carter Nelson for Adafruit Industries // // SPDX-License-Identifier: MIT // -------------------------------------- // i2c_scanner // // Modified from https://playground.arduino.cc/Main/I2cScanner/ // -------------------------------------- #include <Wire.h> // Set I2C bus to use: Wire, Wire1, etc. #define WIRE Wire void setup() { WIRE.begin(); Serial.begin(9600); while (!Serial) delay(10); Serial.println("\nI2C Scanner"); } void loop() { byte error, address; int nDevices; Serial.println("Scanning..."); nDevices = 0; for(address = 1; address < 127; address++ ) { // The i2c_scanner uses the return value of // the Write.endTransmisstion to see if // a device did acknowledge to the address. WIRE.beginTransmission(address); error = WIRE.endTransmission(); if (error == 0) { Serial.print("I2C device found at address 0x"); if (address<16) Serial.print("0"); Serial.print(address,HEX); Serial.println(" !"); nDevices++; } else if (error==4) { Serial.print("Unknown error at address 0x"); if (address<16) Serial.print("0"); Serial.println(address,HEX); } } if (nDevices == 0) Serial.println("No I2C devices found\n"); else Serial.println("done\n"); delay(5000); // wait 5 seconds for next scan }
Wire up I2C device
While the examples here will be using the Adafruit MCP9808, a high accuracy temperature sensor, the overall process is the same for just about any I2C sensor or device.
The first thing you'll want to do is get the sensor connected so your board has I2C to talk to.
Wiring the MCP9808
The MCP9808 comes with a STEMMA QT connector, which makes wiring it up quite simple and solder-free.
Now upload the scanning sketch to your microcontroller and open the serial port to see the output. You should see something like this:
Since there is only one port, you should not see a 'secondary' I2C scan. The primary scan shows the built in battery monitoring chip on 0xB and also the special 'all call' address on 0x00 (the battery monitoring chip listens there as well) and finally the MCP9808 on 0x18.
Text editor powered by tinymce.