Введение
Вы когда-нибудь подключали новый I2C-датчик или дисплей к Arduino и задавались вопросом: «Какой адрес у этого устройства?» Вы не одиноки! Протокол I2C — это мощный способ общения с несколькими устройствами всего по двум проводам, но у каждого устройства есть уникальный адрес — и иногда этот адрес не очевиден из технической документации. Вот тут-то и приходит на помощь I2C-сканер. Это простой скетч, который проверяет все возможные адреса и сообщает, какие из них отвечают.
В этом руководстве мы создадим I2C-сканер с использованием Arduino Uno и OLED-дисплея SSD1306 (который также послужит известным устройством на шине). Мы запустим всё в браузерном симуляторе Velxio, так что вам не понадобится никакое оборудование. К концу вы поймёте, как работает шина I2C, как подключать устройства и как писать код для их сканирования.
Давайте начнём!
Схема подключения

Схема удивительно проста. Нам понадобятся всего два компонента:
- Arduino Uno — мозг операции.
- OLED-дисплей SSD1306 — монохромный дисплей 128x64 пикселей, использующий I2C для связи. Его адрес по умолчанию —
0x3C.
Детали подключения
Подключите OLED к Arduino с помощью четырёх проводов:
| Пин Arduino | Пин OLED | Цвет провода |
|---|---|---|
| A4 (SDA) | DATA | Синий |
| A5 (SCL) | CLK | Оранжевый |
| GND | GND | Чёрный |
| 5V | VIN | Красный |
- SDA (A4) — линия данных. Она передаёт фактические данные между мастером (Arduino) и ведомым (OLED).
- SCL (A5) — линия тактового сигнала. Она синхронизирует передачу данных.
- GND и 5V обеспечивают питание OLED.
Примечание: На Arduino Uno A4 и A5 — это выделенные пины I2C. На других платах могут использоваться другие пины (например, SDA/SCL на ESP32).
В симуляторе Velxio вы можете добавить OLED из палитры компонентов и подключить его, щёлкая по пинам. Панель инструментов холста помогает увеличивать и перемещать изображение для удобства подключения.

Разбор кода

Теперь давайте посмотрим на код. Откройте редактор кода в Velxio (вы увидите редактор Monaco с подсветкой синтаксиса). Скетч написан на Arduino C++ и использует встроенную библиотеку Wire.
Подключение библиотеки
#include <Wire.h>
Библиотека Wire обрабатывает всю низкоуровневую связь I2C. Она входит в состав Arduino IDE, поэтому дополнительная установка не требуется.
Функция Setup
void setup() {
Wire.begin();
Serial.begin(9600);
Serial.println("===========================");
Serial.println(" I2C Bus Scanner (TWI)");
Serial.println("===========================");
Serial.println("Scanning...");
Serial.println();
int devicesFound = 0;
for (byte addr = 1; addr < 127; addr++) {
Wire.beginTransmission(addr);
byte error = Wire.endTransmission();
if (error == 0) {
Serial.print(" Device found at 0x");
if (addr < 16) Serial.print("0");
Serial.print(addr, HEX);
// Identify known addresses
switch (addr) {
case 0x27: Serial.print(" (PCF8574 LCD backpack)"); break;
case 0x3C: Serial.print(" (SSD1306 OLED)"); break;
case 0x48: Serial.print(" (Temperature sensor)"); break;
case 0x50: Serial.print(" (EEPROM)"); break;
case 0x68: Serial.print(" (DS1307 RTC)"); break;
case 0x76: Serial.print(" (BME280 sensor)"); break;
case 0x77: Serial.print(" (BMP180/BMP280)"); break;
}
Serial.println();
devicesFound++;
}
}
Serial.println();
Serial.print("Scan complete. ");
Serial.print(devicesFound);
Serial.println(" device(s) found.");
if (devicesFound == 0) {
Serial.println("No I2C devices found. Check connections.");
}
}
Разберём его по частям:
Wire.begin()— Инициализирует Arduino как I2C-мастер.Serial.begin(9600)— Запускает последовательную связь на скорости 9600 бод, чтобы мы могли видеть результаты в мониторе порта.- Цикл проходит по адресам с 1 по 126 (0x01 — 0x7E). Адрес 0 зарезервирован для общего вызова, а 127 — для специальных целей.
Wire.beginTransmission(addr)— Начинает передачу на указанный адрес.Wire.endTransmission()— Завершает передачу и возвращает код ошибки. Если ошибка равна0, это означает, что устройство подтвердило (ACK) — мы нашли устройство!- Вывод адреса — Мы выводим его в шестнадцатеричном формате с ведущим нулём для удобства чтения.
- Оператор switch — Идентифицирует распространённые устройства по их известным адресам. Это необязательно, но полезно.
- Подсчёт устройств — Мы увеличиваем
devicesFoundдля каждого ACK. - Финальный отчёт — Выводит общее количество найденных устройств.
Функция Loop
void loop() {
// Rescan every 10 seconds
delay(10000);
Serial.println("\nRescanning...");
setup();
}
Функция loop() просто ждёт 10 секунд, а затем снова вызывает setup() для повторного сканирования. Это полезно, если вы добавляете или удаляете устройства во время работы системы.
Ключевые концепции для студентов
Что такое I2C?
I2C (Inter-Integrated Circuit), также называемый TWI (Two-Wire Interface), — это синхронный последовательный протокол связи. Он использует две двунаправленные линии с открытым стоком: SDA (данные) и SCL (такт). Каждое устройство на шине имеет уникальный 7-битный адрес (хотя существуют и 10-битные адреса). Мастер (Arduino) инициирует связь и генерирует тактовый сигнал.
Как работает сканер
Сканер отправляет условие старта, за которым следует байт адреса (7-битный адрес + бит чтения/записи). Если устройство с таким адресом существует, оно отвечает ACK (подтверждением), притягивая SDA к низкому уровню во время девятого тактового импульса. Если устройство не отвечает, получается NACK (отрицательное подтверждение), и endTransmission() возвращает ненулевой код ошибки.
Зачем использовать сканер?
- Поиск неизвестных адресов — Многие I2C-устройства имеют настраиваемые адреса (например, с помощью перемычек). Сканер сообщает фактический адрес.
- Отладка подключения — Если устройство не отвечает, сканер может подтвердить, правильно ли оно подключено.
- Проверка на конфликты — Два устройства с одинаковым адресом вызовут ошибки связи. Сканер может помочь выявить дубликаты.
Распространённые ошибки и советы по отладке
- Неправильное подключение — Перепроверьте, что SDA и SCL подключены правильно. Их перестановка не сработает.
- Отсутствие подтягивающих резисторов — Линии I2C нуждаются в подтягивающих резисторах (обычно 4,7 кОм) к VCC. Многие платы расширения включают их, но если вы собираете схему с нуля, не забудьте их добавить.
- Конфликты адресов — Если два устройства имеют одинаковый адрес, ни одно не будет работать надёжно. Используйте сканер для обнаружения конфликтов.
- Несоответствие скорости передачи — Сканер использует стандартную скорость 100 кГц (стандартный режим). Некоторым устройствам может потребоваться более низкая скорость. Вы можете изменить её с помощью
Wire.setClock(400000)для быстрого режима. - Монитор порта не показывает вывод — Убедитесь, что скорость передачи в мониторе порта соответствует
9600.
В Velxio вы можете открыть монитор порта на панели инструментов редактора. Если вы не видите вывод, проверьте, успешно ли скомпилировался код (ищите ошибки в консоли).

Предлагаемые расширения
Когда базовый сканер заработает, попробуйте эти улучшения:
- Отображение результатов на OLED — Вместо вывода в монитор порта покажите список адресов на дисплее SSD1306. Вам понадобятся библиотеки
Adafruit_SSD1306иAdafruit_GFX. - Добавьте кнопку для запуска сканирования — Подключите тактовую кнопку к пину Arduino и сканируйте только при нажатии.
- Сканирование конкретных устройств — Измените код для поиска только определённого диапазона адресов (например, 0x20-0x2F для PCF8574).
- Используйте LCD — Замените OLED на 16x2 I2C LCD (адрес 0x27 или 0x3F).
- Запись на SD-карту — Если у вас есть модуль SD-карты, записывайте результаты сканирования для последующего анализа.
Чтобы добавить библиотеки в Velxio, используйте менеджер библиотек.

Заключение
Вы только что создали универсальный I2C-сканер, который работает с любой платой, совместимой с Arduino. Этот инструмент бесценен для отладки и изучения новых I2C-модулей. Самое лучшее? Вы можете запустить его прямо сейчас в своём браузере на Velxio без какого-либо оборудования.
Готовы попробовать сами? Откройте живой пример и начинайте сканирование:
👉 Запустить I2C-сканер на Velxio
Удачного хакерства!