Назад

I2C-сканер с Arduino: найдите каждое устройство на шине

Введение

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

В этом руководстве мы создадим I2C-сканер с использованием Arduino Uno и OLED-дисплея SSD1306 (который также послужит известным устройством на шине). Мы запустим всё в браузерном симуляторе Velxio, так что вам не понадобится никакое оборудование. К концу вы поймёте, как работает шина I2C, как подключать устройства и как писать код для их сканирования.

Давайте начнём!

Схема подключения

Схема i2c-сканера на холсте симулятора Velxio

Схема удивительно проста. Нам понадобятся всего два компонента:

Детали подключения

Подключите OLED к Arduino с помощью четырёх проводов:

Пин ArduinoПин OLEDЦвет провода
A4 (SDA)DATAСиний
A5 (SCL)CLKОранжевый
GNDGNDЧёрный
5VVINКрасный

Примечание: На Arduino Uno A4 и A5 — это выделенные пины I2C. На других платах могут использоваться другие пины (например, SDA/SCL на ESP32).

В симуляторе Velxio вы можете добавить OLED из палитры компонентов и подключить его, щёлкая по пинам. Панель инструментов холста помогает увеличивать и перемещать изображение для удобства подключения.

Панель инструментов холста Velxio над окном симуляции

Разбор кода

Исходный код i2c-сканера в редакторе Monaco от Velxio

Теперь давайте посмотрим на код. Откройте редактор кода в 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.");
  }
}

Разберём его по частям:

  1. Wire.begin() — Инициализирует Arduino как I2C-мастер.
  2. Serial.begin(9600) — Запускает последовательную связь на скорости 9600 бод, чтобы мы могли видеть результаты в мониторе порта.
  3. Цикл проходит по адресам с 1 по 126 (0x01 — 0x7E). Адрес 0 зарезервирован для общего вызова, а 127 — для специальных целей.
  4. Wire.beginTransmission(addr) — Начинает передачу на указанный адрес.
  5. Wire.endTransmission() — Завершает передачу и возвращает код ошибки. Если ошибка равна 0, это означает, что устройство подтвердило (ACK) — мы нашли устройство!
  6. Вывод адреса — Мы выводим его в шестнадцатеричном формате с ведущим нулём для удобства чтения.
  7. Оператор switch — Идентифицирует распространённые устройства по их известным адресам. Это необязательно, но полезно.
  8. Подсчёт устройств — Мы увеличиваем devicesFound для каждого ACK.
  9. Финальный отчёт — Выводит общее количество найденных устройств.

Функция 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() возвращает ненулевой код ошибки.

Зачем использовать сканер?

Распространённые ошибки и советы по отладке

  1. Неправильное подключение — Перепроверьте, что SDA и SCL подключены правильно. Их перестановка не сработает.
  2. Отсутствие подтягивающих резисторов — Линии I2C нуждаются в подтягивающих резисторах (обычно 4,7 кОм) к VCC. Многие платы расширения включают их, но если вы собираете схему с нуля, не забудьте их добавить.
  3. Конфликты адресов — Если два устройства имеют одинаковый адрес, ни одно не будет работать надёжно. Используйте сканер для обнаружения конфликтов.
  4. Несоответствие скорости передачи — Сканер использует стандартную скорость 100 кГц (стандартный режим). Некоторым устройствам может потребоваться более низкая скорость. Вы можете изменить её с помощью Wire.setClock(400000) для быстрого режима.
  5. Монитор порта не показывает вывод — Убедитесь, что скорость передачи в мониторе порта соответствует 9600.

В Velxio вы можете открыть монитор порта на панели инструментов редактора. Если вы не видите вывод, проверьте, успешно ли скомпилировался код (ищите ошибки в консоли).

Панель инструментов редактора Velxio с кнопками компиляции и запуска

Предлагаемые расширения

Когда базовый сканер заработает, попробуйте эти улучшения:

Чтобы добавить библиотеки в Velxio, используйте менеджер библиотек.

Модальное окно менеджера библиотек Velxio со списком установленных библиотек Arduino

Заключение

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

Готовы попробовать сами? Откройте живой пример и начинайте сканирование:

👉 Запустить I2C-сканер на Velxio

Удачного хакерства!


Поделиться:
David Montero

Автор

David Montero

Creator of Velxio, the open-source circuit and Arduino simulator.

GitHub velxio.dev

Похожие статьи


Предыдущая статья
Часы реального времени I2C с DS1307 на Velxio
Следующая статья
Последовательное управление светодиодом с помощью Arduino: отправка команд для мигания