Основы · 11 мин чтения

Что такое I2C? SDA, SCL, подтягивающие резисторы и сканер на Arduino

Что такое I2C и как он работает? SDA и SCL, 7-битные адреса, расчёт подтягивающих резисторов, скетч I2C-сканера, конфликты адресов и пины Uno, ESP32 и Pico.

I2C (Inter-Integrated Circuit) — протокол последовательной связи, с помощью которого микроконтроллер общается с десятками датчиков, дисплеев и модулей всего по двум сигнальным проводам (SDA и SCL). Читается он как «и-два-си» (по-английски «I-squared-C»), а в некоторых даташитах называется IIC или TWI (Two Wire Interface). I2C LCD, OLED-дисплей, акселерометр MPU6050, датчик давления BMP280 и модуль часов DS1307 из проектов на Arduino — все говорят на этом протоколе; их можно параллельно подключить к одним и тем же двум проводам и обращаться к каждому по его собственному адресу.

В этом руководстве разберём, как I2C работает с точки зрения электрики, что означают адреса, почему без подтягивающих резисторов не обойтись и как рассчитать их номинал. Затем шаг за шагом пройдём таблицу пинов для Arduino Uno, ESP32 и Raspberry Pi Pico, скетч I2C-сканера, который находит все устройства на шине, пример чтения регистров без библиотеки и решения частых проблем вроде конфликта адресов.

I2C-адаптер для LCD с микросхемой PCF8574
I2C-адаптер для LCD: микросхема PCF8574, припаянная к обратной стороне дисплея, сокращает 16 пинов LCD всего до четырёх проводов (GND, VCC, SDA, SCL) и обычно отвечает по адресу 0x27 или 0x3F.

Что такое I2C и как он работает?

I2C разработала компания Philips (сегодня NXP) в 1982 году, чтобы микросхемы на одной плате могли общаться по небольшому числу проводов. На шине две роли: контроллер (раньше его называли master, ведущий), который начинает каждую передачу и формирует тактовый сигнал, и целевые устройства (раньше slave, ведомые), которые ему отвечают. В проектах на Arduino контроллером почти всегда выступает Arduino, ESP32 или Pico, а датчики и дисплеи — целевые устройства.

  • SDA (Serial Data): линия, по которой данные идут в обе стороны. Контроллер отправляет адреса и команды, а датчик по той же линии возвращает показания.
  • SCL (Serial Clock): линия тактового сигнала. На каждом тактовом импульсе считывается один бит на SDA, а такты формирует контроллер.
  • GND (общая земля): опорный уровень для сигналов. Даже у модулей с отдельным питанием GND должна быть общей.

Линии работают по схеме открытый сток (open-drain): ни одно устройство не выставляет на линии высокий уровень, оно может только прижать её к земле. Уровень 1 на линии держат подтягивающие резисторы, которые соединяют SDA и SCL с напряжением питания. Поэтому короткого замыкания не бывает, даже если два устройства пытаются говорить одновременно: если хоть одно прижимает линию, все видят 0. Сообщение I2C выглядит так:

  1. START: пока SCL в высоком уровне, контроллер переводит SDA из 1 в 0, и все устройства на шине начинают слушать.
  2. Адрес и бит направления: отправляется 7-битный адрес, а за ним бит чтения (1) или записи (0).
  3. ACK: устройство с этим адресом прижимает SDA во время 9-го тактового импульса и тем самым сообщает «я здесь». Если не отвечает никто, это называется NACK.
  4. Байты данных: каждый байт передаётся 8 битами, и приёмник отвечает на каждый подтверждением ACK. У большинства датчиков первый байт — номер регистра, который нужно прочитать или записать.
  5. STOP: пока SCL в высоком уровне, SDA поднимается из 0 в 1, и шина снова свободна. При чтении вместо STOP используется повторный START, чтобы сменить направление, не освобождая шину.

Если сравнить I2C с двумя другими популярными в мире Arduino протоколами, сразу видно, когда его выбирать:

ПараметрI2CSPIUART (Serial)
Сигнальные провода2 (SDA, SCL)3 общих (MOSI, MISO, SCK) + по одному CS на устройство2 (TX, RX)
Число устройствБольше 100 адресов на одной шинеСколько свободных пинов CSОбычно 2 устройства
Типичная скорость100 kHz, 400 kHz, 1 MHz10 MHz и выше9600 – 115200 бод
Выбор устройстваПо адресуПином CSНе нужен, точка-точка
Типичное применениеДатчики, часы, небольшие дисплеи, EEPROMSD-карты, TFT-дисплеи, RFIDGPS, Bluetooth, связь с компьютером

Скорости I2C и технические ограничения

РежимМаксимальная скоростьМаксимальное время нарастанияГде применяется?
Стандартный режим (Sm)100 kHz1000 нсПо умолчанию, длинные провода
Быстрый режим (Fm)400 kHz300 нсOLED, MPU6050, BMP280
Быстрый режим плюс (Fm+)1 MHz120 нсPico и некоторые новые датчики
Высокоскоростной режим (Hs)3,4 MHz80 нс (400 pF), нужны специальные драйверыВ хобби-проектах встречается редко

Библиотека Wire в Arduino по умолчанию запускается на 100 kHz; большинство датчиков поддерживают и 400 kHz, переключиться на эту частоту можно командой Wire.setClock(400000). На более высокой скорости дисплеи обновляются плавнее, но шина становится чувствительнее к длине проводов и номиналу подтяжки. По стандарту общая ёмкость шины (провода плюс выводы устройств) не должна превышать 400 pF. Обычные перемычки и шлейфы добавляют 50–100 pF на метр, а каждый вывод устройства — до 10 pF, поэтому I2C задумывался для работы в пределах одной платы или с проводами длиной в несколько десятков сантиметров. Дальше 1 метра придётся снизить скорость, поставить подтяжку посильнее или добавить расширители шины вроде P82B715.

Адреса I2C: 7-битные, 8-битные и зарезервированные

У каждого устройства на шине есть 7-битный адрес, что теоретически даёт 128 адресов. Диапазоны 0x00–0x07 и 0x78–0x7F зарезервированы для особых целей, поэтому для использования остаются 112 адресов от 0x08 до 0x77. Обычно адрес задаёт производитель микросхемы, но на многих модулях последние биты можно изменить паяными перемычками или пинами A0, A1, A2 или AD0.

Теперь запутанная часть: в некоторых даташитах и на наклейках на обратной стороне модулей адрес указан 8-битным, вместе с битом направления. Например, на обороте OLED-платы написано «0x78», а в коде адрес — 0x3C; если на LCD-модуле указано 0x4E, то в коде адрес 0x27. Правило простое: раздели 8-битное значение на 2 (сдвинь вправо на один бит) и получишь 7-битный адрес. Библиотеки для Arduino, ESP32 и MicroPython ожидают именно 7-битные адреса.

МодульМикросхемаАдрес по умолчаниюМожно изменить?
I2C-модуль для LCD (16x2, 20x4)PCF8574 / PCF8574A0x27 / 0x3FПеремычками A0–A2: 0x20–0x27 или 0x38–0x3F
OLED 0,96″SSD13060x3C0x3D резистором на обороте
Акселерометр и гироскопMPU60500x680x69 при AD0 = 1
Часы реального времениDS1307 / DS32310x68Нет
Давление и температураBMP280 / BME2800x76 или 0x77Зависит от пина SDO
ОсвещённостьBH17500x230x5C при ADDR = 1
16-битный АЦПADS11150x480x48–0x4B пином ADDR
16-канальный драйвер сервоприводов и PWMPCA96850x40Десятки адресов от 0x40 перемычками A0–A5
Память EEPROMAT24C32 / AT24C2560x500x50–0x57 через A0–A2
I2C-мультиплексорTCA9548A0x700x70–0x77 через A0–A2
Если просканировать модуль Tiny RTC (DS1307), рядом с 0x68 появится адрес 0x50; это не ошибка, а EEPROM AT24C32 на модуле. На модулях ZS-042 с DS3231 та же память отвечает по адресу 0x57.

Подтягивающие резисторы: зачем они нужны и как выбрать номинал

Устройства на шине I2C умеют только прижимать линии к земле, поэтому высокий уровень обеспечивают подтягивающие резисторы. Если резистор слишком большой, ёмкость шины замедляет переход из 0 в 1, фронты сигнала скругляются, и на высоких скоростях биты читаются с ошибками. Если он слишком маленький, растёт ток, который устройство должно пропустить через себя, прижимая линию; стандарт требует от устройства лишь не меньше 3 mA при 0,4 V, так что подтяжка должна держать ток ниже этого значения.

Две границы дают такие формулы: минимальное сопротивление R(min) = (VCC − 0,4 V) / 3 mA, а максимальное R(max) = t(нарастания) / (0,8473 × C(шины)). Для 5 V R(min) = 4,6 V / 0,003 A ≈ 1,53 kΩ, а для 3,3 V ≈ 0,97 kΩ. На короткой шине с ёмкостью 100 pF R(max) ≈ 11,8 kΩ на 100 kHz и ≈ 3,5 kΩ на 400 kHz. Поэтому на практике чаще всего ставят 4,7 kΩ для 100 kHz и 2,2 kΩ для 400 kHz и нагруженных шин. Прочитать полосы резистора поможет утилита Цветовая маркировка резисторов, а задержку, которую создают сопротивление и ёмкость, покажет утилита Постоянная времени RC.

СитуацияРекомендуемая подтяжкаПримечание
Один модуль, короткие провода, 100 kHz4,7 kΩ – 10 kΩНа большинстве модулей они уже есть
Несколько модулей, 400 kHz2,2 kΩ – 4,7 kΩРезисторы на модулях оказываются включены параллельно
Провода длиннее 50 см2,2 kΩ и 100 kHzНе скручивай SDA с SCL; каждый скручивай с GND
Шина 3,3 V (ESP32, Pico)2,2 kΩ – 4,7 kΩПодключай резисторы к 3,3 V, а не к 5 V
На большинстве модулей уже стоят подтягивающие резисторы 4,7 kΩ или 10 kΩ, а резисторы модулей на одной шине оказываются включены параллельно. Если у трёх модулей по 4,7 kΩ, в сумме получается около 1,57 kΩ; при 5 V это чуть ниже предела в 3 mA. Если на шине собираются четыре-пять модулей, возможно, у части из них придётся выпаять подтяжку или разрезать её паяную перемычку.

На Arduino Uno вызов Wire.begin() заодно включает встроенные подтягивающие резисторы ATmega328P на 20–50 kΩ. С одним модулем и проводами 10–20 см их часто хватает, но надёжными их не назовёшь; внешние резисторы всегда лучше. Если используется голая плата датчика без подтяжки, не забудь поставить резисторы 4,7 kΩ от SDA и от SCL к VCC.

Пины I2C: Arduino Uno, Mega, ESP32, ESP8266 и Pico

ПлатаSDASCLПримечание
Arduino Uno / NanoA4A5На Uno R3 пины SDA и SCL рядом с AREF — это та же шина, что и A4/A5
Arduino Mega 25602021На Mega A4 и A5 не относятся к I2C
Arduino Leonardo / MicroD2D3Это цифровые пины
ESP32 (DevKit)GPIO 21GPIO 22Другие пины задаются через Wire.begin(SDA, SCL); вторая шина — Wire1
ESP8266 NodeMCUD2 (GPIO 4)D1 (GPIO 5)Программный I2C, пины можно менять
Raspberry Pi PicoGP4 (I2C0)GP5 (I2C0)I2C0 и I2C1 доступны на многих парах пинов
Arduino Uno работает от 5 V, а ESP32, ESP8266 и Pico — от 3,3 V. Если модуль, подключённый к плате на 3,3 V, питается от 5 V и его подтяжка идёт к 5 V, линии SDA и SCL поднимаются до 5 V и могут повредить пины, не рассчитанные на 5 V. Питай модуль от 3,3 V или поставь между двумя напряжениями двунаправленный преобразователь уровней на транзисторах BSS138.

Шаг за шагом: ищем адреса скетчем I2C-сканера

Когда в руках новый модуль, первое дело — узнать адреса устройств на шине. I2C-сканер отправляет пустое сообщение на каждый адрес от 0x08 до 0x77 и выводит список тех, кто ответил ACK. Так сразу становится ясно и то, что модуль подключён правильно, и то, какой адрес нужно указать в коде.

  1. Подключи GND модуля к GND Arduino, а VCC — к 5V (к 3.3V для модулей, которые поддерживают только 3,3 V).
  2. Подключи SDA к A4, а SCL к A5. Если модулей несколько, соедини все их пины SDA и SCL на макетной плате.
  3. Загрузи скетч ниже и открой монитор порта на скорости 115200 бод.
  4. Запиши найденные адреса. Если ничего не появилось, проверь подключение, общую GND и подтягивающие резисторы.
  5. Отключай и снова подключай модули по одному, чтобы убедиться, какой адрес какому устройству принадлежит; сканер повторяет поиск каждые 5 секунд.
C++ (Arduino IDE)
1#include <Wire.h>
2
3void printHex(byte addr) {
4  Serial.print(F("0x"));
5  if (addr < 16) Serial.print('0');    // tek haneliye sıfır ekle / pad single digit
6  Serial.print(addr, HEX);
7}
8
9void setup() {
10  Serial.begin(115200);
11  Wire.begin();                         // Uno: A4 = SDA, A5 = SCL
12#if defined(ARDUINO_ARCH_AVR)
13  Wire.setWireTimeout(3000, true);      // AVR (Uno, Nano, Mega): hat kilitlenirse 3 ms sonra kurtar / recover a stuck bus after 3 ms
14#endif
15  Serial.println(F("I2C tarayici / I2C scanner"));
16}
17
18void loop() {
19  byte found = 0;
20  for (byte addr = 0x08; addr <= 0x77; addr++) {   // geçerli 7 bit adresler / valid 7-bit addresses
21    Wire.beginTransmission(addr);
22    byte err = Wire.endTransmission();             // 0 = cihaz ACK verdi / device acknowledged
23    if (err == 0) {
24      Serial.print(F("Bulundu / found: "));
25      printHex(addr);
26      Serial.println();
27      found++;
28    } else if (err == 4 || err == 5) {
29      Serial.print(F("Hat hatasi / bus error at "));
30      printHex(addr);
31      Serial.println();
32    }
33  }
34  if (found == 0) {
35    Serial.println(F("Cihaz yok: kablolari ve pull-up'lari kontrol et / no devices: check wiring and pull-ups"));
36  } else {
37    Serial.print(found);
38    Serial.println(F(" cihaz bulundu / device(s) found"));
39  }
40  Serial.println();
41  delay(5000);                          // 5 sn sonra yeniden tara / rescan after 5 s
42}
Результат endTransmission()ЗначениеЧто делать
0Устройство подтвердило свой адрес (ACK)Используй этот адрес в коде
1Данные не помещаются в буферВ сканере не встречается; на Uno не записывай больше 32 байт за раз
2NACK на адресПо этому адресу устройства нет, при сканировании это нормально
3NACK на данныеУстройство отклонило команду; проверь номер регистра
4Другая ошибка шиныКороткое замыкание, нет подтяжки или помехи
5Тайм-аутШина зависла; проверь подключение и питание

Строка setWireTimeout в скетче важна: если SDA или SCL замкнуты или какое-то устройство зависло, прижав линию, библиотека Wire на Uno с настройками по умолчанию может ждать бесконечно, и программа зависнет. С включённым тайм-аутом библиотека сдаётся через 3 мс, сбрасывает аппаратный блок I2C, а сканер сообщает о проблеме кодом ошибки. Строка обёрнута в #if, поэтому компилируется только на платах AVR (Uno, Nano, Mega); у библиотек Wire для ESP32 и ESP8266 уже есть своя защита по тайм-ауту, так что один и тот же скетч без изменений компилируется и работает на всех трёх платформах.

I2C без библиотеки: чтение и запись регистров

Библиотеки упрощают жизнь, но внутри все они делают одно и то же: отправляют устройству номер регистра, а затем читают байты из этого регистра или записывают в него. Если хотя бы раз проделать это вручную, можно разобраться в даташите нового датчика и пользоваться им даже без библиотеки. Пример ниже выводит датчик MPU6050 из спящего режима, читает его регистр идентификации (WHO_AM_I), а затем по сырым значениям вычисляет температуру и ускорение по оси Z.

Модуль акселерометра и гироскопа MPU-6050
Модуль MPU-6050: подключается к шине I2C через пины VCC, GND, SCL и SDA, а пин AD0 выбирает адрес 0x68 или 0x69.
C++ (Arduino IDE)
1#include <Wire.h>
2
3const byte MPU_ADDR = 0x68;             // AD0 GND'de; AD0 = 3.3V ise 0x69 / AD0 low; 0x69 if AD0 high
4
5void writeReg(byte reg, byte value) {
6  Wire.beginTransmission(MPU_ADDR);
7  Wire.write(reg);                      // önce yazmaç adresi / register address first
8  Wire.write(value);                    // sonra veri / then the data
9  Wire.endTransmission();               // STOP gönder / send STOP
10}
11
12int16_t readWord(byte reg) {
13  Wire.beginTransmission(MPU_ADDR);
14  Wire.write(reg);
15  Wire.endTransmission(false);          // STOP yok, tekrarlı START / no STOP, repeated START
16  Wire.requestFrom(MPU_ADDR, (byte)2);  // 2 bayt iste / request 2 bytes
17  uint8_t hi = Wire.read();
18  uint8_t lo = Wire.read();
19  return (int16_t)(((uint16_t)hi << 8) | lo);
20}
21
22void setup() {
23  Serial.begin(115200);
24  Wire.begin();
25  Wire.setClock(400000);                // hızlı mod 400 kHz / fast mode 400 kHz
26  writeReg(0x6B, 0x00);                 // PWR_MGMT_1: uykudan uyandır / wake up from sleep
27  Wire.beginTransmission(MPU_ADDR);
28  Wire.write(0x75);                     // WHO_AM_I yazmacı / WHO_AM_I register
29  Wire.endTransmission(false);
30  Wire.requestFrom(MPU_ADDR, (byte)1);
31  Serial.print(F("WHO_AM_I = 0x"));
32  Serial.println(Wire.read(), HEX);     // 68 beklenir / expect 68
33}
34
35void loop() {
36  int16_t raw = readWord(0x41);         // TEMP_OUT_H ve TEMP_OUT_L / TEMP_OUT_H and TEMP_OUT_L
37  float tempC = raw / 340.0 + 36.53;    // veri sayfasındaki formül / datasheet formula
38  int16_t az = readWord(0x3F);          // Z ekseni ivmesi / Z-axis acceleration
39  Serial.print(F("Sicaklik / temp: "));
40  Serial.print(tempC, 1);
41  Serial.print(F(" C   AccZ: "));
42  Serial.println(az / 16384.0, 2);      // +-2g aralığında 16384 = 1 g / 16384 = 1 g at +-2g
43  delay(500);
44}

Обрати внимание на строку endTransmission(false) в функции чтения: она меняет направление повторным START вместо STOP, поэтому никакое другое устройство не может вклиниться, а датчик не забывает, какой регистр запрошен. Если WHO_AM_I возвращает 0x68, связь в полном порядке. На дешёвых модулях-клонах значение может быть 0x70 или другим числом; это значит, что стоит совместимая, но другая микросхема, например MPU6500, и именно из-за этого некоторые готовые библиотеки пишут «sensor not found» (датчик не найден). Формула температуры (сырое значение / 340 + 36.53) взята прямо из даташита MPU6050; для ускорения в диапазоне ±2 g сырое значение 16384 соответствует 1 g, поэтому у датчика, лежащего ровно на столе, по оси Z будет около 1.00.

Несколько устройств на одной шине и конфликты адресов

Главное преимущество I2C в том, что устройства можно подключать к тем же двум проводам параллельно, пока их адреса различаются. Например, LCD (0x27), OLED (0x3C), BMP280 (0x76) и часы DS3231 (0x68) спокойно делят одни и те же пины A4 и A5: каждая библиотека говорит со своим адресом, а остальные устройства молча слушают. Проблемы начинаются, когда у двух устройств одинаковый адрес: оба отвечают ACK, их данные сталкиваются, и обычно не работает ни одно. Вот способы это исправить:

  • Смени адрес пином: если подключить пин AD0 у MPU6050 к 3,3 V, адрес станет 0x69, и конфликт с DS3231 (0x68) исчезнет.
  • Используй паяные перемычки: перемычки A0–A2 на LCD-модулях дают 8 адресов, а пин ADDR у ADS1115 — 4.
  • Заведи вторую шину I2C: перенеси конфликтующее устройство на отдельные пины через Wire1 на ESP32 или I2C1 на Pico.
  • Добавь I2C-мультиплексор: TCA9548A открывает восемь отдельных подшин с одного адреса (0x70); так можно подключить даже восемь OLED с одинаковым адресом.
  • Устройства с фиксированным адресом: у некоторых микросхем, например DS1307 или HTU21D, адрес изменить вообще нельзя; им поможет только отдельная шина или мультиплексор.

I2C на ESP32: любые пины и две отдельные шины

На ESP32 аппаратный блок I2C можно гибко вывести на разные пины. По умолчанию это GPIO 21 (SDA) и GPIO 22 (SCL), но с Wire.begin(SDA, SCL) можно выбрать почти любые два GPIO. У классического ESP32 и ESP32-S3 два контроллера I2C, поэтому два датчика с одинаковым адресом можно запустить на двух отдельных шинах; у ESP32-C3 контроллер только один. GPIO 34–39 работают только на вход и для I2C не подходят. Полную карту пинов платы смотри в утилите Распиновка, а общее введение — в статье Что такое ESP32?.

C++ (Arduino IDE)
1#include <Wire.h>
2
3// Klasik ESP32'de iki I2C denetleyicisi vardır: Wire ve Wire1 / the classic ESP32 has two I2C controllers: Wire and Wire1
4
5void scan(TwoWire &bus, const char *name) {
6  Serial.printf("%s:\n", name);
7  for (uint8_t addr = 0x08; addr <= 0x77; addr++) {
8    bus.beginTransmission(addr);
9    if (bus.endTransmission() == 0) {
10      Serial.printf("  bulundu / found 0x%02X\n", addr);
11    }
12  }
13}
14
15void setup() {
16  Serial.begin(115200);
17  Wire.begin(21, 22);                   // SDA, SCL: varsayılan pinler / default pins
18  Wire1.begin(32, 33, 400000);          // SDA, SCL, hız: başka iki GPIO / SDA, SCL, speed: any two other GPIOs
19  scan(Wire, "Wire  (SDA 21, SCL 22)");
20  scan(Wire1, "Wire1 (SDA 32, SCL 33)");
21}
22
23void loop() {
24}

I2C на Raspberry Pi Pico (MicroPython)

У микросхемы RP2040 в Pico два контроллера — I2C0 и I2C1, и каждый можно вывести на несколько разных пар пинов. Для I2C0 подходят GP0/GP1, GP4/GP5, GP8/GP9, GP12/GP13, GP16/GP17 и GP20/GP21; для I2C1 — GP2/GP3, GP6/GP7, GP10/GP11, GP14/GP15, GP18/GP19 и GP26/GP27. В каждой паре чётный пин — SDA, а нечётный — SCL. В MicroPython сканер умещается в одну строку: i2c.scan() возвращает список адресов, ответивших ACK. Pico работает от 3,3 V, поэтому питать модули от пина 3V3(OUT) безопаснее всего; RP2040 поддерживает и режим Fast mode plus на 1 MHz, но на макетной плате с 400 kHz сюрпризов меньше. Первые шаги с Pico описаны в статье Что такое Raspberry Pi Pico?.

MicroPython
1from machine import Pin, I2C
2
3i2c = I2C(0, sda=Pin(4), scl=Pin(5), freq=400000)   # I2C0: GP4 = SDA, GP5 = SCL
4devices = i2c.scan()                                 # ACK veren adresler / addresses that ACK
5
6if devices:
7    for addr in devices:
8        print("Bulundu / found:", hex(addr))
9else:
10    print("Cihaz yok / no devices")
11
12# MPU6050 varsa WHO_AM_I yazmacını oku / if an MPU6050 is present, read WHO_AM_I
13if 0x68 in devices:
14    i2c.writeto_mem(0x68, 0x6B, b"\x00")             # uykudan uyandır / wake up
15    who = i2c.readfrom_mem(0x68, 0x75, 1)[0]
16    print("WHO_AM_I:", hex(who))                     # 0x68 beklenir / expect 0x68

Идеи проектов с I2C

  • Мини-метеостанция: измеряй давление и температуру с BMP280 и выводи их на OLED-дисплей; оба модуля делят одни и те же два провода.
  • Цифровые часы: читай время из модуля часов DS3231 и выводи его на I2C LCD-дисплей.
  • Индикатор наклона: вычисляй угол с помощью MPU6050 и рисуй результат на OLED, как на электронном уровне.
  • Wi-Fi-узел с датчиком: следи с телефона за датчиком, подключённым к пинам D1 и D2 платы ESP8266 NodeMCU.
  • Роборука на 16 сервоприводов: управляй 16 сервоприводами всего с двух пинов через драйвер PCA9685.
  • Регистратор данных: записывай показание в EEPROM AT24C256 каждую минуту, чтобы данные пережили отключение питания.

Частые ошибки и как их исправить

ПризнакВероятная причинаРешение
Сканер не находит ни одного устройстваПерепутаны SDA и SCL, нет общей GND или модуль без питанияПроверь подключение; на Uno A4 = SDA, A5 = SCL
Сканер зависает или выдаёт ошибки на каждом адресеЗамыкание на шине или нет подтяжкиДобавь setWireTimeout; измерь напряжение питания на SDA и SCL в покое
Скетч компилируется, но дисплей пустойНеверный адрес в коде (0x27 вместо 0x3F)Используй адрес, найденный сканером
На обороте платы написано 0x78, и код не работаетИспользован 8-битный адресРаздели на 2: 0x78 → 0x3C
Два датчика не работают вместеКонфликт адресовСмени адрес пином, используй вторую шину или TCA9548A
Случайные зависания, сбои при работе мотораДлинные провода, помехи или слабое питаниеУкороти провода, снизь частоту до 100 kHz, поставь на модули конденсаторы 100 nF
Повреждён пин ESP32 или PicoК пину 3,3 V подключена подтяжка к 5 VПитай модуль от 3,3 V или используй преобразователь уровней
При проблемах с I2C лучший друг — мультиметр: при включённом питании и отсутствии обмена на SDA и SCL должно быть напряжение питания (5 V или 3,3 V). Если там 0 V, какое-то устройство замкнуло линию или зависло. На обесточенной плате можно ещё и примерно определить общий номинал подтяжки на шине, измерив сопротивление между SDA и VCC.

I2C — самый практичный способ добавить в проект дисплеи, часы, датчики и память всего по двум проводам; когда понятны адреса, подтягивающие резисторы и скетч-сканер, большинство проблем решается за несколько минут. В приложении BlueGrays есть проекты на I2C: I2C LCD-дисплей, игра Pong на OLED-дисплее, цифровые часы с DS1307 и погодный дисплей на ESP32 — у каждого пошаговые схемы подключения и код.

Частые вопросы

Чем I2C отличается от SPI?

I2C благодаря адресации позволяет посадить больше сотни устройств на одни и те же два провода, но обычно ограничен 100–400 kHz. SPI нужны три общих провода плюс отдельный пин выбора микросхемы (CS) для каждого устройства; зато он достигает 10 MHz и выше. I2C выбирают для датчиков и небольших дисплеев, SPI — для SD-карт и цветных TFT-дисплеев.

Сколько устройств можно подключить к шине I2C?

7-битная адресация даёт 112 доступных адресов. На практике предел задаёт не столько число адресов, сколько ёмкость шины (максимум 400 pF) и параллельно включённые подтягивающие резисторы; на макетной плате нормально работают 5–10 устройств. Для большего числа используй мультиплексор TCA9548A или вторую шину I2C.

Какого номинала должны быть подтягивающие резисторы I2C?

Чаще всего ставят 4,7 kΩ для 100 kHz и коротких проводов и 2,2 kΩ для 400 kHz или шин с большим числом устройств. Не опускайся ниже 1,5 kΩ на шине 5 V и ниже 1 kΩ на шине 3,3 V. И помни, что резисторы на модулях оказываются включены параллельно.

Какие пины на Arduino Uno относятся к I2C?

На Arduino Uno и Nano SDA — это пин A4, а SCL — пин A5. У Uno R3 рядом с AREF есть ещё два пина с подписями SDA и SCL, но на плате они соединены с A4 и A5 и отдельной шиной не являются. На Mega пины I2C — 20 (SDA) и 21 (SCL).

Какой максимальной длины может быть кабель I2C?

I2C задумывался для коротких расстояний в пределах платы; на 100 kHz и с подходящей подтяжкой он обычно работает примерно до 1 метра. Для больших расстояний нужно снизить скорость, взять кабель «витая пара» или перейти на драйверы шины вроде P82B715. Для нескольких метров лучше выбрать RS-485 или беспроводную связь.

Что делать, если I2C-сканер не находит устройство?

Сначала проверь, что SDA и SCL стоят на правильных пинах, общая GND подключена, а модуль получает питание. Затем проверь подтяжку, измерив напряжение питания на SDA и SCL в покое. Если устройство всё равно не находится, попробуй модуль отдельно, с короткими проводами и на 100 kHz, а на ESP32 убедись, что в Wire.begin переданы правильные пины.

Все проекты
LCD-экран с I2C
#32Новичок
Premium

LCD-экран с I2C

Дай своему Arduino собственный экран и заставь его написать первое сообщение. Двухстрочный LCD-экран подключается всего несколькими проводами; в верхней строке появляется приветствие, затем второе соо

4.8(53)
70
I2C LCD-дисплей (16x2) на ESP32
#119Средний
Premium

I2C LCD-дисплей (16x2) на ESP32

В этом проекте символьный LCD-экран 16x2 подключается к ESP32 по протоколу I2C и выводит текст. Благодаря I2C экраном можно управлять всего двумя пинами данных (SDA и SCL), не тратя 6+ пинов, как при классическом параллельном подключении. Код печатает постоянное сообщение в первой строке и счётчик, растущий каждую секунду, во второй. Кроме того, при запуске работает сканер I2C, который выводит адрес дисплея в монитор порта.

4.9(23)
40
Цифровые часы на ESP32 и DS1307 RTC (I2C + LCD)
#120Средний
Premium

Цифровые часы на ESP32 и DS1307 RTC (I2C + LCD)

В этом проекте время и дата из модуля часов реального времени (RTC) DS1307 выводятся на I2C LCD-экран 16x2. DS1307 — RTC с резервной батарейкой, который хранит время даже при выключенной ESP32. Оба модуля делят одну шину I2C (SDA/SCL), и ты узнаёшь, как управлять несколькими устройствами всего по двум сигнальным проводам. Проект даёт практические знания о протоколе I2C, работе модуля RTC и динамическом выводе данных на LCD-экран.

4.6(26)
40
Калькулятор на Arduino с I2C
#94Средний
Premium

Калькулятор на Arduino с I2C

Калькулятор на Arduino, который выполняет сложение, вычитание, умножение и деление с помощью плёночной клавиатуры 4x4 и LCD-дисплея 16x2 с I2C. Благодаря I2C дисплей подключается всего 2 проводами, поэтому проводов меньше, а свободных пинов больше. Поддерживаются ввод дробных чисел и отрицательные числа.

5.0(31)
43
Игра в пинг-понг — SSD1306
#86Средний
Premium

Игра в пинг-понг — SSD1306

Мяч, две ракетки и ты: на маленьком OLED-экране ты играешь в настольный теннис — одну из самых первых видеоигр. Две кнопки двигают твою ракетку справа вверх и вниз, а левой ракеткой управляет компьюте

4.5(47)
65
ESP32 HTTPClient + API погоды (с OLED-дисплеем SSD1306)
#134Продвинутый
Premium

ESP32 HTTPClient + API погоды (с OLED-дисплеем SSD1306)

В этом проекте ESP32 через HTTPClient.h делает вызов REST API к сервису погоды (wttr.in). В отличие от прошлой версии с I2C LCD, здесь используется OLED SSD1306 (128×64), который позволяет крупные шрифты, векторные значки и богатую картинку на одном экране. Семь векторных значков погоды (солнечно, переменная облачность, облачно, дождь, снег, гроза, туман) рисуются во время работы (растровые файлы не нужны). Температура выводится крупными цифрами.

4.3(10)
19
Часы и календарь на матрице (MAX7219, DS1307)
#84Средний
Premium

Часы и календарь на матрице (MAX7219, DS1307)

Светящееся табло для стола или стены, которое показывает время и дату бегущей строкой. На светодиодном дисплее 8x32 крупные цифры часов, а две точки между ними мигают каждую секунду; в начале каждой м

5.0(37)
59
Регистратор температуры на ESP32 (DHT22 + DS1307 RTC + microSD + OLED)
#144Продвинутый
Premium

Регистратор температуры на ESP32 (DHT22 + DS1307 RTC + microSD + OLED)

Собери на ESP32 регистратор температуры с отметками времени! Каждую минуту читай температуру и влажность с DHT22, бери реальное время из DS1307 RTC и записывай всё на карту microSD в формате CSV. OLED показывает текущую температуру (крупным шрифтом), влажность в процентах, время и счётчик записей. Файл /temp_log.csv на SD-карте открывается в Excel, Google Sheets или Python pandas — идеально для теплиц, комнат, лабораторий и хранения продуктов.

4.7(7)
12