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_optionsin the example). - Bump the SPI to 40MHz (see
data_ratein the example). - Make sure your
lambdahas no side-effects, i.e., does not change variables. - Setup
external_componentsas in the example. - Add
fragmentation: 3or more to thedisplayentry.
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++);