I2C (Inter-Integrated Circuit, aka IIC, Speak: Eye-Squared-See) is a synchronous bus system invented 1982 by Philips that can transfer data with speeds in the range of 100-400 kBit/s while requiring just two wires, similar to classic serial interfaces. Today, it is widely used to connect peripherals like displays or sensors to microcontrollers inside devices.
Components requiring higher data rates (such as color displays) typically use SPI.
Quick Overview
I2C is a two-wire bus that is used to inter-connect components, typically inside a device and over a short distance.
I2C GPIOs
With I2C, there are two pins that need to be connected to your microcontroller:
Pin Label | Alternate Labels | Description |
---|---|---|
SDA | DATA, SDI | Serial Data (data and target address) |
SCL | CLK, SCLK, | Serial Clock (synchronization) |
If your microcontroller supports hardware GPIOs for I2C, it’s best to use these pins. They typically offer better performance by supporting higher speeds while reducing the processing burden on the microcontroller.
When using freely assignable software GPIOs, you can assign any available GPIO pin that supports reading and writing. However, using hardware pins is generally recommended for optimal performance.
Default I2C Hardware GPIOs for Popular DIY Microcontrollers
Here are the GPIOs typically used for hardware I2C across some of the popular DIY microcontrollers.
The development board you are using may use different GPIOs. Modern ESP32 family members such as ESP32-C3 or ESP32-S3 can route any GPIO to its hardware I2C controllers, and development board designers may have designated arbitrary GPIOs.
Microcontroller | SDA Pin | SCL Pin | Pin Reassignment Allowed? |
---|---|---|---|
Arduino Uno R3 | A4 | A5 | No |
Arduino Uno Mini LE | A4 | A5 | No |
Arduino Uno R4 | A4 | A5 | No |
Arduino Uno WiFi | 20 | 21 | No |
Arduino Leonardo | D2 | D3 | No |
Arduino Nano | A4 | A5 | No |
Arduino MKR | D11 | D12 | No |
Arduino Giga R1 | 20 | 21 | No |
Arduino Due | 20 | 21 | No |
Arduino Mega 2560 | 20 | 21 | No |
ESP8266 | 4/D2 | 5/D1 | Yes |
ESP8266-01 | 0/D5 | GPIO2/D3 | Yes |
ESP32 | 21 | 22 | Yes |
ESP32-S2 | 8 | 9 | Yes |
ESP32-S3 | 8 | 9 | Yes |
ESP32-C3 | 5 | 4 | Yes |
Teensy | varies | varies | Yes |
STM32 (Blue Pill) | PB9 | PB8 | Yes |
Digispark (ATTiny85) | PB0/pin 5 | PB2/pin 7 | No |
When you are using a microcontroller that supports I2C pin reassignments, make sure you use a freely available GPIO that can read and write and has a built-in pull-up resistor.
Well-Known I2C Addresses
Before you can access a I2C device, you need to know its specific I2C address. I2C devices typically use a fixed address. Some devices allow you to select an address, i.e. via a series of solder bridges.
If you do not know your devices’ I2C address, start with a well-known standard address for the particular device class. If it is for example a monochrome OLED display, use 0x3c
, and if this does not work, try 0x3d
.
If that does not work, or you do not know the well-known I2C address for your device class, look up the address in a list:
List of well-known I2C addresses
I2C Address | Device Type |
---|---|
0x0c | AK8975 |
0x0d | AK8975 |
0x0e | AK8975, IST-8310, MAG3110 |
0x0f | AK8975 |
0x10 | LM25066, VEML6075, VEML7700, VML6075 |
0x11 | LC709203F, LM25066, SAA5243P/E, SAA5243P/H, SAA5243P/K, SAA5243P/L, SAA5246, Si4713 |
0x12 | LM25066, PMSA003I, SEN-17374 |
0x13 | LM25066, SEN-17374, VCNL40x0 |
0x14 | LM25066 |
0x15 | LM25066 |
0x16 | LM25066 |
0x17 | LM25066 |
0x18 | 47L04/47C04/47L16/47C16, COM-15093, LIS3DH, LSM303, MCP9808 |
0x19 | COM-15093, LIS3DH, LSM303, MCP9808 |
0x1a | 47L04/47C04/47L16/47C16, MCP9808 |
0x1b | MCP9808 |
0x1c | 47L04/47C04/47L16/47C16, FXOS8700, MCP9808, MMA845x, SAA7706H |
0x1d | ADXL345, FXOS8700, MCP9808, MMA845x |
0x1e | 47L04/47C04/47L16/47C16, FXOS8700, HMC5883, LSM303, LSM303, MCP9808 |
0x1f | FXOS8700, MCP9808 |
0x20 | Chirp!, FXAS21002, HW-061, MA12070P, MCP23008, MCP23017, PCA6408A, PCF8574, PCF8575, TCA9554, XD8574A |
0x21 | FXAS21002, HW-061, MA12070P, MCP23008, MCP23017, PCA6408A, PCF8574, PCF8575, SAA4700, TCA9554, XD8574A |
0x22 | HW-061, MA12070P, MCP23008, MCP23017, PCA1070, PCF8574, PCF8575, TCA9554, XD8574A |
0x23 | BH1750FVI, HW-061, MA12070P, MCP23008, MCP23017, PCF8574, PCF8575, SAA4700, TCA9554, XD8574A |
0x24 | HW-061, MCP23008, MCP23017, PCD3311C, PCD3312C, PCF8574, PCF8575, TCA9554, XD8574A |
0x25 | HW-061, MCP23008, MCP23017, PCD3311C, PCD3312C, PCF8574, PCF8575, TCA9554, XD8574A |
0x26 | HW-061, MCP23008, MCP23017, PCF8574, PCF8575, TCA9554, XD8574A |
0x27 | HIH6130, HW-061, MCP23008, MCP23017, PCF8574, PCF8575, TCA9554, XD8574A |
0x28 | BNO055, CAP1188, DS1841, DS1881, DS3502, FS3000, MCP4532, PM2008 |
0x29 | BNO055, CAP1188, DS1841, DS1881, DS3502, MCP4532, TCS34725, TSL2591, VL53L0x, VL6180X |
0x2a | CAP1188, DS1841, DS1881, DS3502, MCP4532 |
0x2b | CAP1188, DS1841, DS1881, DS3502, MCP4532 |
0x2c | AD5248, AD5251, AD5252, CAP1188, CAT5171, DS1881, MCP4532 |
0x2d | AD5248, AD5251, AD5252, CAP1188, CAT5171, DS1881, MCP4532, ST25DV16K |
0x2e | AD5248, AD5251, AD5252, DS1881, LPS22HB, MCP4532 |
0x2f | AD5243, AD5248, AD5251, AD5252, DS1881, MCP4532 |
0x30 | SAA2502 |
0x31 | SAA2502 |
0x32 | ZMOD4410, ZMOD4450 |
0x33 | MLX90640, ZMOD4510 |
0x36 | MAX17048, MAX17048 |
0x38 | AHT10, AHT20, BMA150, FT6x06, PCF8574AP, RRH46410, SAA1064, SEN-15892, VEML6070 |
0x39 | APDS-9960, PCF8574AP, SAA1064, TSL2561, VEML6070 |
0x3a | MLX90632, PCF8574AP, PCF8577C, SAA1064 |
0x3b | PCF8569, PCF8574AP, SAA1064 |
0x3c | PCF8569, PCF8574AP, PCF8578, SH1106, SSD1305, SSD1306 |
0x3d | PCF8574AP, PCF8578, SH1106, SSD1305, SSD1306 |
0x3e | BU9796, PCF8574AP |
0x3f | PCF8574AP |
0x40 | HDC1080, HTU21D-F, HTU31D, INA219, INA260, LM25066, NE5751, PCA9685, PCF8574, Si7021, TDA8421, TDA9860, TEA6300, TEA6320, TEA6330, TMP006, TMP007 |
0x41 | HTU31D, INA219, INA260, LM25066, NE5751, PCA9536, PCA9685, PCF8574, STMPE610, STMPE811, TDA8421, TDA8424, TDA8425, TDA8426, TDA9860, TMP006, TMP007 |
0x42 | HDC1008, INA219, INA260, LM25066, PCA9685, PCF8574, TDA8415, TDA8417, TMP006, TMP007 |
0x43 | HDC1008, INA219, INA260, LM25066, PCA9685, PCF8574, TMP006, TMP007 |
0x44 | HS30xx, INA219, INA260, ISL29125, LM25066, PCA9685, PCF8574, SHT31, STMPE610, STMPE811, TDA4670, TDA4671, TDA4672, TDA4680, TDA4687, TDA4688, TDA4780, TDA8442, TMP006, TMP007 |
0x45 | INA219, INA260, LM25066, PCA9685, PCF8574, SHT31, TDA7433, TDA8376, TMP006, TMP007 |
0x46 | INA219, INA260, LM25066, PCA9685, PCF8574, TDA8370, TDA9150, TMP006, TMP007 |
0x47 | INA219, INA260, LM25066, PCA9685, PCF8574, TMP006, TMP007 |
0x48 | ADS1015, ADS1115, ADS7828, INA219, INA260, LM75b, PCA9685, PCF8574, PN532, STDS75, TMP102 |
0x49 | ADS1015, ADS1115, ADS7828, AS7262, INA219, INA260, LM75b, PCA9685, PCF8574, STDS75, TMP102, TSL2561 |
0x4a | ADS1015, ADS1115, ADS7828, CS43L22, INA219, INA260, LM75b, MAX44009, PCA9685, PCF8574, STDS75, TMP102 |
0x4b | ADS1015, ADS1115, ADS7828, INA219, INA260, LM75b, MAX44009, PCA9685, PCF8574, STDS75, TMP102 |
0x4c | EMC2101, INA219, INA260, LM75b, PCA9685, PCF8574, STDS75 |
0x4d | INA219, INA260, LM75b, PCA9685, PCF8574, STDS75 |
0x4e | INA219, INA260, LM75b, PCA9685, PCF8574, STDS75 |
0x4f | INA219, INA260, LM75b, PCA9685, PCF8574, STDS75 |
0x50 | 47L04/47C04/47L16/47C16, AT24C02N, AT24C64, CAT24C512, FS1015, LM25066, MB85RC, PCA9685 |
0x51 | AT24C02N, AT24C64, CAT24C512, LM25066, MB85RC, PCA9685, PCF8563, VCNL4200 |
0x52 | 47L04/47C04/47L16/47C16, APDS-9250, AT24C02N, AT24C64, CAT24C512, controller, LM25066, MB85RC, Nunchuck, PCA9685, SI1133 |
0x53 | ADXL345, AT24C02N, AT24C64, CAT24C512, LM25066, MB85RC, PCA9685, ST25DV16K |
0x54 | 47L04/47C04/47L16/47C16, AT24C02N, AT24C64, CAT24C512, HS40xx, LM25066, MB85RC, PCA9685 |
0x55 | AT24C02N, AT24C64, CAT24C512, D7S, LM25066, MAX30101, MB85RC, PCA9685, SI1133 |
0x56 | 47L04/47C04/47L16/47C16, AT24C02N, AT24C64, CAT24C512, LM25066, MB85RC, PCA9685 |
0x57 | AT24C02N, AT24C64, CAT24C512, LM25066, MAX3010x, MB85RC, PCA9685, ST25DV16K |
0x58 | LM25066, PCA9685, SGP30, TPA2016 |
0x59 | LM25066, PCA9685, SGP40 |
0x5a | CCS811, CCS811, DRV2605, LM25066, MLX90614, MPR121, PCA9685 |
0x5b | CCS811, CCS811, MPR121, PCA9685 |
0x5c | AM2315, AM2320, BH1750FVI, MPR121, PCA9685 |
0x5d | MPR121, PCA9685, SFA30 |
0x5e | PCA9685 |
0x5f | HTS221, PCA9685 |
0x60 | ATECC508A, ATECC608A, MCP4725A0, MCP4725A1, MCP4728, MPL115A2, MPL3115A2, PCA9685, SAB3035, SAB3037, SI1132, Si1145, Si5351A, TEA5767, TSA5511 |
0x61 | MCP4725A0, MCP4725A1, MCP4728, PCA9685, SAB3035, SAB3037, SCD30, Si5351A, TEA6100, TSA5511 |
0x62 | MCP4725A1, MCP4728, PCA9685, SAB3035, SAB3037, SCD40, SCD40-D-R2, SCD41, TSA5511, UMA1014T |
0x63 | MCP4725A1, MCP4728, PCA9685, SAB3035, SAB3037, Si4713, TSA5511, UMA1014T |
0x64 | MCP4725A1, MCP4725A2, MCP4728, PCA9685 |
0x65 | MCP4725A1, MCP4725A2, MCP4728, PCA9685 |
0x66 | IS31FL3731, LTC4151, MCP4725A1, MCP4725A3, MCP4728, PCA9685 |
0x67 | LTC4151, MCP4725A1, MCP4725A3, MCP4728, PCA9685 |
0x68 | AMG8833, BQ32000, DS1307, DS1371, DS3231, ICM-20948, ITG3200, LTC4151, MCP3422, MPU6050, MPU-9250, MPU-9250, PCA9685, PCF8523, PCF8573, WITTY-PI-3 |
0x69 | 3, AMG8833, ICM-20948, ITG3200, LTC4151, MAX31341, MPU6050, MPU-9250, PCA9685, PCF8573, PI, RRH62000, SPS30, WITTY |
0x6a | L3GD20H, LTC4151, PCA9685, PCF8573 |
0x6b | L3GD20H, LTC4151, PCA9685, PCF8573 |
0x6c | LTC4151, PCA9685 |
0x6d | LTC4151, PCA9685 |
0x6e | LTC4151, PCA9685 |
0x6f | LTC4151, MCP7940N, PCA9685 |
0x70 | HT16K33, PCA9541, PCA9685, SHTC3, TCA9548, TCA9548A, XD8574 |
0x71 | HT16K33, PCA9541, PCA9685, TCA9548, TCA9548A, XD8574 |
0x72 | HT16K33, PCA9541, PCA9685, TCA9548, TCA9548A, XD8574 |
0x73 | HT16K33, PCA9541, PCA9685, TCA9548, TCA9548A, XD8574 |
0x74 | HT16K33, PCA9539, PCA9541, PCA9685, TCA9548, TCA9548A, XD8574 |
0x75 | HT16K33, PCA9539, PCA9541, PCA9685, TCA9548, TCA9548A, XD8574 |
0x76 | BME280, BME680, BME688, BMP280, HT16K33, MS5607, MS5611, PCA9539, PCA9541, PCA9685, SPL06-007, TCA9548, TCA9548A, XD8574 |
0x77 | BMA180, BME280, BME680, BME688, BMP085, BMP180, BMP280, HT16K33, IS31FL3731, MS5607, MS5611, PCA9539, PCA9541, PCA9685, SPL06-007, TCA9548, TCA9548A, XD8574 |
0x78 | PCA9685 |
0x79 | PCA9685 |
0x7a | PCA9685 |
0x7b | PCA9685 |
0x7c | PCA9685 |
0x7d | PCA9685 |
0x7e | PCA9685 |
0x7f | PCA9685 |
Here is a detailed list with clickable device types for more device information.
I2C Scanner
You can also create yourself a simple I2C Address Scanner: upload the following code to a microcontroller, then connect the unknown device to its designated I2C pins. The scanner then scans all devices connected to I2C, and lists the addresses it found:
#include <Wire.h>
// change to the GPIOs you want to use for I2C
#define SDA_PIN 21
#define SCL_PIN 22
void setup() {
Serial.begin(9600);
// Initialize I2C with custom pins
Wire.begin(SDA_PIN, SCL_PIN);
Serial.println("\nI2C Scanner");
for (byte address = 1; address < 127; address++) {
Wire.beginTransmission(address);
byte error = Wire.endTransmission();
if (error == 0) {
Serial.print("I2C device found at address 0x");
if (address < 16) {
Serial.print("0");
}
Serial.println(address, HEX);
}
}
}
void loop() {
// Nothing to do here
}
If you are using ESPHome, you can use this configuration to achieve the same:
i2c:
sda: GPIO21
scl: GPIO22
scan: True
The Roots: Serial
To understand how I2C works and what its requirements are, let’s look at where it came from: in some respect, it is a modernized serial interface.
The most basic ubiquous interface in computing is the two-wire serial interface that many users know:
Pin | Description |
---|---|
TX | transmits raw data at defined speed and is connected to RX on the other side |
RX | receives raw data at defined speed and is connected to TX on the other side |
The serial interface has severe limitations that make it impractical to connect peripherals in modern devices:
- 1:1 Connection: it uses a cross-over design and can connect exactly two devices. While it is ok to use the serial interface with one peripheral, you would need distinct serial interfaces for each peripheral you want to connect.
- Asynchronous: the serial interface has no clock signal, so both parties must agree on a given data transfer speed, the dreaded baud rate. Synchronization is performed on each device independently, so both devices must have a stable clock to not drift away and misinterpret data. This entire concept requires either a hardware UART unit, or it is implemented in software and adds significant overhead to the microcontroller.
- Slow: because of the overhead, serial interfaces are typically limited to a maximum baud rate of 230,400 bps (28,800 bytes/s).
The serial interface is fairly old which explains some of its design implementations: it stems from a time where signal processing was expensive. That’s why serial uses separated data lines for receiving and transmitting which is highly inefficient since most of the time, data transmissions are unidirectional.
With the advent of modern microcontrollers and highly integrated chips, focus could shift from simplistic hardware to sophisticated data protocols, meaning the data carries some of the information that previously was organized by the wires, i.e. read and write operations.
I2C Modernizes Serial
I2C has the same hardware requirements for the connections, requiring just two wires (and two GPIOs):
Pin | Description |
---|---|
SDA | Serial Data (data packages with payload and overhead information, i.e. the target address) |
SCL | Serial Clock (synchronizes the data speed) |
However, it more efficiently uses just one wire for bi-directional data transfer, and uses the other wire for a dynamic clock signal. This way, the data transfer speed can be synchronized, and I2C is no longer limited to a pure 1:1 communication. Instead, it is a bus system which can improve many limitations found in serial:
- Multiple Peripherals: I2C can address up to 112 peripherals (clients)
- Multiple Controllers: it supports multiple controllers (masters)
- Fast: it is much faster than serial with communication rates in the range of 100-400 kHz. There are also ultra-fast modes up to 5 MHz that require higher-quality wiring. , and since it is designed as a bus system, it allows multiple controllers within this bus.
- Simpler: amazingly, I2C is much simpler to implement than serial and can be easily implemented in software
Since I2C uses cost-effective normal wires without shielding, it is susceptible to noise and can only be used reliably for short distances within a device. Its high impedance requires a common ground all devices participating in the bus system.
Clock
A dedicated clock line synchronizes data between the different parties. Communication speed can be negotiated and does not have to be set as a prerequisite (like the baud rate in serial). Also, any participating device can use the clock to introduce delays, i.e. when it is not yet done processing information.
The clock signal is generated by the (current) bus controller. Slower peripherals can force the clock low in order to signal to the controller that they are not yet ready to receive more data. This is called clock stretching.
Open Drain
Since I2C is designed to allow many peripherals and controllers to access the bus simultaneously, precautions are necessary to prevent short circuits. Without these safeguards, if one device pulls the bus low while another pulls it high, harmful currents could flow.
This is why I2C uses an open-drain configuration for both lines, meaning that each participant can actively pull the lines low, but cannot pull them high. Instead, the line is kept high by default through a pull-up resistor (typically 4.7kΩ).
Both SDA and SCL need a pull-up resistor.
The resistor value can be adjusted depending on factors like the bus length and the number of devices. For longer cables or higher speeds, you might need to lower the resistance (e.g., 2.2kΩ), while shorter cables may work with higher resistance values.
Pull-Up Resistor
Issues can arise if a line either has no pull-up resistor or too many:
- No Pull-Up Resistor: If no pull-up resistor is used, the line will be left floating, causing I2C communication to fail. This is why many I2C peripherals come with pull-up resistors already built in.
- Too Many Pull-Up Resistors: When using I2C peripherals that include built-in pull-up resistors, their combined resistance may be too low. If the resistance becomes too low, I2C communication may fail, and you may experience issues such as excessive current draw.
As a general rule, once you connect more than six I2C peripherals with built-in pull-up resistors, the combined resistance may be too low for reliable communication. In most DIY projects, exceeding this number is uncommon.
If you need to use more than six peripherals on a single I2C bus, it’s important to test each device. Some peripherals with built-in pull-up resistors allow you to disable the internal pull-ups, while others may require manual intervention, such as cutting a trace on the PCB.
I2C Address
I2C uses a 7-bit address to uniquely identify individual devices. The address range is from 0x00
to 0x7F
(or 0
to 127
in decimal).
In theory, this provides 128 unique device addresses, but some addresses are reserved for special purposes. For example, addresses like 0x00
(the general call address) and 0x7F
(reserved for future use) cannot be assigned to devices. This typically leaves 112 usable addresses for devices.
The 8th bit in the address is the Read/Write (R/W) bit, which indicates whether the master intends to read from (1
) or write to (0
) the slave device.
The maximum number of devices on an I2C bus is also limited by bus capacitance, which should not exceed 400 pF. This limit is influenced by factors such as the physical wiring and the number of connected devices.
Confusing Address Notations
There can be confusion regarding I2C device addresses. For example, simple OLED displays are often configured with the address 0x3C
by default. However, in some cases, the same address may be specified as 0x78
, leading to uncertainty about which one to use.
In most source codes, the 7-bit address is used, which in this example is 0x3C
. When I2C transmits the address in its address frame, the 7-bit address is shifted by one bit to fit into an 8-bit frame in most significant bit (MSB) order. This results in the 8-bit value 0x78
.
Thus, while I2C internally sends the 8-bit value (i.e., 0x78
) over the wire, software (and your source code) should use the original 7-bit address (i.e., 0x3C
).
Aside from this, the address can be specified in different formats. Address 0x3C
, for example, would be 60
in decimal notation and 00111100
in binary format.
Protocol
Most of the I2C features are defined by its protocol, which is the sequence of data exchanged between devices. Each message is divided into two frame types:
- Address Frame: This frame targets the recipient by its unique I2C address and indicates whether the operation is a read or write request. A read operation requests information from a peripheral, while a write operation sends instructions to the peripheral.
- Data Frame: This frame contains 8 bits of data. Multiple data frames can be sent, but they are always initiated by an address frame.
The sender pulls SCL low, then places the frames on the SDA line. Once the frames are sent, SCL is released and pulled high automatically by the pull-up resistor. This is one of the protocol’s key features: the recipient can also pull SCL low, indicating that it needs more time to process the data. This prevents the controller from overwhelming a slower peripheral.
Preventing Collisions
Since I2C allows multiple controllers to communicate with multiple peripherals, a smart protocol is used to manage data transmission and prevent collisions:
- Is Bus Available? The SCL signal tells all participants whether the bus is in use. When the bus is free, SCL is high (no device is actively pulling it low, so the pull-up resistor pulls it high).
- Taking Ownership: When a controller wants to send data, it actively pulls SDA low. This signals all peripheral devices that a transmission is about to start. The device that pulls SDA low first takes control of the bus.
- Targeting Device: The device that gains control begins communication by pulling SCL low. It then places the address frame on SDA in MSB format (most significant bit first).
- Establishing Connection: After sending the address frame, the controller releases SDA to high and expects the recipient to pull SDA low before the 9th clock cycle to acknowledge the transmission.
- Sending Data: Once communication is established, the controller continues to generate clock pulses. Depending on whether the address frame indicated a read or write operation, the peripheral or controller sends one or more data frames that are picked up by the counterpart.
- Releasing Ownership: After all data frames are transferred, the controller generates a stop signal. During normal data writing, SDA should never change while SCL is high. The stop signal first releases SCL (which goes high), then releases SDA (which also goes high).
Voltage
While I2C is somewhat resilient to differing signal voltages, it is always safer to use a logic level shifter when connecting devices with different voltage levels. For instance, when using a 5V microcontroller board with 3.3V sensor peripherals, it’s advisable to add a level shifter to ensure reliable communication.
Ensure you use a fast level shifter that supports I2C. Basic level shifters may not respond quickly enough to the high signal frequencies used by I2C, which could cause communication issues.
Limitations and Workarounds
Below are some of the most common I2C limitations and challenges, along with their corresponding workarounds.
Issue #1: Fixed Hardware Addresses
Each I2C peripheral is identified by a unique address:
- Device Class: The simplest approach for many devices in a given class is for them to use the same predefined address. For example, most monochrome OLED displays use the address 0x3C (0x78 in 8-bit) or 0x3D (0x7A in 8-bit), meaning only one such device can be used on the bus at a time.
- Jumper: Some breakout boards feature solder pads that allow you to change the address. Typically, such devices can be configured to use 4-8 different I2C addresses, allowing multiple devices of the same class to be used on the same bus as long as each is configured with a unique address.
Workaround
If you need to use multiple peripherals that share the same I2C address, consider using an I2C Multiplexer, such as the TCA9548A. A multiplexer can switch between devices, allowing communication with each one individually.
Issue #2: Unreliable Communication
I2C communication is usually very reliable unless there are hardware issues:
- Pull-Up Resistor: The bus requires pull-up resistors. If you have no or too many pull-up resistors, I2C communication may fail.
- Distance: I2C is designed for short-range communication within devices, and the optimal distance for reliable operation is typically less than 20 cm. With longer distances, I2C may experience noise interference and weak signals.
Workarounds
Ensure that the total pull-up resistance on your I2C bus is correct. If you’re using more than six peripherals, check if any have built-in pull-up resistors and remove or disable them as needed. If the peripherals lack built-in pull-ups, add them. Start with a 4.7 kOhm resistor, and lower the resistance if needed, especially for distances greater than 20 cm.
For distances longer than 20 cm, use twisted-pair cables and/or shielding to reduce noise, and lower the pull-up resistance. Alternatively, use dedicated I2C range extenders that boost the signal strength. If your application requires significantly longer distances, you may want to explore other communication interfaces designed for long-range use, such as CAN Bus, which is commonly used in automotive systems.
Materials
Slow Website?
This website is very fast, and pages should appear instantly. If this site is slow for you, then your routing may be messed up, and this issue does not only affect done.land, but potentially a few other websites and downloads as well. Here are simple steps to speed up your Internet experience and fix issues with slow websites and downloads..
Comments
Please do leave comments below. I am using utteran.ce, an open-source and ad-free light-weight commenting system.
Here is how your comments are stored
Whenever you leave a comment, a new github issue is created on your behalf.
-
All comments become trackable issues in the Github Issues section, and I (and you) can follow up on them.
-
There is no third-party provider, no disrupting ads, and everything remains transparent inside github.
Github Users Yes, Spammers No
To keep spammers out and comments attributable, all you do is log in using your (free) github account and grant utteranc.es the permission to submit issues on your behalf.
If you don’t have a github account yet, go get yourself one - it’s free and simple.
If for any reason you do not feel comfortable with letting the commenting system submit issues for you, then visit Github Issues directly, i.e. by clicking the red button Submit Issue at the bottom of each page, and submit your issue manually. You control everything.
Discussions
For chit-chat and quick questions, feel free to visit and participate in Discussions. They work much like classic forums or bulletin boards. Just keep in mind: your valued input isn’t equally well trackable there.
(content created Jul 07, 2024 - last updated Jan 22, 2025)