3 мин на чтение

Никогда ранее не писал компоненты для ESPHome, а тут судьба подкинула T-Display S3 Long, и пришлось. Именно об этом сегодняшняя зарисовочка ;)

AXS15231 from github://buglloc/esphome-components

T-Display S3 Long

Но для начала пара слов о LILYGO T-Display S3 Long:

На борту у которого:

  • ESP32-S3R8
  • 16MB флешки
  • 8MB PSRAM
  • зарядка для аккумулятора на базе SY6970
  • 3.4” capacitive touch экран разрешением 180x640, QSPI интерфейсом и AXS15231 MCU

Это из хорошего, а из плохого:

  • ужасная (точнее практически отсутствующая) документация
  • кривые и полурабочие примеры

Не скажу, что у LILYGO документация когда-то была сильной стороной, но примерчики зачастую были норм. В этот же раз у меня сложилось впечатление, что никто и не ставил себе целью сделать что-то достойное, чисто запушили наброски какие были :( В общем, я бы скорее не советовал к покупке этот борд и проголосовал батомрублем за что-то другое. Но что куплено, то куплено - тут главное не отчаиваться :)

ESPHome: External Components

Как я и говорил в самом начале - использовать T-Display S3 Long я хотел из ESPHome. А ESPHome, будучи довольно взрослым фреймворком, поддерживает т.н. External Components, с помощью которых можно как подключить новый компонент, так и заменить существующий.

При этом процесс создания нового компонента не сложнее рисования совы:

  • заводим репо нужной структуры:
$ git init && mkdir -p components/<my_cool_component>
  • пишем новый компонент - см. Contributing to ESPHome
  • все, любой желающий может подключить этот репо и воспользоваться компонентом:
external_components:
  - source: github://cool-author/cool-repo-name
	components: [ my_cool_component ]

Если же говорить о потрошках самого компонента, то он состоит из трех частей:

import esphome.config_validation as cv

CONF_MY_REQUIRED_KEY = 'my_required_key'
CONF_MY_OPTIONAL_KEY = 'my_optional_key'

CONFIG_SCHEMA = cv.Schema({
  cv.Required(CONF_MY_REQUIRED_KEY): cv.string,
  cv.Optional(CONF_MY_OPTIONAL_KEY, default=10): cv.int_,
}).extend(cv.COMPONENT_SCHEMA)
import esphome.codegen as cg

def to_code(config):
    var = cg.new_Pvariable(config[CONF_ID])
    yield cg.register_component(var)

    cg.add(var.set_my_required_key(config[CONF_MY_REQUIRED_KEY]))
    if optional_val := config.get(CONF_MY_OPTIONAL_KEY):
        cg.add(var.set_my_optional_key(optional_val))
  • ну и сама реализация компонента на C++

Пожалуй, наиболее коварная часть - это одновременная поддержка нескольких нижележащих фреймворков, и это кунг-фу я, к своему стыду, пока не познал. При этом сам ESPHome с одной стороны имеет множество базовых абстракций (e.g. I2CDevice, UARTDevice, SPIDevice, etc), а с другой - внушительную базу примеров из уже реализованных компонентов.

ESPHome: AXS15231 component

К счастью, один добрый человек уже добавил поддержку QSPI в ESPHome, поэтому мне осталось только реализовать Display и Touchscreen компоненты.

Сказано - сделано. Пара утроночеров копипасты и нужный компонент готов. На 80% состоит из С++ и на 20% из Python, что, на мой вкус, звучит не плохо.

К сожалению, плохость примеров от LILYGO и моя тупость пока оставили за бортом такие фичи как:

  • DMA (скорее всего должен помочь ускорить рендеринг)
  • аппаратный поворот экрана (MADCTL_MV тупо все портит)
  • прерывания от сенсорного экрана

Не скажу, что эти фичи мне прям сейчас очень нужны, но как-то обидненько, и если будут силы, то я добью. Но хватит болтовни! Подключаем борд к ESPHome, пишем простенький конфиг (внимательнее с пинами, как обычно):

esphome:
  name: t-display-s3-long
  friendly_name: LilyGo-T-Display-Long
  platformio_options:
    upload_speed: 921600
    build_unflags: -Werror=all
    board_build.flash_mode: dio
    board_build.f_flash: 80000000L
    board_build.f_cpu: 240000000L

psram:
 mode: octal
 speed: 120MHz

esp32:
  board: esp32-s3-devkitc-1
  flash_size: 16MB
  framework:
    type: esp-idf

external_components:
  - source: github://buglloc/esphome-components
    refresh: 10min

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

spi:
  id: display_qspi
  clk_pin: 17
  data_pins:
    - 13
    - 18
    - 21
    - 14

i2c:
  sda: 15
  scl: 10
  id: touchscreen_bus

font:
  - file: "gfonts://Madimi One"
    id: font_std
    size: 40
    glyphs: "!\"%()+=,-_.:°0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz/\\[]|&@#'"
  - file: "gfonts://Madimi One@400"
    id: font_title
    size: 40
    glyphs: "!\"%()+=,-_.:°0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz/\\[]|&@#'"

globals:
  - id: title_color
    type: Color
    initial_value: "Color::random_color()"

display:
  - platform: axs15231
    id: main_display
    spi_id: display_qspi
    dimensions:
      height: 640
      width: 180
    cs_pin: 12
    reset_pin: 16
    backlight_pin: 1
    transform:
      swap_xy: false
    rotation: 90
    auto_clear_enabled: false
    lambda: |-
      it.print(it.get_width()/2, it.get_height()/2-20, id(font_title), id(title_color), TextAlign::CENTER, "ESPHome @ AXS15231B");
      it.print(it.get_width()/2, it.get_height()/2+30, id(font_std), {230,0,115}, TextAlign::CENTER, "@UTBDK");

touchscreen:
  - platform: axs15231
    id: main_touch
    display: main_display
    i2c_id: touchscreen_bus
    transform:
      swap_xy: true
    on_touch:
      - lambda: |-
            Color newColor;
            do { newColor =  Color::random_color(); } while (newColor == id(title_color));
            id(title_color) = newColor;

            ESP_LOGI("cal", "x=%d, y=%d, x_raw=%d, y_raw=%0d",
              touch.x,
              touch.y,
              touch.x_raw,
              touch.y_raw
            );

Прошиваем, запускаем и….вуаля:

Closure

Признаться, у меня пока настолько положительные впечатления от ESPHome, что в следующий раз придется хорошенько задуматься - тащить в очередной проект поддержку mqtt, ota, ha, wifi manager и черта лысого руками или дописать недостающее внешним компонентом к ESPHome. Понятное дело, что проект проекту рознь, но для большей части сенсоров, датчиков, кнопочек и прочего home automation IoT я бы точно рассматривал ESPHome как добротную платформу :)

А на этом у меня все, всем кота (づ˶•༝•˶)づ♡

Разделы: ,

Дата изменения: