Mój pierwszy LCD ESPHome

Pierwszy raz próbuję swoich sił w esphome z LCD. Kupiłem na li takie kombo: 2,8-calowy moduł ESP32 TFT LCD z akrylową obudową Dwurdzeniowy ESP32-2432S028R WIFI + BT 240X320 ILI9341 Rezystancyjny ekran dotykowy - AliExpress 502

Oczywiście w opisie aukcji nie ma żadnych połączeń pinów do TFT wskazanych. Znalazłem w sieci taką bibliotekę: https://raw.githubusercontent.com/RuiSantosdotme/ESP32-TFT-Touchscreen/main/configs/User_Setup.h i razem z chatem GPT zrobiłem taki konfig do ESPHOME:

esphome:
  name: lcd1
  friendly_name: lcd1

esp32:
  board: esp32dev
  framework:
    type: arduino

# Enable logging
logger:

# Enable Home Assistant API
api:
  encryption:
    key: "8tLi47FRR6T2ughQnEBT4SIDLk4LTtrYCNoU+JPtgro="

ota:
  - platform: esphome
    password: "751a50e2dcb47937317ac6786712569b"

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

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Lcd1 Fallback Hotspot"
    password: "5nFWPddzEdSA"

captive_portal:
font:
  - file: "fonts/Roboto-Regular.ttf"
    id: my_font
    size: 50
spi:
  clk_pin: 14
  mosi_pin: 13
  miso_pin: 12 

output:
  - platform: gpio
    pin: 21
    id: tft_backlight

display:
  - platform: ili9xxx
    model: ILI9341
    invert_colors: false
    cs_pin: 15 
    dc_pin: 2
    auto_clear_enabled: true
    show_test_card: false
    update_interval: 10s
    rotation: 270
    lambda: |-
      it.print(165, 130, id(my_font), Color::BLACK, TextAlign::CENTER, "21 C");
switch:
  - platform: output
    name: "TFT Backlight"
    output: tft_backlight

touchscreen:
  - platform: xpt2046
    cs_pin: 33 
    update_interval: 50ms
    calibration:
      x_min: 200
      x_max: 3900
      y_min: 200
      y_max: 3900
 

Ekran uruchamia się bez podświetlenia, ale w homeassistant mogę je włączyć w dashboardzie. Widać, że jest włączone, ale nic się na ekranie nie wyswietla.
gdy zmienię show_test_card: na “true” i włącze podświetlenie to wyświetla się plansza testowa.

Trochę skończyły mi się pomysły, jeśli ktoś z was może mi pomóc to będę wdzięczny. Podejrzewam, że problem jest z niewłaściwymi pinami ale nie znalazłem specyfikacji.

To znaczy, że GPIO i generalnie wyświetlacz (jeśli kolory zgadzają się z opisem) masz skonfigurowany poprawnie.

na czarnym wyświetlaczu piszesz na czarno, więc nie będzie tego widać…

PS Oferta na którą się powołujesz nie jest aukcją (nie pozwólmy by poznański sklep internetowy, który kiedyś istotnie był portalem aukcyjnym, zniszczył nam język polski).

Byłoby lepiej gdybyś po prostu przeczytał dokumentację, GPT zlepia losowe fragmenty kodu i jest w pełnym samozadowoleniu.

Aż wstyd. Chciałem na białym tle pisać na czarno, cóż :slight_smile:

Dobra, a teraz coś trudniejszego - chcę mieć na wyświetlaczu odwzorowanie dashboardu na którym byłoby dotykowe sterowanie 2x termostat + podgląd wartości 2 encji. Muszę to wszystko rysować czy da się coś wyciągnąć z HA bezpośrednio?

Chyba żartujesz… oczywiście musisz sobie sam to narysować.
Odwzorowanie dashboradu czy nawet karty to kilometry YAMLa.

No fajnie będzie zabawa. Myślałem, że ktoś już to ogarnął w takim sensie, że są jakieś gotowe biblioteki “z kilometrami yamla” które mogę wykorzystać do zrobienia króciutkiego kodu - coś w stylu blueprintów w HA.

Tak to nie będzie, bo to YAML ESPHome już jest tym “blueprintem”, który interpreter przetwarza na kod źródłowy w c++ (z tego co pokazałeś wyżej powstaje tyle “kilometrów” kodu źródłowego, że się w głowie nie mieści - aby go przeczytać byś musiał spędzić przynajmniej kilka miesięcy czytając po wiele godzin dzienne)
ale jest coś innego, co jest jeszcze bardziej a’la blueprinty

Oprócz tego możesz oczywiście adaptować do swoich potrzeb dowolne inne projekty, które powstały dla innych wyświetlaczy (również w innych technologiach, tylko musisz wtedy zaadaptować ustawienia silnika renderowania do możliwości twojego wyświetlacza).

Tu masz przykład dla e-inka (on ma zwykle tylko czerń i biel oraz wymaga ekstremalnie rzadkiego odświeżania, więc to akurat wymaga modyfikacji, ale resztę możesz wykorzystać)

a tu inny przykład (też wyświetlacz jakiś inny, ale już się drastycznie nie różni od tego co masz)

a nie szukałem jakoś ultra głęboko - to trafienia z tego forum

2 polubienia

Bardzo dziękuję za wszystkie wskazówki. To bardzo ułatwia mi zadanie.

Z okazji twojego wątku oznaczyłem “tyle ile mi wpadło w ręce” tagiem display więc możesz przejrzeć inne wątki łatwo.

Trochę mnie zmotywowałeś do odgrzebania starego YAMLa, którym testowałem e-inki (bo jeśli chodzi o tą technologię to dokumentacja mocno kuleje, a same wyświetlacze dedykowane dla fanów DIY nie są zwykle rozsądnie oznaczone - coś o tym wiem bo byłem przekonany, że kupiłem kiedyś 2 identycznie, ale identyczne to były tylko pozornie) to wrzucę do osobnego wątku.


A i jeszcze jedno ta twoja gotowa płytka prototypowa z wyświetlaczem i dotykiem jest bardziej znana jako CYD (Cheap-Yellow-Display = tani żółty wyświetlacz) i nawet dla niej istnieją “gotowce” dla ESPHome (tylko czy ktoś się czegoś kiedyś nauczył z samych gotowców?)

1 polubienie

Jeszcze raz dzięki. Bawię się nieźle dzięki tym wskazówkom. Działa dotyk, czujnik światła, teoretycznie głośnik (bo nie mam jeszcze fizycznie na czym sprawdzić) mogę rysować różne widgety przez lvgl. jedynie wskazówka dla potomnych

lvgl:
  buffer_size: 25%

Bo bez tego urządzenie wpada w bootloop.

W tym linku wyżej jest też gdzieś opis/link jak dołożyć kość PSRAM modyfikując płytkę (trochę dla hardkorów, no niestety Chińczyk trochę przesadził z wytanianiem konstrukcji… a 500kB RAMu to nie za wiele, choć to i tak więcej niż miały wczesne pecety, tylko nikt wtedy nie wymagał od nich obsługi multimediów ani zaawansowanej kolorowej grafiki).

Miałem dziś trochę czasu i pobawiłem się dalej tym wyświetlaczem. Z pomocą Internetu i AI napisałem konfigurację i jestem ogólnie zadowolony:

Jednakże jak widać na załaczonym obrazku z prawej strony pojawia mi się pasek przewijania tak jakby coś nie mieściło się w wyznaczonym obszarze. Przez to gdy klikam na przyciski ekran potrafi się przesunąć:


Próbowałem to diagnozować, przesuwałem przyciski +/- wyżej napisy Co2/Wilgotność i skalę z temperaturą niżej ale nic to nie dało.
Może macie jakieś pomysły?

esphome:
  name: lcd1
  friendly_name: lcd1
  on_boot:
    priority: 600
    then:
      - lambda: |-
          lv_obj_t *blank_screen = lv_obj_create(NULL);
          lv_scr_load(blank_screen); // Ładuje pusty ekran

esp32:
  board: esp32dev
  framework:
    type: arduino

logger:

api:
  encryption:
    key: "XXXXXXXXXXXXXXXXXXXX"

ota:
  - platform: esphome
    password: "XXXXXXXXXXXXXXXX"

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
  ap:
    ssid: "Lcd1 Fallback Hotspot"
    password: "XXXXXXX"

captive_portal:

globals:
  - id: brightness
    type: float
    restore_value: yes
    initial_value: "1.0"
  - id: temperatura
    type: float
    restore_value: no
  - id: temperatura_k
    type: float
    restore_value: no

spi:
  - id: tft
    clk_pin: GPIO14
    mosi_pin: GPIO13
    miso_pin: GPIO12
  - id: touch
    clk_pin: GPIO25
    mosi_pin: GPIO32
    miso_pin: GPIO39

output:
  - platform: ledc
    pin: GPIO21
    id: backlight_pwm
  - platform: ledc
    pin: GPIO4
    id: led_red
    inverted: true
  - platform: ledc
    pin: GPIO16
    id: led_green
    inverted: true
  - platform: ledc
    pin: GPIO17
    id: led_blue
    inverted: true

lvgl:
  buffer_size: 25%
  pages:
    - id: meter_page
      widgets:
        - obj:
            height: 240
            width: 320
            align: CENTER
            y: 0
            x: 0
            bg_color: 0x000000
            border_width: 0
            pad_all: 0
            widgets:
              - meter:
                  id: my_meter   # Dodany identyfikator metra
                  x: 0
                  y: -25
                  height: 200
                  width: 200
                  border_width: 0
                  align: CENTER
                  bg_opa: TRANSP
                  scales:
                    - range_from: -15
                      range_to: 35
                      angle_range: 180
                      ticks:
                        count: 70
                        width: 1
                        length: 31
                      indicators:
                        - tick_style:
                            start_value: -15
                            end_value: 35
                            color_start: 0x3399ff
                            color_end: 0xffcc66
                    - range_from: -150
                      range_to: 350
                      angle_range: 180
                      ticks:
                        count: 0
                      indicators:
                        - line:
                            id: temperature_needle
                            width: 8
                            r_mod: 0
                            value: 10
                            color: 0x3399ff
              - obj:  # Przykrywamy środek wskaźnika
                  height: 123
                  width: 123
                  radius: 73
                  y: -25
                  align: CENTER
                  border_width: 0
                  pad_all: 0
                  bg_color: 0x000000
              - label:
                  id: temperature_text
                  text: "--.-°C"
                  align: CENTER
                  y: -50
                  text_color: 0xffffff
                  bg_color: 0x000000
                  text_font: montserrat_32
              - label:
                  text: "Temperatura"
                  align: CENTER
                  y: -30    
                  text_color: 0xffffff
                  bg_color: 0x000000
        - obj:
            align: BOTTOM_LEFT
            width: 100
            height: 140
            border_width: 0
            pad_all: 0
            text_color: 0xffffff
            bg_color: 0x000000
            text_font: montserrat_32
            widgets:
              - button:
                  width: 90
                  height: 45               
                  id: temp_down
                  align: CENTER
                  text_align: CENTER
                  y: +45
                  bg_color: 0x3399ff
                  on_click:
                    - lambda: |-
                        id(temperatura) -= 0.2;
                        {
                          char buf[10];
                          snprintf(buf, sizeof(buf), "%.1f", id(temperatura));
                          lv_label_set_text(id(temperatura_wysw), buf);
                        }
                    - homeassistant.action:
                        action: climate.set_temperature
                        data:
                          temperature: !lambda "return id(temperatura);"
                          entity_id: climate.salonik
                  widgets:
                    - label:
                        align: CENTER
                        text_align: CENTER
                        text: "-"
              - label:
                  id: temperatura_wysw
                  align: CENTER
                  text_align: CENTER
                  width: 90
                  height: 45
                  y: +10
                  text_font: montserrat_28
                  text_color: 0xffffff
                  on_value:
                    then:
                      - homeassistant.action:
                          action: climate.set_temperature
                          data:
                            temperature: !lambda "return id(temperatura);"
                            entity_id: climate.salonik
              - button:
                  id: temp_up
                  width: 90
                  height: 45
                  align: CENTER
                  text_align: CENTER
                  bg_color: 0x3399ff
                  y: -40
                  on_click:
                    - lambda: |-
                        id(temperatura) += 0.2;
                        {
                          char buf[10];
                          snprintf(buf, sizeof(buf), "%.1f", id(temperatura));
                          lv_label_set_text(id(temperatura_wysw), buf);
                        }
                    - homeassistant.action:
                        action: climate.set_temperature
                        data:
                          temperature: !lambda "return id(temperatura);"
                          entity_id: climate.salonik
                  widgets:
                    - label:
                        align: CENTER
                        text_align: CENTER
                        text: "+"
        - obj:
            border_width: 3
            border_side: 
              - bottom
              - top
            width: 135
            height: 55
            pad_all: 0
            text_color: 0xffffff
            bg_color: 0x000000
            text_font: montserrat_22
            transform_angle: 90
            y: 100
            x: 155
            widgets:
              - button:
                  id: temp_downgrzejnik
                  align: CENTER
                  text_align: CENTER
                  width: 130
                  height: 50
                  bg_color: 0x000000
              - label:
                  align: CENTER
                  text_align: CENTER
                  text: "Grzejnik"
        - obj:
            border_width: 0
            width: 90
            height: 40
            pad_all: 0
            text_color: 0xffffff
            bg_color: 0x000000
            text_font: montserrat_14
            y: 10
            x: 0
            widgets:
              - label:
                  id: co2_label
                  align: CENTER
                  text_align: CENTER
                  text: "CO2: \n-- ppm"
        - obj:
            border_width: 0
            width: 90
            height: 40
            pad_all: 0
            text_color: 0xffffff
            bg_color: 0x000000
            text_font: montserrat_14
            y: 10
            x: 230
            widgets:
              - label:
                  id: hum_label
                  align: CENTER
                  text_align: CENTER
                  text: "Wilgotn. \n-- %%"
        - obj:
            border_width: 3
            border_side: 
              - bottom
              - top
            width: 135
            height: 55
            pad_all: 0
            text_color: 0xffffff
            bg_color: 0x000000
            text_font: montserrat_22
            transform_angle: 270
            y: 232
            x: 165
            widgets:
              - button:
                  id: temp_klima
                  align: CENTER
                  text_align: CENTER
                  width: 130
                  height: 50
                  bg_color: 0x000000
                  on_click:
                    then:
                      - homeassistant.action:
                          action: climate.toggle
                          data:
                            entity_id: climate.153931628223294_climate
              - label:
                  align: CENTER
                  text_align: CENTER
                  text: "Klimatyz."
        - obj:
            align: BOTTOM_LEFT
            x: +220
            width: 100
            height: 140
            border_width: 0
            pad_all: 0
            text_color: 0xffffff
            bg_color: 0x000000
            text_font: montserrat_32
            widgets:
              - button:
                  width: 90
                  height: 45               
                  id: temp_down_k
                  align: CENTER
                  text_align: CENTER
                  y: +45
                  bg_color: 0x3399ff
                  on_click:
                    - lambda: |-
                        id(temperatura_k) -= 0.2;
                        {
                          char buf[10];
                          snprintf(buf, sizeof(buf), "%.1f", id(temperatura_k));
                          lv_label_set_text(id(temperatura_wysw_k), buf);
                        }
                    - homeassistant.action:
                        action: climate.set_temperature
                        data:
                          temperature: !lambda "return id(temperatura_k);"
                          entity_id: climate.153931628223294_climate
                  widgets:
                    - label:
                        align: CENTER
                        text_align: CENTER
                        text: "-"
              - label:
                  id: temperatura_wysw_k
                  align: CENTER
                  text_align: CENTER
                  width: 90
                  height: 45
                  y: +10
                  text_font: montserrat_28
                  text_color: 0xffffff
                  on_value:
                    then:
                      - homeassistant.action:
                          action: climate.set_temperature
                          data:
                            temperature: !lambda "return id(temperatura_k);"
                            entity_id: climate.153931628223294_climate

              - button:
                  id: temp_up_k
                  width: 90
                  height: 45
                  align: CENTER
                  text_align: CENTER
                  bg_color: 0x3399ff
                  y: -40
                  on_click:
                    - lambda: |-
                        id(temperatura_k) += 0.2;
                        {
                          char buf[10];
                          snprintf(buf, sizeof(buf), "%.1f", id(temperatura_k));
                          lv_label_set_text(id(temperatura_wysw_k), buf);
                        }
                    - homeassistant.action:
                        action: climate.set_temperature
                        data:
                          temperature: !lambda "return id(temperatura_k);"
                          entity_id: climate.153931628223294_climate
                  widgets:
                    - label:
                        align: CENTER
                        text_align: CENTER
                        text: "+"
display:
  - platform: ili9xxx
    model: ILI9341
    spi_id: tft
    invert_colors: false
    cs_pin: 15 
    dc_pin: 2
    update_interval: 1s
    id: my_display
    auto_clear_enabled: false
    rotation: 90

light:
  - platform: monochromatic
    output: backlight_pwm
    name: "Podświetlenie LCD"
    id: backlight
    restore_mode: ALWAYS_ON
  - platform: rgb
    name: RGB
    id: led
    red: led_red
    green: led_green
    blue: led_blue
    restore_mode: ALWAYS_OFF

switch:
  - platform: restart
    name: "Restart"
  - platform: shutdown
    name: "Shutdown"
  - platform: safe_mode
    name: "Restart (Safe Mode)"

touchscreen:
  platform: xpt2046
  spi_id: touch
  cs_pin: GPIO33
  interrupt_pin: GPIO36
  update_interval: 50ms
  threshold: 400
  calibration:
    x_min: 280
    x_max: 3860
    y_min: 340
    y_max: 3860
  transform:
    swap_xy: true
      
sensor:
  - platform: adc
    pin: GPIO34
    name: "board_ldr"
    update_interval: 1500ms
  - platform: wifi_signal 
    name: "WiFi Signal dB"
    id: wifi_signal_db
    update_interval: 60s
    entity_category: "diagnostic"
  - platform: copy 
    source_id: wifi_signal_db
    name: "WiFi Signal Percent"
    filters:
      - lambda: return min(max(2 * (x + 100.0), 0.0), 100.0);
    unit_of_measurement: "Signal %"
    entity_category: "diagnostic"
  - platform: homeassistant
    id: temperatura_aktualna
    entity_id: sensor.salon_temp_wilg_temperatura
    on_value:
      - lambda: |-
          lv_meter_set_indicator_value(id(my_meter), id(temperature_needle), x * 10);
      - lvgl.label.update:
          id: temperature_text
          text:
            format: "%.1f°C"
            args: [ x ]
  - platform: homeassistant
    id: room_thermostat
    entity_id: climate.salonik
    attribute: temperature
    on_value:
      - lambda: |-
          id(temperatura) = x;
          {
            char buf[10];
            snprintf(buf, sizeof(buf), "%.1f", x);
            lv_label_set_text(id(temperatura_wysw), buf);
          }
  - platform: homeassistant
    id: co2_salon
    entity_id: sensor.czujnik_c02_salon_2_poziom_co2
    on_value:
      - lambda: |-
          char buf[20];
          snprintf(buf, sizeof(buf), "CO2: \n%d ppm", (int)x);
          lv_label_set_text(id(co2_label), buf);
  - platform: homeassistant
    id: hum_salon
    entity_id: sensor.salon_temp_wilg_wilgotnosc
    on_value:
      - lambda: |-
          char buf[20];
          snprintf(buf, sizeof(buf), "Wilgotn.: \n%d %%", (int)x);
          lv_label_set_text(id(hum_label), buf);

  - platform: homeassistant
    id: room_klima
    entity_id: climate.153931628223294_climate
    attribute: temperature
    on_value:
      - lambda: |-
          id(temperatura_k) = x;
          {
            char buf[10];
            snprintf(buf, sizeof(buf), "%.1f", x);
            lv_label_set_text(id(temperatura_wysw_k), buf);
          }

i2s_audio:
  i2s_lrclk_pin: GPIO26

media_player:
  - platform: i2s_audio
    name: ESPHome I2S Media Player
    dac_type: internal
    mode: stereo

Wiesz, nie wiem jak to ująć, ale chyba nikomu się nie chce poprawiać po AI…

Przypuszczalnie generujesz większy obraz od ekranu, ale aby to sprawdzić kartką i ołówkiem trzeba by poświęcić pewnie więcej czasu niż sam na to straciłeś (bo to wymaga rozrysowania współrzędnych, które zaczynają się w wielu różnych miejscach i liczenia pikseli).

1 polubienie

Już sobie poradziłem - wystarczyło zastosować w nadrzędnym obj:
`scrollbar_mode: “OFF”

scrollable: false`
Wszystko działa tak jak chciałem

2 polubienia