LCD1602: два способа подключения
Символьный дисплей 1602 (16 символов × 2 строки) — классика для вывода данных. Изначально у него 16 ног и подключение идёт параллельной шиной: 6-8 проводов данных + управление = почти все пины Arduino заняты.
Решение — I2C-модуль PCF8574 на обратной стороне: вместо десятка проводов всего четыре — VCC, GND, SDA, SCL. Купите дисплей с припаянным модулем — разницы в цене почти нет.
Arduino A4 (SDA) ── SDA
Arduino A5 (SCL) ── SCL
5V ── VCC
GND ── GND
Библиотека и первый текст
Ставим «LiquidCrystal I2C» (автор marcoschwartz или Frank de Brabander — обе работают):
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2); // адрес 0x27 или 0x3F — см. ниже
void setup() {
lcd.init();
lcd.backlight();
lcd.setCursor(0, 0);
lcd.print("Hello, LCD!");
lcd.setCursor(0, 1);
lcd.print("строка 2");
}
Адрес модуля бывает 0x27 или 0x3F — если дисплей не отвечает, попробуйте другой. Для поиска есть скетч I2C-сканера.
Курсор и управление
lcd.setCursor(5, 1); // колонка 5, строка 1 (нумерация с 0)
lcd.print("x");
lcd.clear(); // очистка всего
lcd.home(); // курсор в 0,0
lcd.cursor(); // показать курсор
lcd.noCursor(); // скрыть
lcd.blink(); // мигающий курсор
lcd.noBlink();
lcd.noBacklight(); // выключить подсветку
lcd.display(); / lcd.noDisplay(); // экран вкл/выкл без очистки
Печать данных: lcd.print принимает строки, числа, float с заданием знаков:
float t = 23.456;
lcd.print(t, 1); // "23.5" — один знак после точки
lcd.print(42); // целые
lcd.print("text");
Свои символы и русские буквы
У LCD1602 до 8 кастомных символов в памяти CGRAM (коды 0–7). Каждый — битовая маска 5×8:
byte bell[8] = {
0b00100,
0b01110,
0b01110,
0b01110,
0b11111,
0b00000,
0b00100,
0b00000
};
void setup() {
lcd.createChar(0, bell); // символ 0
lcd.write(0); // напечатать символ 0
}
Русские буквы: знакогенератор дисплея содержит кириллицу (HD44780 A00-прошивки), но кодировка не совпадает с UTF-8 — нужна перекодировка. Готовые библиотеки вроде LiquidCrystal_I2C с поддержкой кириллицы или lcdRus решают это; в простых проектах пишут транслитом или английским.
Проект: вывод данных DHT22
Типичное применение — показания датчика:
#include <DHT.h>
#include <LiquidCrystal_I2C.h>
DHT dht(2, DHT22);
LiquidCrystal_I2C lcd(0x27, 16, 2);
void setup() {
dht.begin();
lcd.init();
lcd.backlight();
}
void loop() {
float t = dht.readTemperature();
float h = dht.readHumidity();
if (!isnan(t) && !isnan(h)) {
lcd.setCursor(0, 0);
lcd.print("Temp: " + String(t, 1) + "C ");
lcd.setCursor(0, 1);
lcd.print("Hum: " + String(h, 0) + "% ");
}
delay(2000);
}
Пробелы в конце строки затирают старые длинные значения — иначе «25» на «8» оставит «8 ».
Поиск адреса I2C
Не знаете адрес модуля — сканируйте шину:
#include <Wire.h>
void setup() {
Wire.begin();
Serial.begin(9600);
for (byte i = 8; i < 120; i++) {
Wire.beginTransmission(i);
if (Wire.endTransmission() == 0) {
Serial.print("найден: 0x"); Serial.println(i, HEX);
}
}
}
void loop() {}
Типичные проблемы
- Пустые квадраты вместо текста: крутите потенциометр контраста на I2C-модуле (маленький синий винтик).
- Ничего не горит: проверьте питание, адрес (0x27/0x3F) и не перепутаны ли SDA/SCL.
- Крякозябры: кириллица требует перекодировки или английский текст.
- Дисплей работает, но текст не виден: забыт
lcd.backlight()или контраст на минимуме. - Мусор при перезаписи: строки разной длины — добивайте пробелами или
lcd.clear().
Итог
LCD1602 через I2C — это 4 провода и lcd.print. Держите в уме три момента: адрес 0x27 или 0x3F, потенциометр контраста для «чёрных квадратов», перекодировка для кириллицы. Дальше — меню на кнопках, вывод с датчиков, простые анимации кастомными символами.
Полный пример: живое обновление показаний
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2); // адрес 0x27, 16x2
void setup() {
lcd.init();
lcd.backlight();
lcd.setCursor(0, 0);
lcd.print("Smartep");
}
void loop() {
float t = dht.readTemperature();
lcd.setCursor(0, 1);
lcd.print("T=");
lcd.print(t, 1);
lcd.print((char)223); // символ градуса
lcd.print("C "); // пробелы — стирают хвост старого значения
delay(2000);
}
Важно: lcd.print не стирает строку — печатайте пробелы хвостом или используйте lcd.clear() (мигает). Лучше — всегда писать значения фиксированной ширины.
Вывод «температура → шкала»
Вторая строка — шкала из блоков:
int bars = map(t * 10, 0, 400, 0, 16); // 0..16 блоков при 0..40°C
lcd.setCursor(0, 1);
for (int i = 0; i < 16; ++i)
lcd.write(i < bars ? 0xFF : ' ');
Создание своего символа
LCD1602 поддерживает 8 пользовательских символов — 5×8 пикселей каждый:
byte deg[8] = {0b01100, 0b10010, 0b10010, 0b01100,
0b00000, 0b00000, 0b00000, 0b00000};
lcd.createChar(0, deg);
lcd.write(0); // выводит символ градуса
Онлайн-генераторы символов LCD (вроде maxpromer.github.io/LCD-Character-Creator) рисуют символы мышкой и выдают готовый массив.
Бегущая строка
lcd.setCursor(0, 0);
lcd.print(" ");
lcd.scrollDisplayLeft(); // сдвиг на одну позицию
delay(300);
В цикле — классическая «бегущая строка» с текстом больше 16 символов.
Управление подсветкой и контрастом
lcd.backlight() / lcd.noBacklight() — программное управление. Контраст — подстроечный резистор на модуле I2C. При подключении без I2C-расширителя — потенциометр на ногу V0 дисплея.
Частые проблемы и решения
- Пустые квадраты: дисплей получает питание, но данных нет — неверный I2C-адрес (проверьте сканером), перепутаны SDA/SCL.
- Иероглифы: написали быстрее чем дисплей успел — добавьте delay после init или обновляйте реже.
- Мигает/тускло: просадка питания — отдельный 5V для дисплея, конденсатор.
- Печать поверх старого:
printне стирает — печатайте пробелы хвостом.
Полный пример: меню на LCD
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
const char* items[] = {"Настройки", "Яркость", "Таймер", "Выход"};
int pos = 0;
void show() {
lcd.clear();
lcd.print(">");
lcd.print(items[pos]);
lcd.setCursor(0, 1);
lcd.print(items[(pos + 1) % 4]);
}
void loop() {
if (encoderDelta()) {
pos = (pos + encoderDelta() + 4) % 4;
show();
}
if (buttonPressed()) {
// выбор пункта
}
}
Создание своего символа
byte deg[8] = {0b01100, 0b10010, 0b10010, 0b01100,
0b00000, 0b00000, 0b00000, 0b00000};
lcd.createChar(0, deg);
lcd.write(0); // выводит символ градуса
Альтернативы
- OLED SSD1306 — 128×64, графика, I2C, дороже.
- TFT ILI9341 — цветной, 240×320, SPI, ещё дороже.
- 7-сегментный — только цифры, ярче, дешевле.