M5Stack Tab5
Description
The M5Stack Tab5 is a self contained, optionally battery powered 5 inch touchscreen display with an ESP32-P4 at the heart. It has an ESP32-C6 co-processor that gives the P4 Wi-Fi capabilities.
The Tab5 has many peripherals built in including but not limited to:
- Display
- Touchscreen
- Microphone
- Speaker
- Camera
- IMU
- RTC
Example Configuration
The base configuration below covers all of the on-board hardware: the ESP32-P4, the ESP32-C6 hosted Wi-Fi
co-processor, the MIPI DSI display and GT911 touchscreen, the ES8388 DAC + ES7210 ADC audio path, the RX8130
RTC, the PI4IOE5V6408 IO expanders, and the INA226 battery monitor. Add your own wifi:, api:, and ota:
sections (or include them via !include/packages) before flashing.
esphome: name: m5stack-tab5 friendly_name: M5Stack Tab5 on_boot: then: # read the RTC time once when the system boots rx8130.read_time:
esp32: variant: esp32p4 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
wifi: ap:
psram: mode: hex speed: 200MHz
i2c: - id: bsp_bus sda: GPIO31 scl: GPIO32 frequency: 400kHz
esp_ldo: - voltage: 2.5V channel: 3
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
i2s_audio: - id: mic_bus i2s_lrclk_pin: GPIO29 i2s_bclk_pin: GPIO27 i2s_mclk_pin: GPIO30
audio_adc: - platform: es7210 id: es7210_adc bits_per_sample: 16bit sample_rate: 16000
audio_dac: - platform: es8388 id: es8388_dac
microphone: - platform: i2s_audio id: tab5_microphone i2s_din_pin: GPIO28 sample_rate: 16000 bits_per_sample: 16bit adc_type: external
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
display: - platform: mipi_dsi dimensions: height: 1280 width: 720 model: M5Stack-Tab5 reset_pin: pi4ioe5v6408: pi4ioe1 number: 4 show_test_card: true
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
output: - platform: ledc pin: GPIO22 id: backlight_pwm frequency: 1000Hz
light: - platform: monochromatic output: backlight_pwm name: "Display Backlight" id: backlight restore_mode: RESTORE_DEFAULT_ON default_transition_length: 250ms
time: - platform: rx8130 id: rtc_time i2c_id: bsp_bus # repeated synchronization is not necessary unless the external RTC # is much more accurate than the internal clock update_interval: never timezone: UTC
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 restore_mode: ALWAYS_ON - 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
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
# The DAC Output select needs to be manually (or with an automation) changed to `LINE1` for the onboard speakerselect: - 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: id: battery_voltage name: "Battery Voltage" current: id: battery_current name: "Battery Current" # Positive means discharging # Negative means chargingWiFi Antenna Selector
A template select that exposes the on-board antenna switch as an “Internal” / “External” option rather than the raw GPIO toggle.
# A friendlier UI on top of the `wifi_antenna_int_ext` GPIO switch defined in# config.yaml. Lets the user pick "Internal" / "External" rather than toggling# a raw on/off switch.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_extBattery Percentage
A template sensor that derives a 0–100% reading from the INA226 battery voltage. Adjust the min/max voltages to match your specific cell.
# Tab5 built-in battery discharges from full (8.23 V) to shutdown threshold (6.0 V)sensor: - platform: template name: "Battery Percentage" lambda: |- float voltage = id(battery_voltage).state; // Adjust these values based on your battery's actual min/max voltage float min_voltage = 6.0; // Discharged voltage float max_voltage = 8.23; // Fully charged voltage float percentage = (voltage - min_voltage) / (max_voltage - min_voltage) * 100.0; if (percentage > 100.0) return 100.0; if (percentage < 0.0) return 0.0; return percentage; update_interval: 60s unit_of_measurement: "%" accuracy_decimals: 1Voice Assistant
The voice assistant configuration below adds a media_player, micro_wake_word, and voice_assistant on top of
the audio hardware defined in the base config.
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-initiated 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;
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: