Гаражный термометр с LCD 16x2 я питал от четырёх щелочных батареек АА и искренне рассчитывал на пару месяцев. Посчитать в уме я почему-то поленился, а цифры говорят сами: ёмкость приличной АА — около 2000–2500 мА·ч, дисплей с включённой подсветкой брал на своём модуле 22–25 мА при 5 В. Делим 2000 на 23 — выходит часа восемьдесят семь. Трое с половиной суток, ровно столько моя сборка и прожила. При этом сама панель, если верить замерам, ела смешные 1–2 мА: девяносто процентов бюджета улетало в светодиоды подсветки за стеклом, которые светили в пустой гараж круглые сутки.
В этом уроке посчитаем, что именно и сколько жрёт в дисплейном узле, разберём пары команд backlight()/noBacklight() и display()/noDisplay() — они делают принципиально разные вещи, — и соберём приличную механику сна: экран гаснет через десять секунд бездействия и просыпается от нажатия, как экран телефона. Попутно проверим цифры на своём модуле мультиметром и решим, когда оправдано полное отключение питания. Если вы ещё не считали бюджет тока для своих сборок, полезно держать под рукой урок про бюджет тока проекта — там та же арифметика для всей макетки.
Подсветка — это просто светодиод. Но какой прожорливый
Подсветка символьного LCD — это пара светодиодов за стеклом, выведенных на крайние контакты с маркировкой A (анод) и K (катод). Ток им ограничивает резистор, распаянный на большинстве готовых модулей, поэтому подключение к 5 В напрямую — штатный режим. На переходниках I2C между битом шины и анодом стоит транзистор: библиотека дёргает один бит в пакете, транзистор подключает или отключает анод. Из скетча это выглядит как пара команд: lcd.backlight() зажигает, lcd.noBacklight() гасит. Никакой магии, никакой записи в память контроллера — свет просто физически отсекается от питания.
Отсюда приятное следствие: после noBacklight() дисплей продолжает жить полной жизнью — текст остаётся в памяти, данные принимаются, счётчики тикают. Проверка на столе, которую я делаю на каждом втором собранном экране: гасим подсветку и подносим фонарик под острым углом к стеклу — буквы на месте, просто теперь их видно только с подсветкой со стороны. Ночью на улице я этим пользовался наоборот: подсветка включалась на пять секунд по нажатию, а в остальное время показания читались от луны. Для батареек это лучший из миров: данные не теряются, ток падает в разы, а код состоит из одной команды в нужном месте.
Теперь числа с условиями, потому что «прожорливость» зависит от модуля. Синий 16x2 с резистором на плате — типичные 20–25 мА при 5 В; зелёные панели бывают в два раза скромнее, 10–15 мА; а вот модули без ограничивающего резистора (их отличает надпись BL без номинала на плате) способны потреблять за сотню миллиампер, и резистор для них обязателен — иначе сгорают светодиоды, а заодно и бюджет. Сравните: логика HD44780, чип PCF8574 и подтяжки вместе взятые — единицы миллиампер. Любая экономия в дисплейном узле начинается и заканчивается подсветкой.
| Потребитель | Типичный ток | Комментарий |
|---|---|---|
| Подсветка модуля 16x2 | 20–25 мА | Главный едок; гасится noBacklight() без потери текста |
| Логика HD44780 | 1–2 мА | Жива, пока на дисплей поданы 5 В, командами не отключается |
| Чип PCF8574 на переходнике | меньше 1 мА | На фоне подсветки не виден |
| Плата Uno целиком | 45–50 мА | Если питаете от батареек, дисплей — лишь половина проблемы |
#include <Wire.h>#include <LiquidCrystal_I2C.h> LiquidCrystal_I2C lcd(0x27, 16, 2);const int btnPin = 2;unsigned long lastActivity = 0; void setup() { pinMode(btnPin, INPUT_PULLUP); lcd.init(); lcd.backlight(); lastActivity = millis();} void loop() { if (digitalRead(btnPin) == LOW) { lastActivity = millis(); // любое нажатие — признак жизни lcd.backlight(); // и будим экран, если уснул } if (millis() - lastActivity > 10000UL) { // 10 секунд тишины lcd.noBacklight(); } delay(50);}С подсветкой разобрались, теперь пара display()/noDisplay(), которую путают с выключением. noDisplay() отправляет контроллеру команду «погасить отображение»: символы исчезают с экрана, но их коды продолжают лежать в DDRAM — той самой памяти знакомест, о которой шла речь в разборе внутренностей HD44780. Позиция курсора тоже сохраняется. lcd.display() возвращает картинку на место один в один — я проверял на сборках с таймером: текст и место, где стоял курсор, не сдвигаются ни на символ. Экономия же от этой команды копеечная: контроллер продолжает тактировать и питаться, выключается только вывод на стекло. Гасить noDisplay() ради батареек — всё равно что закрывать шторы, не выключив свет в комнате. Впрочем, у команды есть честная работа по профилю: спрятать экран на время загрузки, пока показания ещё считаются, и показать их разом, готовым пакетом, — для этого noDisplay/display подходят идеально.
Настоящий сон дисплейного узла — снять питание целиком: тогда ноль потребляет и панель, и переходник. На макетке это делается мосфетом на разрыв плюсового провода — мы собирали такой ключ в уроке про мосфет IRF520. Минус подхода: при подаче питания дисплей проходит инициализацию заново, а скетч обязан после включения повторить lcd.init() и перерисовать экран. Ради 1–2 мА эта возня того не стоит — она имеет смысл, когда вы отрезаете питание всему проекту, а не только дисплею.
Перемножим гаражную историю в цифры, которые стыдно забывать. Подсветка в 23 мА за сутки съедает 23 × 24 ≈ 550 мА·ч — почти полторы батарейки АА в день только на свет. За месяц — больше сорока батареек, дороже самого дисплея. Те же сутки без подсветки стоят около 80 мА·ч — чуть больше трёх процентов одной АА. Никакая оптимизация кода и никакой noDisplay() не дадут перепада в двадцать раз; поэтому в любой дисплейной сборке на батарейках я сначала ставлю автосон подсветки, и только потом смотрю на остальное.
Тренажёр: экран гаснет, как экран телефона
Соберём механику сна целиком. Кнопка на D2 — источник активности: каждое нажатие передвигает таймер и будит экран. Тумблер на D3 включает ночной режим: только когда он замкнут, бездействие ведёт к засыпанию — так удобно сравнивать оба поведения в одном запуске, не перезаливая скетч. Светодиод на D12 повторяет состояние подсветки: горит, пока экран не спит. Движок симулятора честно отрабатывает noBacklight() — виртуальный LCD тускнеет прямо на макетке, разница видна без всяких измерений.
Сценарий проверки: включите ночной режим, не трогайте ничего пять виртуальных секунд — экран уснёт, светодиод погаснет. Нажмите кнопку — всё оживёт. Выключите тумблер — теперь сколько ни жди, экран не уснёт. Тот же скетч на реальном железе работает без изменений: пины честные, команды библиотеки честные.
Отдельно про плавную яркость, потому что вопрос всплывает в каждой второй сборке. На I2C-переходнике подсветка управляется одним битом — вкл/выкл, промежуточных значений у него нет. Полутон получают быстрым миганием из скетча: переключать бит с интервалом 5–10 миллисекунд, и глаз увидит ровное свечение в полсилы. Работает, но скетч вынужден постоянно этим заниматься, а на фоне delay() в loop() появляется заметное мерцание. Моё мнение с границей: для экономии батареек диммирование не нужно — разница между «тускло» и «выкл» в десятках миллиампер всё равно упирается в полный выключатель; плавная яркость имеет смысл, только когда дисплей питается через транзистор с ШИМ-пином или мосфет, и хочется красоты в ночном режиме. Дешевле и надёжнее проектировать экран так, чтобы он читался при полном включении, а вместо полутонов управлять моментом показа.
И последняя цифра для полноты картины: сама Uno с USB-чипом и стабилизатором берёт 45–50 мА независимо от дисплея. Поэтому серьёзные батареечные сборки уходят от Uno к Nano или вообще в глубокий сон контроллера — но это уже сюжет для урока про watchdog и сон. Дисплейная часть после сегодняшнего умеет главное: не жечь двадцать миллиампер в пустоту.
Если цифры из таблицы хочется проверить на своём модуле — и правильно хочется, — берите мультиметр в режим миллиампер и включайте его в разрыв плюсового провода дисплея: схема измерения разобрана в уроке про мультиметр. Ожидаю у вас 15–25 мА с горящей подсветкой и 1–4 мА после lcd.noBacklight(). Только начинайте с режима измерения тока, а не напряжения: в режиме вольтметра в разрыве вы просто отключите дисплей, а в режиме амперметра напрямую на 5 В — сожжёте предохранитель мультиметра. Оба пути я уже протоптал, второй — дважды.
- Измерьте ток своего модуля мультиметром в разрыве питания при включённой и выключенной подсветке — разница и есть ваш реальный выигрыш в миллиамперах.
- Уменьшите таймаут в тренажёре с 5000 до 2000 миллисекунд и проверьте, что засыпание отследили обе ветки: с включённым и выключенным тумблером.
- Добавьте в скетч подсчёт, сколько секунд экран провёл во сне, и выведите это число на вторую строку при пробуждении.
- Замените кнопку в тренажёре на PIR-датчик (компонент тоже садится на D2): ночник, который будится от движения, собирается из этого же скетча.
- Подсветка — обычные светодиоды A/K: на типовом синем модуле 20–25 мА при 5 В, и это главный потребитель дисплейного узла
- lcd.noBacklight() гасит свет, но текст и инициализация остаются; lcd.backlight() возвращает подсветку одной командой
- lcd.noDisplay() лишь прячет символы: DDRAM и курсор сохраняются, экономия — доли миллиампера
- Автосон по таймеру бездействия строится на millis() и двух переменных; будить можно кнопкой, PIR или любым событием
- Полное отключение питания дисплея имеет смысл только в связке со сном всего проекта: 1–2 мА логики не стоят повторной инициализации
- 1. Сколько примерно берёт подсветка типового синего модуля 16x2 при 5 В?
- 2. Что делает lcd.noDisplay()?
- 3. Какая мера даёт максимальную экономию в дисплейном узле на батарейках?
- 4. Почему noDisplay() почти не экономит ток?
- 5. Как в тренажёре работает засыпание экрана?
Частые вопросы по теме урока
- Сколько примерно берёт подсветка типового синего модуля 16x2 при 5 В?
- Светодиоды подсветки с штатным резистором берут 20–25 мА — это на порядок больше всей остальной электроники модуля вместе взятой. 20–25 мА
- Что делает lcd.noDisplay()?
- Команда гасит вывод на стекло, но коды символов и позиция курсора остаются в памяти: lcd.display() возвращает картинку без изменений. Прячет символы, сохраняя их в памяти
- Какая мера даёт максимальную экономию в дисплейном узле на батарейках?
- Только отсечение светодиодов экономит десятки миллиампер. Остальные меры влияют на доли миллиампера или вообще на ток не влияют. Гасить подсветку по таймеру бездействия
- Почему noDisplay() почти не экономит ток?
- Выключается только вывод на стекло, а вся логика панели живёт и ест свои 1–2 мА. Реальный сон даёт лишь снятие питания. Контроллер продолжает тактировать и питаться
- Как в тренажёре работает засыпание экрана?
- Тумблер включает ночной режим, и только после пяти секунд без нажатий скетч гасит подсветку. Кнопка будит экран и сбрасывает таймер. По таймеру бездействия, только в ночном режиме