Turn M5Stack Tab5 into a Portable Home Assistant Control Panel

Today, we are going to integrate the M5Stack TAB5 into Home Assistant (HA), a very interesting device for creating a portable control dashboard.

 

M5Stack Tab5

 

·        Powered by an ESP32-P4 SoC, with 16MB of flash memory and 32MB of PSRAM. This makes it the device with the most memory we have integrated into Home Assistant to date.

·        It features a generous 5″ TFT touchscreen (1280×720), compatible with LVGL.

·        Includes a front-facing 2 MP SC2356 camera (1600×1200) for capturing images and video.

·        Equipped with one USB-A port, one USB-C port, and a Micro SD card slot (card not included).

·        It has two expansion ports for external sensors (GROVE and M5BUS) and a connector for a LoRa antenna.

·        Features two microphones, a speaker, and a 3.5mm jack, meaning you can also use it to control Assist.

·        If you chose the "TAB5 Kit," it comes with a Li-ion battery that you can easily replace (allowing you to have a spare one charged and ready).

 

In short, these characteristics make it the perfect candidate for a portable, autonomous control device with great tactile feedback. Additionally, as it is based on an ESP32-P4, the M5Stack TAB5 can be integrated into HA via ESPHome.

 

Prerequisites

To integrate the M5Stack TAB5 into HA, you will first need:

·        Your M5Stack Tab5 (with or without the battery).

·        To have ESPHome installed in Home Assistant.

·        A USB-C DATA cable to power the board (you will not be able to install the software with a charge-only cable).

 

Configuration in ESPHome

Follow these steps to integrate the M5Stack TAB5 into HA:

1. In Home Assistant, go to your ESPHome add-on and click on New device > Continue > New Device Setup.

2. Give your device a name (for example, “M5stack Tab5”) and click “Next.”

3. For the device type, select “ESP32-C6.” You will notice in the background that a new block has been created for your device.

4. Click “Skip” and then click “Edit” on your device's block. Copy the code that appears and save it, as you will need parts of it later.

5. Copy the following code and use it to replace the previous code in ESPHome.

 

substitutions:

# Device customization
# Personalización del dispositivo

  name: m5stack-tab5
  friendly_name: M5stack Tab5

####################################

esphome:
  name: ${name}
  friendly_name: ${friendly_name}

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

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

logger:
  hardware_uart: USB_SERIAL_JTAG

psram:
  mode: hex
  speed: 200MHz

api:
  encryption:
    key: "F8WsdfddfKt1XvQV9pU32443dsfdsf"

ota:
  - platform: esphome
    password: "sdffds23b12747edfq43543"

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
  ap:
    ssid: "M5Stack-Tab5 Fallback Hotspot"
    password: "sdfdMtQR34rfww"

# Sensors configuration
# Configuración de sensores

binary_sensor:
  - platform: gpio
    id: charging
    name: "Charging Status"
    pin:
      pi4ioe5v6408: pi4ioe2
      number: 6
      mode: INPUT_PULLDOWN

  - platform: gpio
    id: headphone_detect
    name: "Headphone Detect"
    pin:
      pi4ioe5v6408: pi4ioe1
      number: 7

i2c:
  - id: bsp_bus
    sda: GPIO31
    scl: GPIO32
    frequency: 400kHz

pi4ioe5v6408:
  - id: pi4ioe1
    address: 0x43
    # 0: O - wifi_antenna_int_ext
    # 1: O - speaker_enable
    # 2: O - external_5v_power
    # 3: NC
    # 4: O - lcd reset
    # 5: O - touch panel reset
    # 6: O - camera reset
    # 7: I - headphone detect
  - id: pi4ioe2
    address: 0x44
    # 0: O - wifi_power
    # 1: NC
    # 2: NC
    # 3: O - usb_5v_power
    # 4: O - poweroff pulse
    # 5: O - quick charge enable (inverted)
    # 6: I - charging status
    # 7: O - charge enable

select:
  - platform: template
    id: wifi_antenna_select
    name: "WiFi Antenna"
    options:
      - "Internal"
      - "External"
    optimistic: true
    on_value:
      - if:
          condition:
            lambda: return i == 0;
          then:
            - switch.turn_off: wifi_antenna_int_ext
          else:
            - switch.turn_on: wifi_antenna_int_ext

# The DAC Output select needs to be manually (or with an automation) changed to `LINE1` for the onboard speaker
  - platform: es8388
    dac_output:
      name: DAC Output
    adc_input_mic:
      name: ADC Input Mic

sensor:
  - platform: ina226
    address: 0x41
    adc_averaging: 16
    max_current: 8.192A
    shunt_resistance: 0.005ohm
    bus_voltage:
      name: Battery Voltage
    current:
      name: Battery Current
      # Positive means discharging
      # Negative means charging

switch:
  - platform: gpio
    id: wifi_power
    name: "WiFi Power"
    pin:
      pi4ioe5v6408: pi4ioe2
      number: 0
    restore_mode: ALWAYS_ON
  - platform: gpio
    id: usb_5v_power
    name: "USB Power"
    pin:
      pi4ioe5v6408: pi4ioe2
      number: 3
  - platform: gpio
    id: quick_charge
    name: "Quick Charge"
    pin:
      pi4ioe5v6408: pi4ioe2
      number: 5
      inverted: true
  - platform: gpio
    id: charge_enable
    name: "Charge Enable"
    pin:
      pi4ioe5v6408: pi4ioe2
      number: 7
  - platform: gpio
    id: wifi_antenna_int_ext
    pin:
      pi4ioe5v6408: pi4ioe1
      number: 0
  - platform: gpio
    id: speaker_enable
    name: "Speaker Enable"
    pin:
      pi4ioe5v6408: pi4ioe1
      number: 1
    restore_mode: ALWAYS_ON
  - platform: gpio
    id: external_5v_power
    name: "External 5V Power"
    pin:
      pi4ioe5v6408: pi4ioe1
      number: 2

# Display configuration
# Configuración de la pantalla

esp_ldo:
  - voltage: 2.5V
    channel: 3

font:
  - file: "gfonts://Kanit"
    id: font_title
    size: 100

light:
  - platform: monochromatic
    output: backlight_pwm
    name: "Display Backlight"
    id: backlight
    restore_mode: RESTORE_DEFAULT_ON
    default_transition_length: 250ms

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

touchscreen:
  - platform: gt911
    interrupt_pin: GPIO23
    update_interval: never
    reset_pin:
      pi4ioe5v6408: pi4ioe1
      number: 5
    calibration:
      x_min: 0
      x_max: 720
      y_min: 0
      y_max: 1280
    id: touch

display:
  - platform: mipi_dsi
    dimensions:
      height: 1280
      width: 720
    model: M5Stack-Tab5
    reset_pin:
      pi4ioe5v6408: pi4ioe1
      number: 4
    show_test_card: true
    rotation: 90

lvgl:
  touchscreens: touch
  buffer_size: 100%
  style_definitions:
    - id: style_title
      align: CENTER
      text_font: font_title
  widgets:
    - label:
        styles: style_title
        text: 'Hola Aguacater@s!!'

# Media configuration and voice assistant
# Configuración multimedia y asistente de voz

audio_dac:
  - platform: es8388
    id: es8388_dac

audio_adc:
  - platform: es7210
    id: es7210_adc
    bits_per_sample: 16bit
    sample_rate: 16000

i2s_audio:
  - id: mic_bus
    i2s_lrclk_pin: GPIO29
    i2s_bclk_pin: GPIO27
    i2s_mclk_pin: GPIO30

media_player:
  - platform: speaker
    name: None
    id: speaker_player
    announcement_pipeline:
      speaker: tab5_speaker
      format: FLAC
      sample_rate: 48000
      num_channels: 1
    on_announcement:
      # Stop the wake word (mWW or VA) if the mic is capturing
      - if:
          condition:
            - microphone.is_capturing:
          then:
            - micro_wake_word.stop:
    on_idle:
      # Since VA isn't running, this is the end of user-intiated media playback. Restart the wake word.
      - if:
          condition:
            not:
              voice_assistant.is_running:
          then:
            - micro_wake_word.start:

micro_wake_word:
  id: mww
  models:
    - okay_nabu
    - hey_mycroft
    - hey_jarvis
  on_wake_word_detected:
    - voice_assistant.start:
        wake_word: !lambda return wake_word;

microphone:
  - platform: i2s_audio
    id: tab5_microphone
    i2s_din_pin: GPIO28
    sample_rate: 16000
    bits_per_sample: 16bit
    adc_type: external

# Commented out to avoid duplicates (see above)
# Comentado para evitar duplicidades (ver arriba)
#select:
# The DAC Output select needs to be manually (or with an automation) changed to `LINE1` for the onboard speaker
#  - platform: es8388
#    dac_output:
#      name: DAC Output
#    adc_input_mic:
#      name: ADC Input Mic

speaker:
  - platform: i2s_audio
    id: tab5_speaker
    i2s_dout_pin: GPIO26
    audio_dac: es8388_dac
    dac_type: external
    channel: mono
    buffer_duration: 100ms
    bits_per_sample: 16bit
    sample_rate: 48000

voice_assistant:
  id: va
  microphone: tab5_microphone
  media_player: speaker_player
  micro_wake_word: mww
  on_end:
    # Wait a short amount of time to see if an announcement starts
    - wait_until:
        condition:
          - media_player.is_announcing:
        timeout: 0.5s
    # Announcement is finished and the I2S bus is free
    - wait_until:
        - and:
            - not:
                media_player.is_announcing:
            - not:
                speaker.is_playing:
    - micro_wake_word.start:
  on_client_connected:
    - micro_wake_word.start:
  on_client_disconnected:
    - micro_wake_word.stop:

6. Important note: This code does not include the credentials required for the device to connect to your WiFi and your Home Assistant instance, so you must add them manually. Specifically, I am referring to the following lines from the code you copied in step 4.

 

# Enable Home Assistant API
api:
  encryption:
    key: "bg6hash6sjdjsdjk02hh0qnQeYVwm123vdfKE8BP5"

ota:
  - platform: esphome
    password: "asddasda27aab65a48484502b332f"

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

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Assist Fallback Hotspot"
    password: "ZsasdasdHGP2234"

7. What you need to do is find the corresponding lines in the code (at the beginning) and add the relevant information.

8. Now, click "Save" and "Install." Select "Manual download" and wait for the code to compile.

9. Once finished, select the "Modern format" option to download the corresponding '.bin' file.

10. Connect the M5Stack TAB5 to your computer using the USB-C data cable via the side port.

11. Now go to the ESPHome Web page and click "Connect." In the pop-up window, select your board and click "Connect."

12. Now click "Install" and select the '.bin' file obtained in step 9. Click "Install" once more.

13. Return to Home Assistant and go to Settings > Devices & Services. Your device should normally be discovered and appear at the top, simply waiting for you to click the "Configure" button. Otherwise, click the "Add Integration" button, search for "ESPHome," and enter your board's IP address in the "Host" field. As always, I recommend that you assign a static IP in your router to avoid future issues if it changes.

14. Finally, go to Settings > Devices & Services > ESPHome. Click the "Configure" link for your device. In the pop-up window, check the box "Allow the device to perform Home Assistant actions" and click "Submit." This will allow us to control our devices directly from the screen.

 

If everything went well, you should see the following on your screen:

 

Additionally, with this code, you will be able to:

·        Control and monitor the device's sensors in Home Assistant (such as battery percentage, activating the speaker, turning on the screen…).

·        Use the screen to create your control dashboard and manage your devices.

·        Expose your M5Stack Tab5 as a media player entity, allowing you to use it to play audio notifications or the radio.

·        Use it as a voice assistant if you have already configured Assist.

🏷️ Tips:

Each part in the code has been labeled, so any sections you are not interested in can be removed. 

From here on, the way you use the panel depends on your imagination!

Source: AguacaTEC

Author: TitoTB