Installing ESPhome on GEEKMAGIC Smart Weather Clock (smalltv/pro)

Yes the flickering is coming from the missing frame buffer…

Without frame buffer each time the display needs to be updated we have to load the entire screen memory with blank, then let the lambda update the screen memory with the content we want to display and write this content for each and every pixel in the memory screen.
The flickering is coming from the those 2 sequential write screen operations and the delay in between …
With frame buffer there is one single write operation to the screen…

To reduce flickering you can specify different ‘update_interval’ value (default is 5s) in the display configuration and/or request the update only on demand from another component with component.update: my_display or lambda 'lambda: ‘id(disp).update();’

Ah, i see. Thanks for the explanation.

There seems to be no option to disable the update_interval. So setting a very high amount of seconds does the trick.

Refresh can be disabled using

update_interval: never

Oooops, you’re right. Thanks again!

Do you want to send a pull request to the ESPhome project?

Yes I’ll share this, but in two different proposals.

The no CS pin with spi mode change will be useful for other hwd implementations and no compatibility or performance concerns .

But the no frame buffer implementation a bit more questionable since its performance is not optimal…

1 Like

Hello everyone,

Just received today a pro version. In case it could be useful, I performed some probing to identify the signals.

The programming connector has same assignment.

For tbe screen the signals are:
DC: gpio02
Sck: gpio18
Mosi: gpio23
Rst: gpio14
Backlight: gpio25

Cs is tight to gnd meaning we’ll have to SPI mode 3 as well to get it working.
Think the previously shared fork of the driver should work. I’ll give a trial tomorrow now…

The touch button is mapped on gpio32

[edit] Pins assignment confirmed as well as functionality with forked drivers. Since heap since is huge on ESP32, frame buffer is kept activated by default and no flickering effect…

3 Likes

FYI, PR raised here for SPI mode fix st7789 using mode3 when no cs pin by rletendu · Pull Request #5541 · esphome/esphome · GitHub

Great, thanks! :+1:

My plus arrived today. Will update any progress.

1 Like

I received my Pro today, any further progress on this topic guys ?

Mine is just sitting on my desk telling me the time.

The pro is working fine on my side. The amount of memory available on this one makes it more confortable. I use it as a small monitor to display on different pages (weather forecast, temperature graph, mailbox…) some key information from my HA.

2 Likes

That’s really cool, I was searching for how can I do something similar, Do you mind sharing your ESPHome config file for your setup !!

Implementation is really tied to your HA entities, but In case it could serve your inspiration, here’s what I end up with

Note the native display page feature of ESP Home is not working on this display type. had to rebuild it manually

esphome:
  name: smalltv-esp32
  friendly_name: smalltv_esp32

esp32:
  board: esp32dev
  framework:
    type: arduino

# Enable logging
logger:

# Enable Home Assistant API
api:
  encryption:
    key: !secret api

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

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Smalltv-Esp32 Fallback Hotspot"
    password: "NOtnhLeYNfPB"

captive_portal:
    

external_components:
  - source:
      type: git
      url: https://github.com/rletendu/esphome.git
      ref: st7789_no_frame_buffer
    refresh: 0s
    components: [st7789v]



#captive_portal:
debug:
  update_interval: 5s

sensor:
  - platform: homeassistant
    entity_id: sensor.abri_bois_am2301_temperature
    id: abri_bois

  - platform: homeassistant
    entity_id: sensor.atc_mez41e_641e_temperature
    id: mezzanine

  - platform: homeassistant
    entity_id: sensor.piscine_temperature
    id: piscine

  - platform: homeassistant
    entity_id: sensor.atc_sal505_6505_temperature
    id: salon

  - platform: homeassistant
    entity_id: sensor.atc_julb28_3b28_temperature
    id: juliette

  - platform: homeassistant
    entity_id: sensor.atc_vic77a_d77a_temperature
    id: victorien

  - platform: homeassistant
    entity_id: sensor.atc_cle63e_a63e_temperature
    id: clemence

  - platform: homeassistant
    entity_id: sensor.atc_sdb80a_880a_temperature
    id: sdb_etage

  - platform: homeassistant
    entity_id: sensor.atc_cui76c_576c_temperature
    id: cuisine

  - platform: homeassistant
    entity_id: sensor.atc_cab2c2_temperature
    id: cabane_ext

  - platform: homeassistant
    entity_id: sensor.garage_temp
    id: garage

  - platform: homeassistant
    entity_id: sensor.nodered_f80113f7800c75ed
    id: girouette



  - platform: homeassistant
    entity_id: weather.varades
    attribute: pressure
    id: pressure_weather

  - platform: homeassistant
    entity_id: sensor.girouette_pression
    id: pressure

  

  - platform: homeassistant
    name: "T_max_day0"
    entity_id: sensor.T_max_day0
    id: T_max_day0
  - platform: homeassistant
    name: "T_max_day1"
    entity_id: sensor.T_max_day1
    id: T_max_day1
  - platform: homeassistant
    name: "T_max_day2"
    entity_id: sensor.T_max_day2
    id: T_max_day2
  - platform: homeassistant
    name: "T_max_day3"
    entity_id: sensor.T_max_day3
    id: T_max_day3
  - platform: homeassistant
    name: "T_max_day4"
    entity_id: sensor.T_max_day4
    id: T_max_day4

  - platform: homeassistant
    name: "T_min_day0"
    entity_id: sensor.T_min_day0
    id: T_min_day0
  - platform: homeassistant
    name: "T_min_day1"
    entity_id: sensor.T_min_day1
    id: T_min_day1
  - platform: homeassistant
    name: "T_min_day2"
    entity_id: sensor.T_min_day2
    id: T_min_day2
  - platform: homeassistant
    name: "T_min_day3"
    entity_id: sensor.T_min_day3
    id: T_min_day3    
  - platform: homeassistant
    name: "T_min_day4"
    entity_id: sensor.T_min_day4
    id: T_min_day4  

  - platform: homeassistant
    name: "Precipitation_day0"
    entity_id: sensor.Precipitation_day0
    id: Precipitation_day0
  - platform: homeassistant
    name: "Precipitation_day1"
    entity_id: sensor.Precipitation_day1
    id: Precipitation_day1
  - platform: homeassistant
    name: "Precipitation_day2"
    entity_id: sensor.Precipitation_day2
    id: Precipitation_day2
  - platform: homeassistant
    name: "Precipitation_day3"
    entity_id: sensor.Precipitation_day3
    id: Precipitation_day3    
  - platform: homeassistant
    name: "Precipitation_day4"
    entity_id: sensor.Precipitation_day4
    id: Precipitation_day4   

  - platform: homeassistant
    name: "index_day0"
    entity_id: sensor.index_day0
    id: index_day0

    

text_sensor:
  - platform: homeassistant
    name: "Condition_day0"
    entity_id: sensor.Condition_day0
    id: Condition_day0
  - platform: homeassistant
    name: "Condition_day1"
    entity_id: sensor.Condition_day1
    id: Condition_day1
  - platform: homeassistant
    name: "Condition_day2"
    entity_id: sensor.Condition_day2
    id: Condition_day2
  - platform: homeassistant
    name: "Condition_day3"
    entity_id: sensor.Condition_day3
    id: Condition_day3        
  - platform: homeassistant
    name: "Condition_day4"
    entity_id: sensor.Condition_day4
    id: Condition_day4   


# Define a PWM output on the ESP32
output:
  - platform: ledc
    pin: GPIO25
    inverted: True
    id: backlight_pwm
  - platform: ledc
    pin: GPIO12
    id: rtttl_out

rtttl:
  output: rtttl_out

# Define a monochromatic, dimmable light for the backlight
light:
  - platform: monochromatic
    output: backlight_pwm
    name: "Display Backlight"
    id: back_light
    restore_mode: ALWAYS_ON


esp32_touch:
 # setup_mode: true


globals:
- id: page
  type: int
  initial_value: "1"

interval:
  - interval: 20s
    then:
      - lambda: |-
          /*
          id(page) = (id(page) + 1);
          if (id(page) > 3) {
            id(page) = 1;
          } */


binary_sensor:

  - platform: homeassistant
    entity_id: binary_sensor.status_porte_garage
    id: porte_garage

  - platform: homeassistant
    entity_id: binary_sensor.portail_lock_sense
    id: portail  
  - platform: esp32_touch
    name: "ESP32 Touch Pad GPIO32"
    pin: GPIO32
    threshold: 1250
    id: gp32
    on_click:
    - min_length: 50ms
      max_length: 350ms
      then:
        - if:
            condition:
            - light.is_off: back_light
            then:
            - light.turn_on: 
                id: back_light
            else:
              - lambda: |-
                    id(page) = (id(page) + 1);
                    if (id(page) > 3) {
                      id(page) = 1;
                    }
              - component.update : disp

    - min_length: 1000ms
      max_length: 2000ms
      then:
        - light.turn_off: back_light
        - rtttl.play: 'two_short:d=4,o=5,b=100:16e6,16e6'

  - platform: esp32_touch
    name: "ESP32 Touch Pad GPIO33"
    pin: GPIO33
    threshold: 1375
    id: gp33
    on_click:
    - min_length: 50ms
      max_length: 350ms
      then:

        - if:
            condition:
            - light.is_off: back_light
            then:
            - light.turn_on: 
                id: back_light
            else:
              - lambda: |-
                    id(page) = (id(page) - 1);
                    if (id(page) < 1) {
                      id(page) = 3;
                    } 
              - component.update : disp
    - min_length: 1000ms
      max_length: 2000ms
      then:
        - light.turn_off: back_light


number:
  - platform: template
    name: "disp page"
    optimistic: true
    min_value: 0
    max_value: 4
    step: 1
    on_value:
      then:
        - lambda: |-
            id(page) = x;
        - component.update : disp



font:
  - file: 'OpenSans-Regular.ttf'
    id: font20
    size: 20

  - file: 'OpenSans-Regular.ttf'
    id: font60
    size: 50

  - file: 'fonts/materialdesignicons-webfont.ttf'
    id: fonticon
    size: 50
    glyphs: &mdi-weather-glyphs
      - "\U000F0590" # mdi-weather-cloudy
      - "\U000F0F2F" # mdi-weather-cloudy-alert
      - "\U000F0E6E" # mdi-weather-cloudy-arrow-right
      - "\U000F0591" # mdi-weather-fog
      - "\U000F0592" # mdi-weather-hail
      - "\U000F0F30" # mdi-weather-hazy
      - "\U000F0898" # mdi-weather-hurricane
      - "\U000F0593" # mdi-weather-lightning
      - "\U000F067E" # mdi-weather-lightning-rainy
      - "\U000F0594" # mdi-weather-night
      - "\U000F0F31" # mdi-weather-night-partly-cloudy
      - "\U000F0595" # mdi-weather-partly-cloudy
      - "\U000F0F32" # mdi-weather-partly-lightning
      - "\U000F0F33" # mdi-weather-partly-rainy
      - "\U000F0F34" # mdi-weather-partly-snowy
      - "\U000F0F35" # mdi-weather-partly-snowy-rainy
      - "\U000F0596" # mdi-weather-pouring
      - "\U000F0597" # mdi-weather-rainy
      - "\U000F0598" # mdi-weather-snowy
      - "\U000F0F36" # mdi-weather-snowy-heavy
      - "\U000F067F" # mdi-weather-snowy-rainy
      - "\U000F0599" # mdi-weather-sunny
      - "\U000F0F37" # mdi-weather-sunny-alert
      - "\U000F14E4" # mdi-weather-sunny-off
      - "\U000F059A" # mdi-weather-sunset
      - "\U000F059B" # mdi-weather-sunset-down
      - "\U000F059C" # mdi-weather-sunset-up
      - "\U000F0F38" # mdi-weather-tornado
      - "\U000F059D" # mdi-weather-windy
      - "\U000F059E" # mdi-weather-windy-variant
      - "\U000F058C" # mdi-water
      - "\U000F17FB" # mdi-GarageLock
      - "\U000F06DA" # mdi-GarageOpen      
      - "\U000F116A" # mid-GateOpen
      - "\U000F0299" # mdi-GateClose
      - "\U000F06EE" # mdi-mailbox
      - "\U000F0A79" # mdi-trash-can
      - "\U000F001B" # mdi-Air-conditioner
      - "\U000F0D91" # mdi-MotionSensor-ON
      - "\U000F1435" # mdi-MotionSensor-Off

  - file: 'fonts/materialdesignicons-webfont.ttf'
    id: fonticon20
    size: 20
    glyphs: &mdi-weather-glyphs20
      - "\U000F058C" # mdi-water
      - "\U000F005C" # mdi-ArrowTopRight
      - "\U000F0043" # mdi-ArrowBottomRight"
      - "\U000F092B" # no-wifi
      - "\U000F092F" # low-wifi
      - "\U000F091F" # wifi-1
      - "\U000F0922" # wifi-2
      - "\U000F0925" # wifi-3
      - "\U000F0928" # wifi-4

color:
    - id: color_green
      red: 0%
      green: 100%
      blue: 0%
    - id: color_red
      red: 100%
      green: 0%
      blue: 0%
    - id: color_blue
      red: 0%
      green: 0%
      blue: 100%
    - id: color_orange
      red: 100%
      green: 64%
      blue: 0%

spi:
  clk_pin: GPIO18
  mosi_pin: GPIO23
  interface: hardware
  id: spihwd

graph:

  - id: pressure_graph
    sensor: pressure
    duration: 24h
    width: 180
    height: 100
    color: color_orange
  - id: multi_temperature_graph
    duration: 24h
    width: 180
    height: 100
    traces:
      - sensor: abri_bois
        line_type: DOTTED
        color: color_blue
      - sensor: salon
        line_type: SOLID
        color: color_green

  

display:
  - platform: st7789v
    model: "Custom"
    spi_id: spihwd
    height: 240
    width: 240
    offset_height: 0
    offset_width: 0
    dc_pin: GPIO02
    reset_pin: GPIO04
    #backlight_pin: GPIO25
    eightbitcolor: True
    #update_interval: never
    update_interval: 5s
    id: disp


    lambda: |-
          int y;
          int x;

          //--------------------------------------------------------------------------
          // Map weather states to MDI characters.
          //--------------------------------------------------------------------------
          std::map<std::string, std::string> weather_icon_map
            {
              {"cloudy", "\U000F0590"},
              {"cloudy-alert", "\U000F0F2F"},
              {"cloudy-arrow-right", "\U000F0E6E"},
              {"fog", "\U000F0591"},
              {"hail", "\U000F0592"},
              {"hazy", "\U000F0F30"},
              {"hurricane", "\U000F0898"},
              {"lightning", "\U000F0593"},
              {"lightning-rainy", "\U000F067E"},
              {"night", "\U000F0594"},
              {"clear-night", "\U000F0594"},
              {"night-partly-cloudy", "\U000F0F31"},
              {"partlycloudy", "\U000F0595"},
              {"partly-lightning", "\U000F0F32"},
              {"partly-rainy", "\U000F0F33"},
              {"partly-snowy", "\U000F0F34"},
              {"partly-snowy-rainy", "\U000F0F35"},
              {"pouring", "\U000F0596"},
              {"rainy", "\U000F0597"},
              {"snowy", "\U000F0598"},
              {"snowy-heavy", "\U000F0F36"},
              {"snowy-rainy", "\U000F067F"},
              {"sunny", "\U000F0599"},
              {"sunny-alert", "\U000F0F37"},
              {"sunny-off", "\U000F14E4"},
              {"sunset", "\U000F059A"},
              {"sunset-down", "\U000F059B"},
              {"sunset-up", "\U000F059C"},
              {"tornado", "\U000F0F38"},
              {"windy", "\U000F059D"},
              {"windy-variant", "\U000F059E"},
            };

          std::string weekdays[7]={"Lun","Mar","Mer","Jeu","Ven","Sam","Dim"};


          switch (id(page)){

            default:
            case 0:
            case 1:
              it.printf(0, 0, id(font60),  "%.1f°",id(abri_bois).state);
              if (id(Precipitation_day0).state) {
                it.printf(130, 5, id(fonticon20), id(color_blue),"\U000F058C");
                it.printf(145, 0, id(font20), id(color_blue),"%.0f",id(Precipitation_day0).state);
              }
              it.printf(130, 20, id(font20), id(color_red), "%.0f°",id(T_max_day0).state);
              it.printf(130, 40, id(font20), id(color_green), "%.0f°",id(T_min_day0).state);
              it.printf(190, 20, id(fonticon), "%s", weather_icon_map[id(Condition_day0).state.c_str()].c_str());

              it.printf(0, 60, id(font20), id(color_orange), "%.0fhPa",id(pressure).state);

              // Days name for forecast
              y = 100;
              x = 5; 
              it.printf(x, y, id(font20), "%s", weekdays[(int)(id(index_day0).state+1)%7].c_str());
              x += 60;
              it.printf(x, y, id(font20), "%s", weekdays[(int)(id(index_day0).state+2)%7].c_str());
              x += 60;
              it.printf(x, y, id(font20), "%s", weekdays[(int)(id(index_day0).state+3)%7].c_str());
              x += 60;
              it.printf(x, y, id(font20), "%s", weekdays[(int)(id(index_day0).state+4)%7].c_str());

              //Forecast 

              // Day +1
              y = 122;
              x = 5;
              it.printf(x, y, id(fonticon), "%s", weather_icon_map[id(Condition_day1).state.c_str()].c_str());
              it.printf(x, y+40, id(font20), id(color_red), "%.0f°",id(T_max_day1).state);
              it.printf(x, y+60, id(font20), id(color_green), "%.0f°",id(T_min_day1).state);
              if (id(Precipitation_day1).state) {
                it.printf(x, y+85, id(fonticon20), id(color_blue),"\U000F058C");
                it.printf(x+15, y+80, id(font20), id(color_blue),"%.0f",id(Precipitation_day1).state);
              }

              // Day + 2
              x += 60;
              it.printf(x, y, id(fonticon), "%s", weather_icon_map[id(Condition_day2).state.c_str()].c_str());
              it.printf(x, y+40, id(font20), id(color_red), "%.0f°",id(T_max_day2).state);
              it.printf(x, y+60, id(font20), id(color_green), "%.0f°",id(T_min_day2).state);
              if (id(Precipitation_day2).state) {
                it.printf(x, y+85, id(fonticon20), id(color_blue),"\U000F058C");
                it.printf(x+15, y+80, id(font20), id(color_blue),"%.0f",id(Precipitation_day2).state);
              }

              // Day + 3
              x += 60;
              it.printf(x, y, id(fonticon), "%s", weather_icon_map[id(Condition_day3).state.c_str()].c_str());
              it.printf(x, y+40, id(font20), id(color_red), "%.0f°",id(T_max_day3).state);
              it.printf(x, y+60, id(font20), id(color_green), "%.0f°",id(T_min_day3).state);
              if (id(Precipitation_day3).state) {
                it.printf(x, y+85, id(fonticon20), id(color_blue),"\U000F058C");
                it.printf(x+15, y+80, id(font20), id(color_blue),"%.0f",id(Precipitation_day3).state);
              }

              // Day + 4
              x += 60;
              it.printf(x, y, id(fonticon), "%s", weather_icon_map[id(Condition_day4).state.c_str()].c_str());
              it.printf(x, y+40, id(font20), id(color_red), "%.0f°",id(T_max_day4).state);
              it.printf(x, y+60, id(font20), id(color_green), "%.0f°",id(T_min_day4).state);
              if (id(Precipitation_day4).state) {
                it.printf(x, y+85, id(fonticon20), id(color_blue),"\U000F058C");
                it.printf(x+15, y+80, id(font20), id(color_blue),"%.0f",id(Precipitation_day4).state);
              }
              break;

            case 2:
              x = 5;
              y = 0;

              it.printf(x, y, id(font20),  "Abri");
              it.printf(x, y+20, id(font20), "%.1f°",id(abri_bois).state);
              x += 60;
              it.printf(x, y, id(font20),  "CabE.");
              it.printf(x, y+20, id(font20), "%.1f°",id(cabane_ext).state);
              x += 60;
              it.printf(x, y, id(font20),  "Gir.");
              it.printf(x, y+20, id(font20), "%.1f°",id(girouette).state);
              x += 60;
              it.printf(x, y, id(font20),  "Pisc.");
              it.printf(x, y+20, id(font20), "%.1f°",id(piscine).state);


              x = 5;
              y = 50;
              it.printf(x, y, id(font20),  "Juju");
              it.printf(x, y+20, id(font20), "%.1f°",id(juliette).state);
              x += 60;
              it.printf(x, y, id(font20),  "Clem");
              it.printf(x, y+20, id(font20), "%.1f°",id(clemence).state);
              x += 60;
              it.printf(x, y, id(font20),  "Vict");
              it.printf(x, y+20, id(font20), "%.1f°",id(victorien).state);
              x += 60;
              it.printf(x, y, id(font20),  "Sdb Et.");
              it.printf(x, y+20, id(font20), "%.1f°",id(sdb_etage).state);


              x = 5;
              y = 100;
              it.printf(x, y, id(font20),  "Mezz");
              it.printf(x, y+20, id(font20), "%.1f°",id(mezzanine).state);
              x += 60;
              it.printf(x, y, id(font20),  "Salon");
              it.printf(x, y+20, id(font20), "%.1f°",id(salon).state);
              x += 60;
              it.printf(x, y, id(font20),  "Cuis.");
              it.printf(x, y+20, id(font20), "%.1f°",id(cuisine).state);
              x += 60;
              it.printf(x, y, id(font20),  "Garge");
              it.printf(x, y+20, id(font20), "%.1f°",id(garage).state);

              x = 5;
              y = 150;
              it.printf(x, y, id(font20),  "Garge");
              if (id(porte_garage).state) {
                it.printf(x, y+20, id(fonticon),id(color_green), "\U000F06DA"); // Open
              } else {
                it.printf(x, y+20, id(fonticon),id(color_red), "\U000F17FB"); // Lock
              }
              x += 60;
              it.printf(x, y, id(font20),  "Portail");
              if (id(portail).state) {
                it.printf(x, y+20, id(fonticon),id(color_green), "\U000F116A"); // Gate Open
              } else {
                it.printf(x, y+20, id(fonticon),id(color_red), "\U000F0299"); // Gate Lock
              }


              break;

            case 3:
              
              it.graph(0, 0, id(pressure_graph));
              it.printf(190, 0, id(font20), id(color_orange), "%.0f",id(pressure).state);
              it.printf(190, 20, id(font20), id(color_orange), "hPa");


              it.graph(0, 120, id(multi_temperature_graph));
              it.printf(190, 120, id(font20), id(color_blue),  "Ext");
              it.printf(190, 140, id(font20), id(color_blue),  "%.1f°",id(abri_bois).state);

              it.printf(190, 160, id(font20), id(color_green),  "Int");
              it.printf(190, 180, id(font20), id(color_green),  "%.1f°",id(salon).state);
              break;


          }



9 Likes

Hello! Interesting topic! :star_struck:
I ask for a feature request which it can be helpful and funny as well. Please have a look and if you find it interesting or you have better suggestions please to vote or add a comment. :wink:

Well you don’t need that now do you. Just use esphome

1 Like

Answered my own question: see below.

How are you guys flashing these devices? I have SmallTV Pro (so the esp32 device). When I plug it into USB of the esphome server (a linux x86 box) or into my windows laptop it doesn’t seem to register a serial device. (Using the same cable etc I can see other devices).

Do I perhaps have to disassemble it and plug a flasher device in? I haven’t had to do that in a while. Or perhaps the original firmware can upload an esphome firmware vis OTA in some fashion?

Tips appreciated :slight_smile:

Here is how - if you compile the firmware on esphome and download the bin file in legacy format it can be flashed using the inbuilt firmware updater on the SmallTV Pro.

2 Likes

Just a heads up on @rletendu’s code for the display. I have been playing around over the last couple of days using esphome 2023.12.5 and home assistant 2024.1.0b3 (yes the dreaded beta test version).

esphome 2023.12.5 does not seem to work on @rletendu’s github code, and after reading this PR st7789 using mode3 when no cs pin by rletendu · Pull Request #5541 · esphome/esphome · GitHub I realised that the spi change should be done in the config of the st7789v component in your esphome yaml. In other words, take out the external_component code from what @rletendu’s config in Post 34 above and use this in the display code

display:
  - platform: st7789v
    model: "Custom"
    spi_id: spihwd
    height: 240
    width: 240
    offset_height: 0
    offset_width: 0
    dc_pin: GPIO02
    reset_pin: GPIO04
    #backlight_pin: GPIO25
    eightbitcolor: True
    #update_interval: never
    update_interval: 5s
    id: disp
    spi_mode: mode3

The change is the last line spi_mode: mode3

Hope that helps someone, my device now at least says “Hello World” :slight_smile:

PS no detraction from @rletendu’s work, he worked out the problems and did all the work. I think esphome changed the rules of engagement :slight_smile:

Hello, sorry for my english. Have you the good code for use this module with this screen ?
Thank you

Read the thread, he posted the code, but also see my recent updating post.