Гайд · I²C · Отладка
Датчик I²C не определяется? Вот решение — по порядку
Подключил BME280 (или OLED, или MPU6050), прошил скетч, а в ответ — тишина. Плата не видит датчик. В девяти случаях из десяти виновата одна из четырёх вещей, и все они проверяются за минуту, если идти в правильном порядке. Одинаково работает на ESP32, ESP8266 и Arduino.
Если хочешь понять физику того, что I²C делает на проводе — START, ACK, растягивание такта — смотри интерактивный разбор «один байт — шесть шин». Этот пост — его практическая половина: шина молчит, что дальше?
Шаг 1 — всегда сначала сканируй шину
Никогда не отлаживай вслепую. Каждое устройство I²C отвечает на своём 7-битном адресе, и у шины можно прямо спросить, кто на связи. Прошей это и открой Serial Monitor на 115200:
#include <Wire.h>
void setup() {
Serial.begin(115200);
Wire.begin(); // ESP8266: D2/D1 · ESP32: 21/22 · Uno: A4/A5
}
void loop() {
byte found = 0;
Serial.println("Scanning I2C bus...");
for (byte addr = 1; addr < 127; addr++) {
Wire.beginTransmission(addr);
if (Wire.endTransmission() == 0) { // 0 = устройство ответило ACK
Serial.printf(" found device at 0x%02X\n", addr);
found++;
}
}
Serial.println(found ? "done." : "No devices found — check wiring & pull-ups.");
delay(3000);
} Три исхода — три диагноза:
- Адрес датчика появился (например,
0x76у BME280) — питание и провода в порядке, баг в коде драйвера или в неправильном адресе в библиотеке. - Появился другой адрес — у тебя не та микросхема или не тот адрес (многие платы перемычкой переключаются между двумя адресами).
- «No devices found» — сломан электрический уровень. Читай дальше.
Хочешь сканер на веб-странице, а не через serial-кабель? Пример RisalDash I2C-Scanner выводит каждый адрес с догадкой о чипе, живьём в браузере.
Шаг 2 — подтягивающие резисторы (причина №1 молчащей шины)
Выходы I²C — с открытым стоком: устройство умеет только притягивать линию к нулю. Обратно вверх, к логической единице, её тянут подтягивающие резисторы — один на SDA, один на SCL, к 3V3. Без них линии «болтаются», ничего не читается как высокий уровень, и сканер не находит вообще ничего.
- На многих платах-брейкаутах подтяжки уже стоят (часто 10 кОм или 4,7 кОм). Один датчик на коротком проводе обычно просто работает.
- Ставь свои, только если на плате-ведущем их нет. Типовые номиналы: 4,7 кОм на 100 кГц, 2,2 кОм на 400 кГц — два резистора на всю шину, а не на каждое устройство.
- Навесил кучу модулей, и у каждого своя подтяжка? Параллельное сопротивление падает слишком низко, и линии уже не подтянуть чисто — убери лишние.
Номинал — это компромисс: меньше сопротивление = чётче фронты, но больше ток; предел по даташиту — ёмкость шины (≤400 пФ), и это подводит нас к следующей ловушке.
Шаг 3 — длинные провода убивают I²C
I²C придумали для микросхем на одной плате — сантиметры, не метры. Каждый лишний сантиметр провода добавляет ёмкость, фронт заваливается, и после ~400 пФ ведущий уже не отличает 1 от 0. Симптом: на столе работает, а стоит протянуть датчик через комнату — начинает сбоить.
- Снизь скорость до 100 кГц (или ниже):
Wire.setClock(100000); - Поставь подтяжки посильнее (2,2 кОм), чтобы бороться с ёмкостью.
- Используй витую или экранированную пару, держи провода короткими и не пускай их в одном шлейфе с шумными сигналами.
- Реально нужны метры? Тогда I²C — не та шина, бери дифференциальную (RS-485/CAN). См. почему I²C короткобойный.
Шаг 4 — два датчика, один адрес
Сканер видит устройство, а второй такой же датчик невидим — потому что у них один фиксированный адрес.
Два BME280 отвечают на 0x76 и глушат друг друга. Решения:
- Пин адреса — у большинства датчиков есть
ADDR/SDO, который переключает на второй адрес (0x76→0x77). Один на «плюс», другой на «землю». - Мультиплексор I²C —
TCA9548Aдаёт 8 изолированных под-шин, и восемь одинаковых датчиков уживаются за одним адресом. - Вторая шина — у ESP32 два аппаратных блока I²C; подними
Wire1.begin(sda2, scl2)на других пинах.
Всё ещё тишина? Последние подозреваемые
- Перепутаны SDA/SCL — классика. SDA→SDA, SCL→SCL; перекрёст выглядит так же, но шина молчит.
- Уровни напряжения — 5-вольтовому датчику на 3,3-вольтовом ESP32 (или наоборот) нужен преобразователь уровней; не подавай 5 В прямо на пин ESP32.
- Питание — прожорливый модуль просаживает 3V3 и выпадает с шины. Дай нормальное питание и конденсатор.
- Зависший ведомый держит SDA внизу и блокирует всю шину. Лечится импульсами SCL
(до 9 раз) перед
Wire.begin()— или просто питание по кругу.
Иди по списку сверху вниз — сканер, подтяжки, длина проводов, адреса, потом мелочи — и мёртвая шина I²C почти всегда оживает за пару минут.
Собери схему со своим датчиком и экспортни картинку — прямо в браузере, без Fritzing.