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

New approach to get rid of the flickering on ESP8266: Fractional framebuffer.

Allocates only 1/N of the total display area, and calls the drawing code N times.

This is based on the behavior of u8glib.

Pros:

  • No flicker.
  • Lower RAM usage.
  • Faster than framebuffer-less approach.

Cons:

  • Slower than full framebuffer: ~100ms on the example.
  • Side effects on display lambda are triggered multiple times: framecounter will skip 0…3…6…9… in the example.

Hot to test:

  • Bump the ESP8266 to 160MHz, for speed improvements (see platformio_options in the example).
  • Bump the SPI to 40MHz (see data_rate in the example).
  • Make sure your lambda has no side-effects, i.e., does not change variables.
  • Setup external_components as in the example.
  • Add fragmentation: 3 or more to the display entry.

Tried fragmentation: 2 and it works, but gets out-of-memory exceptions later on. Keep an eye on the logs, and increase fragmentation if you notice OOM resets.

BTW, also took the chance to specialize fill(color) as it makes a huge difference, with the example dropping from 330ms to 101ms.

esphome:
  name: geekmagic-smalltv-01
  friendly_name: geekmagic-smalltv-01
  platformio_options: 
    board_build.f_cpu: 160000000L

esp8266:
  board: esp12e

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

# ommited common wifi and OTA ettings

font:
  - file: "gfonts://Roboto"
    id: roboto
    size: 20

spi:
  clk_pin: GPIO14
  mosi_pin: GPIO13
  interface: hardware
  id: spihwd

output:
  - platform: esp8266_pwm
    inverted: true
    pin: GPIO05
    frequency: 1000 Hz
    id: pwm_output

light:
  - platform: monochromatic
    output: pwm_output
    name: "Backlight"

interval:
  - interval: 100ms
    then:
      - component.update: my_display

color:
  - id: color_green
    red: 0%
    green: 100%
    blue: 0%

display:
  - id: my_display
    platform: st7789v
    model: custom
    spi_id: spihwd
    height: 240
    width: 240
    offset_height: 0
    offset_width: 0
    fragmentation: 3
    dc_pin: GPIO00
    reset_pin: GPIO02
    eightbitcolor: True
    update_interval: 20s
    spi_mode: mode3
    lambda: |-
      // Calculate the center positions
      int center_x = it.get_width() / 2;
      int center_y = it.get_height() / 2;

      // Print "Hello World" centered
      it.printf(center_x, center_y-20, id(roboto), id(color_green), TextAlign::CENTER, "Hello World");

      // This is a bad-example, to demonstrate side-effect multiplication.
      // With even fragmentation this is cut in half, with k on top and k+1 below.
      static int framecounter = 0;
      it.printf(center_x, center_y, id(roboto), TextAlign::CENTER, "%d", framecounter++);
5 Likes