I2C-дисплей
Дисплей превращает внутреннее состояние робота в понятную информацию: показывает расстояние, режим движения, заряд или код ошибки. Подключение по I2C экономит пины, потому что несколько устройств могут использовать общие линии SDA и SCL. Однако слова «I2C-дисплей» недостаточно для выбора библиотеки: нужно определить контроллер экрана, адрес и схему переходной платы.

Сначала проверяют питание, уровни, SDA/SCL, подтяжки и адрес. Затем выбирают библиотеку именно для контроллера дисплея и его I2C-адаптера. Сканер адресов показывает, что кто-то подтвердил адрес, но не определяет модель устройства и не заменяет datasheet.
Зачем это нужно
Без экрана отладка часто зависит от компьютера и Serial Monitor. На автономном роботе дисплей позволяет увидеть состояние прямо на корпусе:
- найден ли датчик при запуске;
- какое значение получено сейчас;
- какой режим выбран кнопкой;
- почему привод остановлен;
- проходит ли калибровка;
- какое устройство не отвечает на шине.
I2C особенно удобен, когда SDA и SCL уже используются датчиками: дисплей подключается к тем же двум шинам, если адреса не конфликтуют и электрическая нагрузка остаётся допустимой.
Главная идея
У задачи есть два независимых слоя:
I2C доставляет байты по адресу
контроллер дисплея превращает команды в символы или пиксели
Wire отвечает за транзакции I2C. Библиотека дисплея знает команды конкретного контроллера и способ, которым I2C-адаптер подключён к его выводам. Успешный ответ по адресу подтверждает только первый слой.

Какие дисплеи скрываются за одним названием
| Вариант | Что находится на модуле | Какая библиотека нужна |
|---|---|---|
| символьный LCD 16×2 или 20×4 с backpack | контроллер семейства HD44780 и I/O-расширитель, часто PCF8574-совместимый | библиотека для HD44780 и конкретного I2C-адаптера |
| небольшой монохромный OLED | графический контроллер, например SSD1306-совместимый | графическая библиотека для этого контроллера |
| цветной графический дисплей | собственный контроллер, иногда I2C только для части функций | библиотека, совпадающая с контроллером и интерфейсом |
| «безымянный I2C LCD» | маркировка продавца без полной схемы | сначала идентификация микросхем и распиновки |
Код lcd.begin(16, 2) относится к геометрии символьного дисплея. Он не подойдёт графическому OLED. Метод setCursor() может встречаться в разных пакетах, но его параметры и система координат всё равно требуют документации.
Подключение четырёх линий
Типичный модуль имеет VCC, GND, SDA и SCL. Их нельзя подключать по физическому порядку контактов на соседнем примере: порядок на разъёме бывает разным.
- Узнайте допустимое питание дисплея и уровни I2C.
- Соедините
GNDдисплея с землёй Arduino. - Подключите
SDAк аппаратномуSDAвыбранной платы. - Подключите
SCLк аппаратномуSCL. - Проверьте, куда уже установлены подтягивающие резисторы.
- Только после проверки подайте питание.
| Проверка | Нормальный смысл | Опасная ошибка |
|---|---|---|
VCC | напряжение из спецификации модуля | питание выше допустимого |
GND | общая точка отсчёта | забытая общая земля |
SDA | двунаправленные данные | перепутан с питанием или SCL |
SCL | тактовая линия контроллера | перепутан с SDA |
| подтяжки | поднимают открытые линии к разрешённому уровню | подтяжка к слишком высокому напряжению |
На многих breakout-платах подтяжки уже распаяны. Несколько модулей соединяют резисторы параллельно, поэтому итоговое сопротивление меняется. Удалять или добавлять их наугад не следует: расчёт зависит от ёмкости шины, скорости, напряжения и требований устройств.
Адрес I2C
Адрес — 7-битное число, по которому контроллер выбирает периферию. На I2C-backpack символьного LCD часть адреса иногда задают перемычки. OLED-модуль может предлагать два варианта через контакт конфигурации.
Документация встречается в двух формах:
- 7-битный адрес, который обычно передают
Wire; - адресный байт, где младший бит уже обозначает чтение или запись.
Если бездумно копировать вторую форму, адрес окажется сдвинут. Сверьте формулировку datasheet и пример той же библиотеки.
Некоторые диапазоны I2C зарезервированы спецификацией. Учебный сканер ниже опрашивает обычный 7-битный диапазон 0x08…0x77, не используя края адресного пространства как адреса периферии.
Безопасный сканер шины
Wire.endTransmission() возвращает код результата. Ноль означает, что адрес был подтверждён сигналом ACK. Это не доказательство, что найден именно дисплей.
#include <Wire.h>
void scanBus() {
uint8_t found = 0;
for (uint8_t address = 0x08; address <= 0x77; ++address) {
Wire.beginTransmission(address);
const uint8_t error = Wire.endTransmission();
if (error == 0) {
Serial.print("I2C device at 0x");
if (address < 0x10) {
Serial.print('0');
}
Serial.println(address, HEX);
++found;
}
}
Serial.print("Devices found: ");
Serial.println(found);
}
void setup() {
Serial.begin(115200);
Wire.begin();
scanBus();
}
void loop() {}
Сканирование само по себе является обменом на шине. Для большинства простых модулей нулевая передача используется как диагностический приём, но перед сканированием незнакомой системы нужно проверить, нет ли у устройства особых реакций на такой запрос.
Если адресов нет, причина обычно находится ниже уровня библиотеки дисплея: питание, земля, перепутанные линии, неверные пины платы, уровни, отсутствующие или слишком сильные подтяжки. Если найдено несколько адресов, отключайте модули по одному, чтобы сопоставить ответ физическому устройству.
Выбираем библиотеку для символьного LCD
Для учебного примера возьмём пакет hd44780 Билла Перри и класс hd44780_I2Cexp. Он предназначен для распространённых I2C-адаптеров символьных дисплеев и умеет определять адрес и соответствие выводов у поддерживаемых backpack. Это конкретный выбор, а не универсальный заголовок для любого LCD.
Перед использованием:
- Найдите
hd44780в Library Manager и проверьте автора. - Откройте пример
I2CexpDiagиз установленного пакета. - Запустите диагностику на одном дисплее.
- Сверьте число столбцов и строк вашего модуля.
- Только затем добавляйте вывод данных робота.
Минимальный пример для дисплея 16×2:
#include <Wire.h>
#include <hd44780.h>
#include <hd44780ioClass/hd44780_I2Cexp.h>
hd44780_I2Cexp lcd;
const uint8_t columns = 16;
const uint8_t rows = 2;
void setup() {
const int status = lcd.begin(columns, rows);
if (status != 0) {
hd44780::fatalError(status);
}
lcd.print("Robot ready");
}
void loop() {}
Если установлен другой пакет с названием вроде LiquidCrystal_I2C, конструктор и начальные методы могут отличаться. Нельзя менять #include и ожидать, что остальной код останется совместимым.
Выводим изменяющееся значение
Постоянный вызов lcd.clear() в каждом проходе loop() приводит к лишнему обмену и заметному мерцанию. Лучше обновлять экран с ограниченной частотой и перезаписывать только нужное поле. В предыдущем полном скетче замените пустую функцию loop() приведённой ниже реализацией и добавьте переменные с функцией updateScreen(); второй loop() рядом с первым создавать нельзя.
// Добавьте этот блок к предыдущему скетчу, заменив его пустой loop().
unsigned long lastScreenUpdate = 0;
int distanceCm = 0;
void updateScreen() {
lcd.setCursor(0, 1);
lcd.print("Distance: ");
lcd.print(distanceCm);
lcd.print(" ");
}
void loop() {
const unsigned long now = millis();
if (now - lastScreenUpdate >= 200) {
lastScreenUpdate = now;
updateScreen();
}
}
Пробелы после числа стирают остаток предыдущего более длинного значения. Строка должна помещаться в доступное число столбцов. Для кириллицы символьный LCD может не иметь нужных символов в таблице знакогенератора; поддержка зависит от ROM контроллера и библиотеки.
Пример: экран состояния робота
Экран полезнее, если показывает решение, а не поток необработанных значений. Для мобильного робота можно распределить две строки:
| Строка | Содержимое | Когда обновлять |
|---|---|---|
| верхняя | режим: ожидание, движение, ошибка | при смене состояния |
| нижняя | расстояние или заряд | с ограниченной частотой |
Если датчик временно не отвечает, не оставляйте старое число как будто оно актуально. Выведите короткий признак ошибки и сохраните код причины в Serial. Дисплей не должен блокировать главный цикл долгими задержками.
Несколько устройств на одной шине
Дисплей и датчик могут использовать Wire одновременно. Условия совместной работы:
- уникальные 7-битные адреса;
- общие допустимые уровни напряжения;
- суммарные подтяжки в допустимом диапазоне;
- скорость, поддерживаемая самым требовательным устройством;
- достаточно короткие и аккуратные соединения;
- библиотеки не меняют шину несовместимым способом.
При конфликте одинаковых адресов программа не может выбрать один из двух узлов. Решением может быть аппаратная перемычка адреса, I2C-мультиплексор или замена устройства, но не повторный вызов Wire.begin().
Диагностика по симптомам
| Симптом | Следующий осмысленный шаг |
|---|---|
| сканер не находит адрес | проверить питание, GND, SDA/SCL, pinout и уровни |
| адрес есть, экран пуст | проверить библиотеку, контроллер, геометрию и контраст LCD |
| случайные символы | проверить соответствие backpack, питание и устойчивость шины |
| экран работает один, но не с датчиком | проверить конфликт адресов и суммарные подтяжки |
| значения мерцают | убрать clear() из быстрого цикла, реже обновлять |
| проект не компилируется | сверить точное имя и API установленной библиотеки |
Контраст символьного LCD часто регулируется подстроечным резистором на backpack. Белые прямоугольники или полностью пустое поле могут иметь разные причины, поэтому сначала отделяют наличие I2C-ответа от настройки самого экрана.
Что запомнить про I2C-дисплей
- I2C и команды контроллера дисплея — разные уровни.
SDAиSCLподключают параллельно и подтягивают к безопасному напряжению.- Сканер находит подтверждённый адрес, но не определяет модель.
- Зарезервированные адреса нельзя произвольно назначать периферии.
- Библиотеку выбирают по контроллеру и адаптеру, а API сверяют с установленной версией.
- Экран обновляют не быстрее, чем нужно человеку, и без постоянного
clear().
Практика
Задание 1. Паспорт модуля
Изучите маркировку дисплея и адаптера. Найдите контроллер, питание, допустимые логические уровни, варианты адреса и рекомендованную библиотеку. Если сведения не подтверждены, пометьте их как неизвестные.
Задание 2. Сканирование
Соберите схему с одним I2C-устройством и запустите сканер. Запишите адрес. Затем отключите питание, добавьте второе устройство и сравните результаты. Не переставляйте провода под напряжением.
Задание 3. Экран состояния
Спроектируйте две строки для робота с датчиком расстояния. Первая должна показывать режим, вторая — значение или ошибку. Ограничьте частоту обновления через millis().
Задание 4. Конфликт адресов
Предложите три способа использовать два одинаковых устройства с одним фиксированным адресом. Для каждого укажите требуемое оборудование или изменение конструкции.
Проверьте себя
- Почему ответ по I2C не доказывает, что найден именно дисплей?
- Чем 7-битный адрес отличается от адресного байта?
- Для чего нужны подтяжки
SDAиSCL? - Почему несколько breakout-плат меняют итоговое сопротивление подтяжки?
- Как контроллер дисплея влияет на выбор библиотеки?
- Зачем запускать диагностический пример до своего проекта?
- Почему не стоит выполнять
lcd.clear()в каждомloop()? - Что проверить, если адрес есть, а экран остаётся пустым?
Сначала ответьте без подсказки. Ответ можно считать полным, если вы:
- формулируете основную мысль своими словами;
- называете важные условия, ограничения или меры безопасности;
- для схемы, кода или расчёта показываете ход решения и ожидаемый результат.
Если один из пунктов объяснить не получается, найдите соответствующую главу статьи, перечитайте её и повторите ответ.
Словарь статьи
- I2C-дисплей — дисплейный модуль, принимающий команды через адресную двухпроводную шину.
- SDA — двунаправленная линия данных I2C.
- SCL — линия тактового сигнала I2C.
- ACK — подтверждение приёма адреса или байта участником шины.
- 7-битный адрес — значение, выбирающее обычное периферийное устройство I2C.
- Backpack — переходная плата, связывающая интерфейс I2C с контактами дисплея.
- Контроллер дисплея — микросхема, интерпретирующая команды и управляющая символами или пикселями.
- Сканер адресов — диагностический скетч, проверяющий наличие ACK.
- Контраст — различимость символов и фона у LCD.
Связанные темы
- Протоколы обмена данными — устройство общей I2C-шины.
- Библиотеки Arduino — выбор пакета и чтение его API.
- analogRead: обработка датчика — подготовка значения для вывода.
- Монитор порта Serial — независимый канал диагностики дисплея.