Создание e-ink дисплея с прогнозом погоды

в 8:04, , рубрики: Без рубрики

Кому-то нравится украшать дом фоторамками, а кому-то — цифровым прогнозом погоды. Если вы из числа последних, то читайте, как собрать своё собственное метеотабло.

Создание e-ink дисплея с прогнозом погоды - 1

Что мы хотим узнать, выходя из квартиры? Правильно, стоит ли взять куртку потеплее? Намотать шарф, или и так сойдёт? Захватить ли зонт? Каждый раз лезть в телефон (который ещё найти надо!) не очень удобно. Уличный термометр тоже есть не у всех, да и привирает он часто.

Я решил сделать метеорологический дисплей с электронными чернилами и питанием от батареи. После изучения вопроса я определил для себя несколько целей: 

  • Наглядный прогноз погоды, который можно расположить на видном месте. Избавляет от необходимости искать телефон.

  • Выглядит как коммерческое изделие, а не детская поделка. Должен вписываться в интерьер.

  • Работает на батарейке. Не хотелось бы, чтобы из прибора торчал кабель, а замуровать его в стену не получится.

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

  • Должен подходить, в первую очередь, для меня, но иметь возможность настройки под других. Например, опцию смены пользовательского местоположения и часового пояса. Конечный результат в итоге привязан к Финляндии из-за использования API Финского метеорологического института, но я предусмотрел и другие варианты.

Поставленные цели сопряжены с проблемами:

  • Время автономной работы ограничено. К счастью, дисплеи с электронными чернилами обладают интересным свойством: изображение остаётся видимым, даже если все кабели отключены. Для сохранения изображения не требуется никакого питания.

  • Низкая скорость обновления данных из-за ограничения времени работы. Мой план состоял в том, чтобы экран обновлялся один-два раза в день. Это ставит передо мной интересные дизайнерские задачи. Как показать, что данные отображаются не в реальном времени? Что следует показывать в качестве дневной температуры: среднюю или максимальную за день?

  • Физические ограничения рамки. В идеале прибор должен располагаться вровень со стеной.

План

Устройство должно “проснуться” рано утром, получить актуальную информацию о прогнозе погоды, обновить информацию на дисплее и вернуться в глубокий сон до следующего дня.

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

Теперь перейдём к исполнению.

Исполнение

Сначала я разработал интерфейс в Figma. Это заняло около 2-х дней (а точнее 2 вечера после работы).

Создание e-ink дисплея с прогнозом погоды - 2

Это был дизайн для 7,5-дюймового дисплея Waveshare с электронными чернилами. После того, как я заказал дисплей, я начал искать шрифты, которые будут хорошо отображаться на 1-битном (черно-белом) экране. На удивление трудно оказалось найти настоящие 1-битные экранные шрифты, поэтому я протестировал несколько вариантов с обычными веб-шрифтами с постобработкой и без неё:

Создание e-ink дисплея с прогнозом погоды - 3
Создание e-ink дисплея с прогнозом погоды - 4
Создание e-ink дисплея с прогнозом погоды - 5

Меня они не слишком устроили... Устройство будет находиться в самом сердце квартиры, поэтому экран должен выглядеть красиво.

Немного подумав, я дополнительно заказал 10,3-дюймовый 16-битный дисплей, который позволяет сглаживать текст. Контуры букв стали намного более плавными. Можно было жить и с 1-битным дисплеем, но я решил использовать его для чего-нибудь другого в будущем.

В тот же день я также заказал кучу другого оборудования: SD-карту, чип и аккумулятор PiJuice, стопорные винты, кабели GPIO и адаптеры. К счастью, у моего друга был запасной Raspberry PI Zero, которым он со мной поделился.

После того, как дизайн в Figma был готов, я начал создавать HTML-страницу, которая будет использоваться для визуализации пользовательского интерфейса. Многие существующие проекты используют библиотеки более низкого уровня вроде Python Imaging Library, но я выбрал HTML и CSS. Разработка идёт быстрее, когда можно редактировать HTML и сразу видеть результат без рендеринга растрового изображения после каждой итерации.

Разработка UI заняла примерно 1-2 недели, с учётом того, что я работал только по вечерам и выходным.

Создание e-ink дисплея с прогнозом погоды - 6

Детали по настройке вы найдёте в репозитории GitHub (перевод в конце статьи).

Когда я закончил разработку, как раз прибыло оборудование. Наконец-то я смог увидеть, как выглядит интерфейс не на моем экране с разрешением 1872x1404, а в бою. Установка и настройка Raspberry PI заняла довольно много времени, но это стоило того. Удивительно было видеть, как интерфейс впервые появляется на e-ink дисплее.

Ночные бдения
Ночные бдения

До этого момента всё шло на удивление гладко. Но потом я собрал все части воедино и понял, что рамка безбожно мала. 

Создание e-ink дисплея с прогнозом погоды - 8

Мне очень не хотелось делать толстый корпус, поэтому пришлось вернуться к чертежам. Я пытался уместить всё в рамке, тестируя всевозможные комбинации. Этот чудовищный кабель GPIO + переходник 1/2 почти справились со своей задачей:

Создание e-ink дисплея с прогнозом погоды - 9

Но даже после того, как я срезал все лишние пластиковые куски с кабелей, установить раму заподлицо со стеной не удалось.

Затем я понял, что на демонстрационной странице Waveshare есть приложение для Windows, которое подключается к контроллеру через интерфейс micro-USB. Можно ли использовать его для управления дисплеем? Не было никаких примеров того, как это сделать в Linux.

К счастью, некоторые великие умы уже задумались об этом. Я подключил контроллер с помощью USB-кабеля, скомпилировал код C на Raspberry PI и в качестве теста попытался очистить дисплей. Сработало! Какое облегчение. Кабели USB намного меньше, чем 40-контактные кабели и разъёмы GPIO.

Теперь, когда я был уверен в USB-стратегии, мне нужно было избавиться от разъёма GPIO контроллера IT851, потому что он всё ещё не влезал в рамку. К счастью, в Хельсинки есть замечательная библиотека Oodi (хакерское пространство, которое представляет собой смесь библиотеки, игрового кафе и места для встреч), куда я мог пойти и бесплатно отпаять разъём.

Фото сделано в той самой библиотеке Oodi, в комнате электроники, где есть классное оборудование, например, лазерный резак, 3D-принтер и многое другое
Фото сделано в той самой библиотеке Oodi, в комнате электроники, где есть классное оборудование, например, лазерный резак, 3D-принтер и многое другое

Уму непостижимо, насколько крут Oodi не только в плане архитектуры, но и с точки зрения функциональности.

К сожалению, паяю я не блестяще. Жене сказал, что работа займёт около 20 минут, но даже спустя 1,5 часа работы (и активного гугления) я не смог удалить разъем с чипа. Моё время в паяльной лаборатории истекло.

Следующей стратегией было применение грубой силы. Я взял бокорезы и просто отрезал половину жатки. Единственное, на что я мог надеяться, это на то, что после моего акта вандализма чип заработает. С разъёмом GPIO, разрезанным пополам, все детали, наконец, прекрасно влезли в рамку от IKEA!

Непонятные проблемы в программном обеспечении были решены, и можно было начинать окончательную сборку. Я прикрепил все к рамке ИКЕА с помощью винтов и термоклея. Дисплей очень тонкий, а задняя крышка слегка прогибается, поэтому я разместил винты так, чтобы они не повредили дисплей при переноске устройства.

Создание e-ink дисплея с прогнозом погоды - 11

Та-дам! Все составные части почти идеально вписались в рамку ИКЕА толщиной 2,9 см. 

Создание e-ink дисплея с прогнозом погоды - 12

Я очень беспокоился, что повредил компоненты в процессе целого часа непрофессиональной распайки, но, к счастью, всё работало.

Наконец, я протестировал всё на ошибки.

Создание e-ink дисплея с прогнозом погоды - 13
Создание e-ink дисплея с прогнозом погоды - 14

Готово, пришло время крепить раму к стене.

Создание e-ink дисплея с прогнозом погоды - 15
Создание e-ink дисплея с прогнозом погоды - 16
Создание e-ink дисплея с прогнозом погоды - 17

Мне очень нравится итоговый результат. Рамка ИКЕА имеет белую картонную вставку, которую я обрезал по размеру экрана. Чтобы не было несоответствия пропорций вставки и самой рамки, я пожертвовал несколькими вертикальными пикселями e-ink дисплея. Отверстие вставки по вертикали короче, чем у дисплея с электронными чернилами, поэтому некоторые Y-пиксели остаются неиспользованными. Немного стыдно, но общий вид важнее всего!

Один из вариантов, который я рассматривал  — распилить рамку таким образом, чтобы она идеально подходила под экран. Но получится фигня, к тому же дополнительное пространство внутри позволило мне уместить там все компоненты.

Проект занял 3 недели. Даже удивительно, что так быстро. Я намеренно выбрал знакомое оборудование и программное обеспечение, чтобы упростить разработку. Идея состояла в том, чтобы действительно закончить проект, хотя и покопаться в нём было полезно и интересно. 

Вот и все, было весело!

Список оборудования для справки

Из репозитория GIT

Проект состоит из двух составляющих: render и rasp.

render

На этом этапе создаётся HTML, который в конечном итоге будет отображаться как PNG. Изображение содержит прогноз погоды. Render предоставляется через Google Cloud Function. Это идеальный инструмент для такого рода задач. Эндпоинт вызывается редко, а задержки не имеют большого значения.

  • Данные о погоде извлекаются из API-интерфейсов Финского метеорологического института (ФМИ) и Open Meteo. API ФМИ имел некоторые ограничения, поэтому я дополнил данные информацией с Open Meteo. 

  • HTML, CSS и Headless Chrome используются для создания файла PNG. Эту часть можно было бы реализовать с помощью низкоуровневого подхода, но использовать для разметки CSS очень удобно.

  • Отображается вcё одним примитивным HTML-файлом, который содержит фиктивные данные для упрощения разработки. Фиктивные данные будут заменены реальными с использованием идентификаторов DOM. Отсутствие инструмента сборки устраняет множество ненужных сложностей.

  • Все даты в системе указаны в формате UTC, при рендеринге они конвертируются в местное время. 

rasp

Работает на Raspberry Pi Zero.

Сюда входит весь код, относящийся к оборудованию, которое будет отображать погоду. Эта часть ничего не знает о погоде, она просто загружает PNG с заданного URL-адреса и отображает его на дисплее e-Ink.

  • Извлекается PNG из заданного URL-адреса, он отображается на дисплее e-Ink и происходит возврат в режим ожидания. 

  • Должно потребляться как можно меньше энергии

  • Могло бы хватить микроконтроллера, но мне хотелось бы закончить проект до конца своей жизни

  • Код IT8951-ePaper скопирован с https://github.com/waveshare/IT8951-ePaper/

Монтаж

Примечание: это примерное руководство, написанное по памяти.

Большая часть программного обеспечения находится в облаке Google. Это снимает большую часть нагрузки с устройства Raspberry Pi, что позволяет увеличить время автономной работы. Развёртывание выполняется с помощью GitHub Actions, но первоначальная настройка была примерно такой:

  • Создать новый проект GCP

  • Создайте учётную запись службы развёртывания с ролью развёртывания Cloud Function. Установите ключ JSON как GCP_SERVICE_ACCOUNT_KEY secret.

  • Создайте ещё одну учётную запись службы для устройства Raspberry PI. Добавьте права записи для Cloud Logging. Таким образом, журналы могут быть отправлены в GCP для отладки, потому что в режиме сна Raspberry PI не использует батарею питания.

  • Создайте облачную функцию Google с исходным кодом hello world. К переменным окружения добавьте NODE_ENV=production и API_KEY=<new random key>. Ключ API предназначен только для предотвращения случайных вызовов http, потребляющих квоты GCP. Рендеринг Headless Chrome, кажется, хорошо работает с 1 ГБ памяти.

Настройка Raspberry PI

  • Загрузите правильный образ отсюда: https://www.raspberrypi.com/software/operating-systems/b

  • Залейте его на SD-карту с помощью balenaEtcher https://www.balena.io/etcher/ (или другой программы для записи образов)

  • Загрузите Raspberry и выполните первоначальную настройку

  • sudo raspi-config

    • Настройка SSID и пароля Wi-Fi (параметры системы)

    • Обновление языка системы, часовых поясов и т. д. (параметры локализации)

    • Включение SSH-сервера (параметры интерфейса)

    • Включение overlayfs (параметры производительности), чтобы сделать FS доступной только для чтения.

  • В вашем маршрутизаторе обязательно назначьте статический локальный IP-адрес для устройства.

  • Установите код обновления дисплея
    Скачайте архив

curl -H "Authorization: token <token>" -L https://api.github.com/repos/kimmobrunfeldt/eink-weather-display/zipball/main > main.zip

или sudo apt install git и

git clone https://<user>:<personal_access_token>@github.com/kimmobrunfeldt/eink-weather-display.git

Вы можете создать ограниченный токен личного доступа Github, который может клонировать это repo. Git мне показался самым простым, можно просто сделать git pull для внесения любых изменений.

  • sudo apt install python3-pip

  • Мне не удалось заставить pipenv работать благодаря тому, что pijuice является общесистемным пакетом. 

  • cd eink-weather-display && pip install Pillow==9.3.0 google-cloud-logging requests python-dotenv

Установка пакетов Python

  • Настройте переменные env: cp .env.example .env и заполните детали

  • Следуйте инструкциям по установке с https://www.waveshare.com/wiki/10.3inch_e-Paper_HAT, чтобы заставить дисплей E-Ink работать.

  • После установки проверьте, работает ли демонстрационное программное обеспечение (на языке C).

  • sudo apt install pijuice-base

  • Включите интерфейс I2C
    Дополнительная информация об отладке:

  • Чтобы разрешить PIJuice включаться без питания от батареи, перейдите в общие настройки и включите «Turn on without battery» или аналогичную опцию.

  • Убедитесь, что вы используете правильный профиль батареи PIJuice (у меня PJLIPO_12000)
    Если используете pijuice_cli, не забудьте применить изменения! Кнопка запрятана внизу.

  • Проверьте, работает ли PIJuice и от батареи.

  • cd rasp/IT8951 и следуйте инструкциям по установке

  • Настройте Pijuice с использованием pijuice_cli. Не забудьте сохранить изменения внутри каждого экрана настройки!

    • Системные события

    Будильник: каждый день в 04:00 UTC (6:00 по хельсинкскому времени зимой, 7:00 летом)

  • После этого вы можете протестировать дисплей PiJuice + E-Ink.

  • Настройте crontab. Запустите обновление при загрузке и выключите устройство, если оно работает от батареи.

    @reboot cd /home/pi/eink-weather-display/rasp && python main.py

    # Every minute

    * * * * * cd /home/pi/eink-weather-display/rasp && python shutdown_if_on_battery.py

Примечание: Всё, что было сделано выше, я делал с использованием пинов Raspberry PI GPIO. Однако они оказались слишком высокими для рамы. Вместо того, чтобы перепаивать пины GPIO, я решил использовать контроллер IT8951 через USB-интерфейс.

  • Установите https://git.sr.ht/~martijnbraam/it8951 в каталог /home/pi/usb-it8591 и скомпилируйте его в Raspberry.

    • Найдите, какой /dev/sdX является вашим USB-устройством, и измените все команды main.py соответственно

  • sudo apt install imagemagick

  • Отредактируйте main.py, указав правильные отступы. Из-за особенностей конструкции видны не все пиксели дисплея E-Ink. 

Разработка с данными-заполнителями

  • npm i

  • npm start

  • Откройте http://127.0.0.1:8080/ , чтобы настроить визуальные элементы со значениями заполнителей, жёстко запрограммированными в src/templates/index.html.

Отображение реальных значений

  • Откройте http://127.0.0.1:8080/render.html.

  • npm run render для запуска инструмента CLI, который отображает HTML вsrc/templates/render.html

Вызов облачной функции

Облачная функция и интерфейс командной строки поддерживают основные операции с изображениями, чтобы выгрузить эту работу из Raspberry: rotate, flip, flip, padding(Top|Right|Bottom|Left), resizeToWidth, resizeToHeight. См. Sharp для их документов. Например --flip с CLI или ?flip=true с CF.

LAT="60.222"
LON="24.83"
LOCATION="Espoo"
BATTERY="100"
TIMEZONE="Europe/Helsinki"

curl -vv -o weather.png 
  -H "x-api-key: $API_KEY" 
  "https://europe-west3-weather-display-367406.cloudfunctions.net/weather-display?lat=$LAT&lon=$LON&locationName=$LOCATION&batteryLevel=$BATTERY&timezone=$TIMEZONE"

Что ещё интересного есть в блоге Cloud4Y

→ Информационная безопасность и глупость: необычные примеры

→ It's Alive! Аккордеон из двух Commodore 64 и дискет

→ Как распечатать цветной механический телевизор на 3D-принтере

→ WD-40: средство, которое может почти всё

→ Подержите моё пиво, или как я сделал RGBeeb, перенеся BBC Micro в современный корпус

Подписывайтесь на наш Telegram-канал, чтобы не пропустить очередную статью. Пишем только по делу. А ещё напоминаем про второй сезон нашего сериала ITить-колотить. Его можно посмотреть на YouTube и ВКонтакте.

Автор: Cloud4Y

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js