esphome: name: tab1 friendly_name: M5Stack Tab5 1 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: # Touchscreen support external_components: - source: github://pr#12075 components: [st7123] refresh: 1h ota: platform: esphome wifi: ssid: !secret wifi_ssid password: !secret wifi_password on_connect: - lvgl.label.update: id: lbl_status text: "IDLE" - select.set: id: dac_output option: "LINE1" on_disconnect: - lvgl.label.update: id: lbl_status text: "DISCONNECTED" 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 button: - platform: restart name: "Restart Tablet" 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 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 charging # Tab5 built-in battery discharges from full (8.23 V) to shutdown threshold (6.0 V) - 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.75; // Discharged voltage float max_voltage = 8.2; // 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: 1 id: battery_percent on_value: then: - lvgl.label.update: id: lbl_battery text: format: "Battery: %.1f%" args: ["id(battery_percent).state"] touchscreen: - platform: st7123 i2c_id: bsp_bus interrupt_pin: GPIO23 display: lcd update_interval: never reset_pin: pi4ioe5v6408: pi4ioe1 number: 5 calibration: x_min: 0 x_max: 720 y_min: 0 y_max: 1280 id: touch on_touch: - logger.log: "LVGL resuming" - lvgl.resume: - light.turn_on: backlight on_release: - media_player.stop: esp_ldo: - voltage: 2.5V channel: 3 display: - platform: mipi_dsi id: lcd dimensions: height: 1280 width: 720 model: M5STACK-TAB5-V2 reset_pin: pi4ioe5v6408: pi4ioe1 number: 4 output: - platform: ledc pin: GPIO22 id: backlight_pwm frequency: 1000Hz light: - platform: monochromatic output: backlight_pwm name: "Display Backlight" id: backlight restore_mode: ALWAYS_ON default_transition_length: 250ms initial_state: brightness: "100%" image: defaults: type: rgb565 transparency: alpha_channel resize: 512x512 byte_order: little_endian images: - file: "images/va_idle.png" id: va_idle - file: "images/va_listen.png" id: va_listen - file: "images/va_speak.png" id: va_speak lvgl: byte_order: little_endian on_idle: timeout: 120s then: - logger.log: "LVGL is idle" - light.turn_off: id: backlight transition_length: 15s - lvgl.pause: widgets: - image: id: listen_icon_widget src: va_idle align: CENTER - label: align: TOP_MID id: lbl_status text_font: montserrat_48 text: "CONNECTING..." - label: align: BOTTOM_LEFT id: lbl_version text_font: montserrat_12 text: "v0.5" - label: align: BOTTOM_RIGHT id: lbl_battery text_font: montserrat_28 text: Loading... # The DAC Output select needs to be manually (or with an automation) changed to `LINE1` for the onboard speaker select: - platform: es8388 dac_output: name: DAC Output id: dac_output adc_input_mic: name: ADC Input Mic id: adc_input - 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 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 microphone: - platform: i2s_audio id: tab5_microphone i2s_din_pin: GPIO28 sample_rate: 16000 bits_per_sample: 16bit adc_type: external audio_dac: - platform: es8388 id: es8388_dac 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 media_player: - platform: speaker name: None id: tab5_media_player announcement_pipeline: speaker: tab5_speaker format: WAV 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: tab5_media_player micro_wake_word: mww on_listening: - logger.log: "LVGL resuming" - lvgl.resume: - light.turn_on: backlight - lvgl.image.update: id: listen_icon_widget src: va_listen - lvgl.label.update: id: lbl_status text: "LISTENING" on_stt_vad_end: - lvgl.label.update: id: lbl_status text: "PROCESSING" - lvgl.image.update: id: listen_icon_widget src: va_idle on_tts_start: - lvgl.label.update: id: lbl_status text: "RESPONDING" - lvgl.image.update: id: listen_icon_widget src: va_speak 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: - lvgl.label.update: id: lbl_status text: "IDLE" - lvgl.image.update: id: listen_icon_widget src: va_idle - light.turn_off: id: backlight transition_length: 15s on_client_connected: - micro_wake_word.start: on_client_disconnected: - micro_wake_word.stop: