Here’s a fun proof of concept config for the M5Stack Atom S3, showing off some animated gifs. You can use any 128x128 pixel gifs but keep in mind that they take up a ton of space in the firmware image. The code simply loops through the list of gifs, changing every 6 seconds.
This method should work for other esp32s3 devices with displays.
esphome:
name: atoms3
friendly_name: AtomS3
platformio_options:
board_upload.maximum_ram_size: 327680
board_upload.maximum_size: 8388608
on_boot:
- priority: 800
then:
- lambda: |-
id(disp).enable();
id(disp).transfer_byte(0x11);
id(disp).disable();
esp32:
board: m5stack-atoms3
variant: esp32s3
flash_size: 8MB
framework:
type: esp-idf
version: 5.1.1
platform_version: 6.4.0
# Enable logging
logger:
level: ERROR
# Enable Home Assistant API
api:
encryption:
key: "<YOURKEYHERE>"
ota:
password: "<YOUROTAPASSWORD>"
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
substitutions:
name: "atoms3"
device_name: "AtomS3"
# esp32_ble_tracker:
# bluetooth_proxy:
# active: true
#G4=IR
# remote_transmitter:
# pin: GPIO4
# carrier_duty_percent: 50%
i2c:
- id: bus_a
sda: GPIO38
scl: GPIO39
sensor:
- platform: mpu6886
address: 0x68
accel_x:
name: "$device_name MPU6886 Accel X"
accel_y:
name: "$device_name MPU6886 Accel Y"
accel_z:
name: "$device_name MPU6886 Accel z"
gyro_x:
name: "$device_name MPU6886 Gyro X"
gyro_y:
name: "$device_name MPU6886 Gyro Y"
gyro_z:
name: "$device_name MPU6886 Gyro z"
temperature:
name: "$device_name MPU6886 Temperature"
spi:
clk_pin: GPIO17
mosi_pin: GPIO21
# color:
# - id: my_red
# red: 100%
# green: 0%
# blue: 0%
# - id: my_yellow
# red: 100%
# green: 100%
# blue: 0%
# - id: my_green
# red: 0%
# green: 100%
# blue: 0%
# - id: my_blue
# red: 0%
# green: 0%
# blue: 100%
# - id: my_gray
# red: 50%
# green: 50%
# blue: 50%
font:
- file: "gfonts://Roboto"
id: roboto_32
# size: 32
# - file: "gfonts://Roboto"
# id: roboto_24
# size: 24
# - file: "gfonts://Roboto"
# id: roboto_12
# size: 12
time:
- platform: homeassistant
id: esptime
globals:
- id: current
type: int
restore_value: no
initial_value: '0'
- id: last_loop_time
type: uint32_t
restore_value: no
initial_value: '0'
- id: gifs
type: std::vector<esphome::animation::Animation*>
restore_value: no
animation:
- file: "_gifs_128x128/mariokart.gif"
id: mariokart
type: RGB565
resize: 128x128
- file: "_gifs_128x128/blinky.gif"
id: blinky
type: RGB565
resize: 128x128
- file: "_gifs_128x128/bmo.gif"
id: bmo
type: RGB565
resize: 128x128
- file: "_gifs_128x128/clyde.gif"
id: clyde
type: RGB565
resize: 128x128
- file: "_gifs_128x128/peach.gif"
id: peach
type: RGB565
resize: 128x128
- file: "_gifs_128x128/megaman.gif"
id: megaman
type: RGB565
resize: 128x128
- file: "_gifs_128x128/kirby.gif"
id: kirby
type: RGB565
resize: 128x128
- file: "_gifs_128x128/galaga.gif"
id: galaga
type: RGB565
resize: 128x128
interval:
- interval: 0.2s
then:
lambda: |-
id(gifs) = {
id(mariokart),
id(blinky),
id(bmo),
id(clyde),
id(peach),
id(megaman),
id(kirby),
id(galaga)
};
id(gifs)[id(current)]->next_frame();
display:
- platform: st7789v # https://esphome.io/components/display/st7789v.html
id: disp
model: Custom
rotation: 180
backlight_pin: GPIO16
cs_pin: GPIO15
dc_pin: GPIO33
reset_pin: GPIO34
height: 128
width: 128
offset_height: 2
offset_width: 1
eightbitcolor: true
update_interval: 0.2s
lambda: |-
uint32_t current_time = id(esptime).now().timestamp;
uint32_t elapsed_time = current_time - id(last_loop_time);
if (elapsed_time >= 6) {
id(current) = (id(current) + 1) % id(gifs).size();
id(last_loop_time) = current_time;
}
it.image(0, 0, id(gifs)[id(current)], COLOR_ON, COLOR_OFF);
#G41=Button
binary_sensor:
- platform: status
name: "Node Status"
id: system_status
- platform: gpio
name: Button
pin:
number: GPIO41
inverted: true
mode:
input: true
pullup: true
filters:
- delayed_off: 10ms
on_press:
then:
- logger.log: Button Pressed