пятница, 8 января 2021 г.

ESPHome: подключение дисплея от Nokia 3310 (5110) на контроллере PCD8544

        В данной статье описаны способы вывода информации на дисплей с контроллером PCD8544 (от старой Нокии 5110 или 3310). Ссылка на данный дисплей на Aliexpress.

Вывод простейших фигур:

1) Линия:

     Для вывода на экран линии используется команда лямбды it.line (x1,y1,x2,y2). Система координат начинается с левой верхней точки. Ось X ведет отсчет вправо по горизонтали, а ось Y – вниз по вертикали.

lambda: |-
   // Вывод линии от точки [x=0,y=0] до точки [x=50,y=20]
   it.line(0, 0, 50, 20)

  


2) Прямоугольник выводится лямбда командой it.rectangle(x1,y1,w,h) по координатам верхнего левого  угла и с заданной шириной – высотой.

    lambda: |-
      // Рисуем контур прямоугольника с верхним левым углом  [5,5], шириной 30 и высотой 40
      it.rectangle(5, 5, 30, 40);




3) Закрашенный прямоугольник выводится лямбда командой it. filled_rectangle (x1,y1,w,h) по координатам аналогичным it.rectangle

    lambda: |-
      //  Рисуем закрашенный прямоугольника с верхним левым уголком [5,5], шириной 30 и высотой 40      
      it.filled_rectangle(5, 5, 30, 40);


4) Круг выводится лямбда командой it.circle(x, y, R) в которой задаются координаты центра окружности и радиус

    lambda: |-
      // Нарисуем круг с центром в [25,25] и радиусов 10
      it.circle(25, 25, 10);



5) Круг с заливкой выводится лямбда командой it.filled_circle (x, y, R) аналогично it.circle

    lambda: |-
      // Нарисуем закрашенный круг с центром в [25,25] и радиусов 10
      it.filled_circle(25, 25, 10);


6) Также можно автоматически получать данные о высоте и ширине дисплея:

    lambda: |-
      // Нарисовать круг в центре дисплея радиусом 20 пикселей
      it.filled_circle(it.get_width() / 2, it.get_height() / 2, 20);


7) Вывод рисунка. Сначала рисунок в формате png необходимо скопировать в корень папки esphome. После этого прописать его в yaml файле в пункте image и вывести на экран лямбдой так (координаты задаются для левого верхнего угла изображения):

    lambda: |-
      // Вывести рисунок начиная с координат [x=0,y=0]
      it.image(0, 0, id(mess));

image:
  - file: "message.png"
    id: mess



Текст:

Настройка шрифта:

Перед выводом текста необходимо настроить шрифты. Для этого файл шрифта в формате ttf нужно положить в корень папки esphome и прописать в yaml-файле:

 font
  - file: "comicsansms3.ttf" 
    id: comic_sans 
    size: 14 :

1) Файл любого ttf шрифта нужно положить в корень папки esphome

2) В id прописать имя файла 

3) В size задать размер шрифта


Вывод текста:

       Для вывода текста на экран используется команда лямбды it.print с параметрами в которых задается отступ по горизонтали, отступ по вертикали, шрифт и выводимый текст.

    lambda: |-
      it.print(0, 0, id(comic_sans), "mynobook"); 
      it.print(0, 15, id(comic_sans), "blogspot.com");

Вот как это выглядит на экране:

 


      По умолчанию ESPHome выравнивает текст в левом верхнем углу. Это означает, что, если вы введете координаты [0,10] для своего текста, верхний левый угол текста будет смещен вниз на 10 пикселей. 

     Если вы хотите выровнять текст по правому краю, можно задать другое выравнивание текста.  Например, при использовании TOP_RIGHT, текст будет располагаться слева от точки привязки, и как следует из названия, точка привязки находится в верхнем правом углу текста.

    lambda: |-
      // Выравнивание по левому краю (по умолчанию)
      it.print(0, 0, id(comic_sans), "Left aligned");

      // Выравнивание по правому краю
      it.print(it.get_width(), 20, id(comic_sans), TextAlign::TOP_RIGHT, "Right aligned");

     В результате на экране будет следующее:

 



Вывод показаний датчиков:

     Также можно вывести значение датчика. Делается это командой it.printf.

    lambda: |-
      // Если значение датчика, например 30.02, то будет выведено: "Temp: 30.0 °C"
      it.printf(0, 0, id(comic_sans), "Temp: %.1f °C", id(temperature_broadlink).state);


      Здесь все аналогично
it.print кроме кода %.1f, который обозначает следующее:

        % - инициировать формат. По умолчанию будет выравнивание по левому краю. Если необходимо выравнивание по правому краю – указываем после % число, обозначающее отступ.  Например, если написать 

…"Temp: %5.1f °C", id(temperature_broadlink).state);

то будет выведено "Temp:   30.0 °C" (число выровнено по правому краю и дополнено слева пробелами, если количество цифр короче 5 символов)

       .1 - округлить десятичное число до 1 цифры после запятой. Если нужно отобразить 2 цифры после запятой – то необходимо указать .2

        f - спецификатор, который сообщает printf тип данных. В данном случае f(loat) – число с плавающей точкой. 


     Если в одной строке необходимо вывести 2 значения переменных можно указать, например так:

…"Temperature: %.1f°C, Humidity: %.1f%%", id(temperature).state, id(humidity).state);



Вывод времени:

          На выводе времени хочется остановиться поподробней. Сначала нужно указать источник получения точного времени.  Можно указать следующие источники:

1) Время из Home Assistant:

# Время из Home Assistant
time:
  - platform: homeassistant
    id: homeassistant_time


2) Время из сервера SNTP

# Время с SNTP сервера
time:
  - platform: sntp
    id: sntp_time


3) Время по GPS

# Время по GPS
time:
  - platform: gps
    id: gps_time


      Для вывода времени используется команда it.strftime, которая переводит представление времени в строковую переменную:

    lambda: |-
      // Вывод даты-времени
      it.strftime(0, 0, id(comic_sans), "%H:%M", id(homeassistant_time).now());
      it.strftime(0, 15, id(comic_sans), "%d-%m-%Y", id(homeassistant_time).now()); 

На экране это выглядит так:



Код в команде обозначает следующее:

Код Описание Пример
%a Сокращенное название дня недели Sat
%A Полное название дня недели Saturday
%w Число, обозначающее день недели, где 0 – воскресенье, а 6 - суббота 6
%d Число, обозначающее день месяца и состоящее из двух цифр 01, 02, …, 31
%b Сокращенное название месяца Aug
%B Полное название месяца August
%m Число, обозначающее месяц и состоящее из двух цифр 01, 02, …, 12
%y Число, обозначающее год и состоящее из двух цифр 00, 01, …, 99
%Y Число, обозначающее год и состоящее из четырех цифр 2021
%H Число, обозначающее часы и состоящее из двух цифр (0-23) 00, 01, …, 23
%I Число, обозначающее часы и состоящее из двух цифр (0-12) 00, 01, …, 12
%p Часовой интервал – до полудня (AM) и после полудня (PM) AM, PM
%M Число, обозначающее минуты и состоящее из двух цифр 00, 01, …, 59
%S Число, обозначающее секунды и состоящее из двух цифр 00, 01, …, 59
%j Число, обозначающее день в году и состоящее из трех цифр 001, 002, …, 366
%U Число, обозначающее номер недели в году, начинающейся с воскресенья 00, 01, …, 53
%W Число, обозначающее номер недели в году, начинающейся с понедельника 00, 01, …, 53
%c Вывод даты и времени Sat Aug 18 16:31:42 2020
%x Вывод даты 08/18/2020
%X Вывод времени 16:31:42
%% Вывод символа «%» %

Архив с используемыми в статье шрифтами и картинкой можно скачать здесь

Часы на ESPHome

  Далее приведу пример, как можно сделать часы при помощи прошивки ESPHome.

Профиль:

esphome:
  name: test
  platform: ESP8266
  board: nodemcuv2

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password


  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Test Fallback Hotspot"
    password: !secret ap_password

captive_portal:

# Enable logging
logger:

# Enable Home Assistant API
api:
  password: !secret api_password

ota:
  password: !secret ota_password

web_server:
  port: 80
  
# Время из Home Assistant
time:
  - platform: homeassistant
    id: homeassistant_time
    
# Вывод текста
spi:
  clk_pin: D5
  mosi_pin: D7

display:
  - platform: pcd8544
    reset_pin: D0
    cs_pin: D8
    dc_pin: D1
    contrast: 0x40
    lambda: |-
      // Вывод часов с мигающей точкой
      static int i = 0;
      i++;
      if ((i % 2) == 0)
        it.strftime(2, 0, id(sfdigital), "%H:%M", id(homeassistant_time).now());
      else
        it.strftime(2, 0, id(sfdigital), "%H %M", id(homeassistant_time).now());  
      // Вывод дня недели
      it.strftime(15, 25, id(sfdigital1), "%A", id(homeassistant_time).now());
      // Вывод даты
      it.strftime(10, 37, id(sfdigital1), "%d-%m-%Y", id(homeassistant_time).now());

font:
  - file: "SFDigitalReadout.ttf"
    id: sfdigital
    size: 36
    
  - file: "SFDigitalReadout.ttf"
    id: sfdigital1
    size: 15

    
# Включение подсветки дисплея
light:
  - platform: monochromatic
    name: "Backlights"
    output: backlight

output:
  - platform: esp8266_pwm
    id: backlight
    pin: D2

Фото:



Вебморда:



Отображение в Home Assistant:

 



  На этом все. Если будут какие-либо вопросы - постараюсь ответить в комментариях.


6 комментариев:

  1. Как работает конструкция с мигающей точкой (i++)? Почему i увеличивается на 1 именно раз в секунду?

    ОтветитьУдалить
    Ответы
    1. Переменная i увеличивается на 1 не раз в секунду, а намного чаще. А мигание точки зависит от остатка деления значения секунд на 2. Если показания секунд четные (остаток от деления равен 0), то точки светятся, а если нечетные - то не светятся. Время берется с Home Assistant.

      Удалить
  2. Этот комментарий был удален автором.

    ОтветитьУдалить
    Ответы
    1. Вся информация о командах и подключении датчиков есть на официальном сайте: https://esphome.io/#sensor-components
      Для примера можете посмотреть как я выводил данные с датчика температуры на экран в этой статье: https://mynobook.blogspot.com/2020/11/kichen-esphome.html

      Удалить
    2. Этот комментарий был удален автором.

      Удалить
    3. В том то и дело что там написано не однозначно, по крайней мере у меня на той информации не заработало.
      В итоге нашел на просторах инета разные отрывки и собрал что называется по интуиции ))
      В итоге получилось (датчик dht22) как то так:
      display:
      - platform: lcd_pcf8574
      dimensions: 16x2
      address: 0x27
      lambda: |-
      it.printf(0, 0, "Temperature:%.2f'C", id(Tsensor).state);
      it.printf(0, 1, "Humidity: %.2f%%", id(Hsensor).state);

      Ваши посты еще посмотрю, большое спасибо !!

      Удалить