← До всіх проєктів
Основи Початковий

I2C-сканер: знаходимо адреси всіх модулів і лагодимо «датчик не знайдено»

Найкорисніший скетч для будь-якого проєкту з I2C. Перебираємо всі 127 адрес, підписуємо знайдені пристрої і розбираємо п'ять причин, чому модуль не відповідає: від переплутаних SDA/SCL до відсутньої підтяжки і конфлікту адрес.

Складність
Початковий
Час
20 min
Категорія
Основи
Оновлено

Про проєкт

«Sensor not found» — найчастіша помилка в проєктах з дисплеями й датчиками на I2C. Перш ніж шукати проблему в бібліотеці, варто з'ясувати, чи взагалі пристрій відповідає на шині і за якою адресою. Для цього існує I2C-сканер: він по черзі звертається до кожної адреси й дивиться, чи хтось відповість.

Що потрібно

  • ESP32 DevKit (або Arduino)
  • Будь-які I2C-модулі: у прикладі AHT20, BMP280, OLED SSD1306 і розширювач PCF8574

Схема

Усі модулі — паралельно на одні й ті самі два проводи:

Сигнал ESP32 Arduino Uno ESP32-C3 SuperMini
SDA GPIO21 A4 GPIO8
SCL GPIO22 A5 GPIO9
VCC 3V3 5V 3V3

Як працює сканер

Кожен обмін по I2C починається з адреси. Пристрій, що впізнав свою адресу, відповідає бітом ACK. Wire.endTransmission() повертає 0, якщо ACK прийшов, і 2, якщо ні. Сканер просто перебирає адреси від 1 до 126.

Код

// I2C-сканер: які адреси відповідають на шині
#include <Wire.h>

const char* guess(uint8_t a) {   // типові пристрої за адресою
  switch (a) {
    case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27: return "PCF8574 / LCD 1602";
    case 0x38: return "AHT10 / AHT20";
    case 0x3C: case 0x3D: return "OLED SSD1306";
    case 0x40: return "INA219";
    case 0x48: return "ADS1115";
    case 0x5A: return "MLX90614";
    case 0x68: return "DS3231 / MPU6050";
    case 0x76: case 0x77: return "BME280 / BMP280";
    default: return "?";
  }
}

void scan() {
  Serial.println("Сканую I2C...");
  int found = 0;
  for (uint8_t addr = 1; addr < 127; addr++) {
    Wire.beginTransmission(addr);
    if (Wire.endTransmission() == 0) {
      Serial.printf("  0x%02X  %s\n", addr, guess(addr));
      found++;
    }
  }
  Serial.printf("Знайдено пристроїв: %d\n\n", found);
}

void setup() {
  Serial.begin(115200);
  Wire.begin();   // ESP32: SDA 21, SCL 22
  scan();
}

void loop() {
  delay(5000);
  scan();   // від'єднайте модуль — і побачите, що він зник
}

У симуляторі видаліть провід SDA одного з модулів або змініть його адресу у властивостях — наступне сканування це покаже.

П'ять причин, чому модуль «не знайдено»

  1. Переплутані SDA і SCL. Найчастіша помилка. Сканер не знайде нічого — поміняйте проводи місцями.
  2. Не та адреса. BME280/BMP280 буває 0x76 або 0x77, OLED — 0x3C або 0x3D, LCD 1602 — 0x27 або 0x3F. Бібліотеки мають адресу за замовчуванням, і вона часто не збігається з вашим модулем. Передайте ту, що знайшов сканер: bme.begin(0x76).
  3. Немає підтяжки. Лініям I2C потрібні резистори 4.7–10 кОм до VCC. На модулях вони майже завжди є; якщо «голий» датчик не знаходиться — додайте їх.
  4. Конфлікт адрес. Два однакові датчики на одній шині мають однакову адресу. Переставте перемичку адреси на одному з них (SDO, A0–A2) або використайте другу шину: на ESP32 є Wire1.
  5. Живлення і рівні. Модуль на 5 В без стабілізатора не працює від 3.3 В, а 5-вольтова підтяжка на модулі шкодить входам ESP32. Для змішаних систем потрібен перетворювач рівнів (BSS138).

Корисно знати

  • Довжина проводів. I2C розрахований на плату, а не на будинок: до 30–50 см на 100 кГц. Для довших ліній зменште частоту Wire.setClock(50000) або візьміть диференційний розширювач.
  • Адреси 0x00–0x07 і 0x78–0x7F зарезервовані, тому сканер їх пропускає.