Перейти к основному содержимому

I2C-дисплей

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

Контроллер и дисплей связаны отдельными линиями SDA, SCL, питания и земли

Коротко

Сначала проверяют питание, уровни, 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. Их нельзя подключать по физическому порядку контактов на соседнем примере: порядок на разъёме бывает разным.

  1. Узнайте допустимое питание дисплея и уровни I2C.
  2. Соедините GND дисплея с землёй Arduino.
  3. Подключите SDA к аппаратному SDA выбранной платы.
  4. Подключите SCL к аппаратному SCL.
  5. Проверьте, куда уже установлены подтягивающие резисторы.
  6. Только после проверки подайте питание.
ПроверкаНормальный смыслОпасная ошибка
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.

Перед использованием:

  1. Найдите hd44780 в Library Manager и проверьте автора.
  2. Откройте пример I2CexpDiag из установленного пакета.
  3. Запустите диагностику на одном дисплее.
  4. Сверьте число столбцов и строк вашего модуля.
  5. Только затем добавляйте вывод данных робота.

Минимальный пример для дисплея 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. Конфликт адресов

Предложите три способа использовать два одинаковых устройства с одним фиксированным адресом. Для каждого укажите требуемое оборудование или изменение конструкции.

Проверьте себя

  1. Почему ответ по I2C не доказывает, что найден именно дисплей?
  2. Чем 7-битный адрес отличается от адресного байта?
  3. Для чего нужны подтяжки SDA и SCL?
  4. Почему несколько breakout-плат меняют итоговое сопротивление подтяжки?
  5. Как контроллер дисплея влияет на выбор библиотеки?
  6. Зачем запускать диагностический пример до своего проекта?
  7. Почему не стоит выполнять lcd.clear() в каждом loop()?
  8. Что проверить, если адрес есть, а экран остаётся пустым?
Ориентиры для самопроверки

Сначала ответьте без подсказки. Ответ можно считать полным, если вы:

  • формулируете основную мысль своими словами;
  • называете важные условия, ограничения или меры безопасности;
  • для схемы, кода или расчёта показываете ход решения и ожидаемый результат.

Если один из пунктов объяснить не получается, найдите соответствующую главу статьи, перечитайте её и повторите ответ.

Словарь статьи

  • I2C-дисплей — дисплейный модуль, принимающий команды через адресную двухпроводную шину.
  • SDA — двунаправленная линия данных I2C.
  • SCL — линия тактового сигнала I2C.
  • ACK — подтверждение приёма адреса или байта участником шины.
  • 7-битный адрес — значение, выбирающее обычное периферийное устройство I2C.
  • Backpack — переходная плата, связывающая интерфейс I2C с контактами дисплея.
  • Контроллер дисплея — микросхема, интерпретирующая команды и управляющая символами или пикселями.
  • Сканер адресов — диагностический скетч, проверяющий наличие ACK.
  • Контраст — различимость символов и фона у LCD.

Связанные темы

Источники