Skip to content
Aux fils des idées Français
Vigie · M5Stack · no Home Assistant

Vigie on the M5Stack Tab5

The 5-inch tablet as a standalone alert display: the world map of current hazards, the five most severe and the weather of your zones, at 1280 × 720. ESPHome without Home Assistant: the screen fetches its data by itself, over Wi-Fi.

The Vigie screen on the M5Stack Tab5 at 1280 × 720: status bar, world map with current hazards, list of the five most severe and weather panel
Screen
5", 1280 × 720
Firmware
ESPHome 2026.9.1+, LVGL
Home Assistant
Not needed
Data
Vigie API, every minute
Status
ST7121 tested on 2026-10-28

Vigie does not replace official warnings: always follow the instructions of your authorities.

What the screen shows

The Waveshare 7B layout, scaled up by 20 % to fill the Tab5's sharper screen: the status bar (link to the API, date and time of the zone), the world map with hazards as dots coloured by severity, the five most severe with their distance and direction, and the weather panel of the zone. Touch the panel to go to the next zone.

Each part in detail, and what the screen does when the API stops answering: the Vigie alert display.

The three versions of the Tab5

M5Stack changed the chip that drives the display and the touch twice; each one is picked at build time.

  • ST7121 (since 2026-04-28): Vigie has run on one since 2026-10-28, Wi-Fi and data from the public API over HTTPS.
  • ST7123 (2025-10-14 to 2026-04-28): compiled, not yet run with Vigie on a tablet.
  • ILI9881C (the first one, 2025-05-09 to 2025-10-14): compiled, never run.

The chip is printed on the back of the tablet, above the Espressif logo; how to tell, and the traps: the versions of the Tab5.

The ESPHome configuration, without Home Assistant

No api: component: nothing links the screen to Home Assistant. Wi-Fi is given after the install (Improv over USB, or the access point the screen opens by itself), the data comes through http_request and LVGL draws it.

Below, a short, complete example on the same hardware base as Vigie: it shows the temperature and the weather warning of a place, read from the public Vigie API. Pick your Tab5's chip at the top of the file; change the latitude and longitude, or the address, to read another API.

tab5-standalone.yamlGitHub
# M5Stack Tab5 with ESPHome, without Home Assistant: display, touch, Wi-Fi and backlight, and
# the screen reads a web API by itself to show the temperature and the weather warning of a
# place (the /v1/point route of the public Vigie API). Pins and settings of the Vigie display
# firmware, which runs on a Tab5 ST7121; this example itself is compiled with ESPHome 2026.9.1
# but not tried as is.
substitutions:
  # The display chip is printed on the back of the Tab5, above the Espressif logo:
  #   ST7123   : M5STACK-TAB5-ST7123, touch st7123, 100ms
  #   ST7121   : M5STACK-TAB5-ST7121, touch st7123, 100ms
  #   ILI9881C : M5STACK-TAB5,        touch gt911,  never
  panel_model: M5STACK-TAB5-ST7123
  touch_chip: st7123
  touch_interval: 100ms
  # The place shown (Paris here).
  latitude: "48.86"
  longitude: "2.35"

esphome:
  name: tab5-standalone
  friendly_name: Tab5 standalone
  min_version: 2026.9.0
  on_boot:
    # The panel reset goes through a PI4IOE5V6408 I/O expander, which needs a second after
    # start-up: without this wait, black screen after a software restart. A C delay(): ESPHome's
    # "delay:" does not hold the display setup back.
    - priority: 700
      then:
        - lambda: "delay(1000);"

esp32:
  board: esp32-p4-evboard
  flash_size: 16MB
  framework:
    type: esp-idf
    advanced:
      enable_idf_experimental_features: true
      execute_from_psram: true

# 32 MB of PSRAM, where LVGL keeps the whole picture (buffer_size: 100% below).
psram:
  mode: hex
  speed: 200MHz

# Wi-Fi is on a second chip, an ESP32-C6, linked over SDIO. Its reset is active high:
# active_high: false gives "sdmmc_card_init failed".
esp32_hosted:
  variant: esp32c6
  active_high: true
  clk_pin: GPIO12
  cmd_pin: GPIO13
  d0_pin: GPIO11
  d1_pin: GPIO10
  d2_pin: GPIO9
  d3_pin: GPIO8
  reset_pin: GPIO15
  slot: 1
  sdio_frequency: 20MHz
  use_psram: true

# No "api:": nothing links the screen to Home Assistant. No password in the file: Wi-Fi is given
# after the install, over USB (Improv, from ESPHome Web) or through the "Tab5 setup" access
# point and its settings page.
wifi:
  ap:
    ssid: "Tab5 setup"

improv_serial:

captive_portal:

ota:
  - platform: esphome

logger:
  hardware_uart: USB_SERIAL_JTAG

# One I2C bus for the touch, the two I/O expanders and the audio chips.
i2c:
  - id: bsp_bus
    sda: GPIO31
    scl: GPIO32
    frequency: 400kHz

pi4ioe5v6408:
  - id: pi4ioe1
    address: 0x43
  - id: pi4ioe2
    address: 0x44

# Power rails behind the expanders. "wifi_power" feeds the ESP32-C6: the expander starts off,
# and without this the Wi-Fi never comes up ("sdmmc_card_init failed"). The charger stays off,
# as with no battery.
switch:
  - platform: gpio
    id: wifi_power
    pin:
      pi4ioe5v6408: pi4ioe2
      number: 0
    restore_mode: ALWAYS_ON
  - platform: gpio
    id: usb_5v_power
    pin:
      pi4ioe5v6408: pi4ioe2
      number: 3
    restore_mode: ALWAYS_ON
  - platform: gpio
    id: external_5v_power
    pin:
      pi4ioe5v6408: pi4ioe1
      number: 2
    restore_mode: ALWAYS_ON
  - platform: gpio
    id: charge_enable
    pin:
      pi4ioe5v6408: pi4ioe2
      number: 7
    restore_mode: ALWAYS_OFF

# Supply of the display's MIPI-DSI link: LDO 3 at 2.5 V.
esp_ldo:
  - voltage: 2.5V
    channel: 3

# The panel is portrait (720 × 1280): LVGL turns it to landscape below.
display:
  - id: panel
    platform: mipi_dsi
    model: ${panel_model}
    dimensions:
      width: 720
      height: 1280
    reset_pin:
      pi4ioe5v6408: pi4ioe1
      number: 4
    pixel_mode: 16bit
    color_order: RGB
    update_interval: never
    auto_clear_enabled: false

# Same pins on the three versions. No mirroring (it corrupts the picture on an ST7121): LVGL
# turns the touches with the picture.
touchscreen:
  - id: touch
    platform: ${touch_chip}
    update_interval: ${touch_interval}
    interrupt_pin: GPIO23
    reset_pin:
      pi4ioe5v6408: pi4ioe1
      number: 5
    calibration:
      x_min: 0
      x_max: 720
      y_min: 0
      y_max: 1280

output:
  - platform: ledc
    id: backlight_pwm
    pin: GPIO22
    frequency: 1000Hz

light:
  - platform: monochromatic
    id: backlight
    name: "Backlight"
    output: backlight_pwm
    restore_mode: RESTORE_DEFAULT_ON

# The screen fetches its data by itself, over HTTPS. verify_ssl: false: the server certificate
# is not checked, as in Vigie display; fine for public data, never for a password.
http_request:
  id: web
  timeout: 8s
  verify_ssl: false

interval:
  # /v1/point takes 10 requests per minute and per address: one every 5 minutes is plenty.
  - interval: 5min
    startup_delay: 10s
    then:
      - if:
          condition:
            wifi.connected:
          then:
            - http_request.get:
                url: "https://vigie.auxfilsdesidees.fr/v1/point?lat=${latitude}&lon=${longitude}"
                capture_response: true
                max_response_buffer_size: 16384
                on_response:
                  then:
                    - lambda: |-
                        if (response->status_code != 200) {
                          ESP_LOGW("exemple", "HTTP %d", response->status_code);
                          return;
                        }
                        json::parse_json(body, [](JsonObject root) -> bool {
                          // Highest weather warning at the point: GREEN, YELLOW, ORANGE or RED.
                          std::string level = root["local_alert_level"] | "";
                          const char *text = "No warning";
                          uint32_t colour = 0x3FA34D;
                          if (level == "YELLOW") { text = "Yellow warning"; colour = 0xF2C230; }
                          if (level == "ORANGE") { text = "Orange warning"; colour = 0xF08A24; }
                          if (level == "RED") { text = "Red warning"; colour = 0xE5484D; }
                          lv_label_set_text(id(level_label), text);
                          lv_obj_set_style_text_color(id(level_label), lv_color_hex(colour), LV_PART_MAIN);
                          // A missing value stays missing: nothing is made up.
                          JsonVariant temperature = root["current"]["temp_c"];
                          if (temperature.is<float>()) {
                            char value[16];
                            snprintf(value, sizeof(value), "%.1f °C", temperature.as<float>());
                            lv_label_set_text(id(temperature_label), value);
                          }
                          return true;
                        });
                on_error:
                  then:
                    - logger.log: "No answer (network or timeout)"

# LVGL's built-in fonts have no accented letters: Roboto, downloaded at build time (it only
# lacks combining accents, hence ignore_missing_glyphs).
font:
  - file: "gfonts://Roboto"
    id: font_text
    size: 32
    glyphsets: [GF_Latin_Core]
    ignore_missing_glyphs: true
  - file: "gfonts://Roboto@700"
    id: font_big
    size: 80
    glyphsets: [GF_Latin_Core]
    ignore_missing_glyphs: true

lvgl:
  displays: [panel]
  touchscreens: [touch]
  rotation: 270
  color_depth: 16
  byte_order: little_endian
  buffer_size: 100%
  default_font: font_text
  pages:
    - id: home_page
      widgets:
        - label:
            id: temperature_label
            align: CENTER
            y: -60
            text: "--"
            text_font: font_big
        - label:
            id: level_label
            align: CENTER
            y: 80
            text: "Waiting for data"

Validated and compiled with ESPHome 2026.9.1 on 2026-10-28, not yet tried as is on the tablet: its hardware settings are those of Vigie display, which runs on a Tab5 ST7121.

The settings that matter on this tablet

  • The ESP32-C6, which carries the Wi-Fi, is powered through an I/O expander (PI4IOE5V6408, pin 0 of the second one): without the wifi_power switch turned on at start-up, the SDIO link never comes up ("sdmmc_card_init failed", seen on an ST7121 on 2026-10-28). Its reset, GPIO15, is active high.
  • The panel reset goes through the other expander, which needs a second after start-up: without the wait in on_boot, black screen after a software restart. It has to block, hence the C delay().
  • The panel is portrait (720 × 1280): LVGL turns it to landscape with rotation: 270, and turns the touches with it.
  • No mirroring on the display or the touch: it corrupts the picture on an ST7121.
  • The MIPI-DSI link is powered by LDO 3 of the ESP32-P4, at 2.5 V (esp_ldo).
  • The display model and the touch chip change with the version: M5STACK-TAB5-ST7123 or -ST7121 with the st7123 touch, M5STACK-TAB5 with the gt911 for the ILI9881C.

The full firmware

vigie.yaml puts packages together: the tablet hardware (board-tab5.yaml, power rails and charger included), the size of the screen, the world map and the fonts (layout-tab5.yaml), the LVGL screen, drawn in C++, and the API client: one request a minute, a frame refused if its size or checksum does not match.

Install Vigie

No published release to install from the browser yet: you build the firmware yourself. Allow half an hour, mostly for the first build.

  1. Install ESPHome 2026.9.1 or newer and get the vigie-display repository.
  2. Create a signing key: once installed, the screen only accepts updates signed with the same key. Keep a copy.
  3. Build for the Tab5: esphome -s vigie_board tab5 -s vigie_api_url https://vigie.auxfilsdesidees.fr -s vigie_signing_key vigie_signing_key.pem compile vigie.yaml. With an ST7121, add -s board_tab5_panel M5STACK-TAB5-ST7121; with an ILI9881C, -s board_tab5_panel M5STACK-TAB5 -s board_tab5_touch gt911 -s board_tab5_touch_interval never. Then install over USB with ESPHome or from ESPHome Web.
  4. Give it Wi-Fi over USB (Improv) or through the "Vigie setup" access point the screen opens after a minute. Within a minute, the status bar reads "Up to date".

Settings and common problems are in the installation guide. Later updates go over Wi-Fi. The same tablet as a Home Assistant display: the M5Stack Tab5.