All checks were successful
Podman DDNS Image / build-and-push-ddns (push) Successful in 1m3s
600 lines
13 KiB
YAML
600 lines
13 KiB
YAML
esphome:
|
|
name: tab1
|
|
friendly_name: M5Stack Tab5 1
|
|
on_boot:
|
|
# Set the charging icon to the correct state on boot
|
|
- then:
|
|
- logger.log: "Delaying backlight initialization"
|
|
- delay: 2s
|
|
- logger.log: "End delay"
|
|
- if:
|
|
condition:
|
|
lambda: return id(charging).state;
|
|
then:
|
|
- lvgl.widget.show:
|
|
id: charging_icon_widget
|
|
else:
|
|
- lvgl.widget.hide:
|
|
id: charging_icon_widget
|
|
|
|
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
|
|
level: DEBUG
|
|
|
|
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
|
|
fast_connect: true
|
|
on_connect:
|
|
- lvgl.label.update:
|
|
id: lbl_status
|
|
text: "IDLE"
|
|
- select.set:
|
|
id: dac_output
|
|
option: "LINE1"
|
|
- lvgl.label.update:
|
|
id: lbl_ip
|
|
text: !lambda return id(ip_addr).state;
|
|
- lvgl.label.update:
|
|
id: lbl_ap
|
|
text: !lambda return id(ssid).state;
|
|
on_disconnect:
|
|
- lvgl.label.update:
|
|
id: lbl_status
|
|
text: "DISCONNECTED"
|
|
|
|
text_sensor:
|
|
- platform: wifi_info
|
|
ip_address:
|
|
id: ip_addr
|
|
name: Device IP Address
|
|
address_0:
|
|
name: Device IP Address 0
|
|
address_1:
|
|
name: Device IP Address 1
|
|
address_2:
|
|
name: Device IP Address 2
|
|
address_3:
|
|
name: Device IP Address 3
|
|
address_4:
|
|
name: Device IP Address 4
|
|
ssid:
|
|
id: ssid
|
|
name: Device Connected SSID
|
|
bssid:
|
|
name: Device Connected BSSID
|
|
mac_address:
|
|
name: Device Mac Wifi Address
|
|
scan_results:
|
|
name: Device Latest Scan Results
|
|
dns_address:
|
|
name: Device DNS Address
|
|
power_save_mode:
|
|
name: Device Wifi Power Save Mode
|
|
|
|
time:
|
|
- platform: sntp
|
|
id: sntp_time
|
|
timezone: America/New_York
|
|
servers:
|
|
- 0.pool.ntp.org
|
|
- 1.pool.ntp.org
|
|
- 2.pool.ntp.org
|
|
|
|
# wireguard:
|
|
# address: !secret tab1_wg_ip
|
|
# private_key: !secret tab1_wg_pk
|
|
# peer_endpoint: !secret wg_host
|
|
# peer_public_key: !secret wg_pubkey
|
|
|
|
# # Optional keepalive (disabled by default)
|
|
# peer_persistent_keepalive: 25s
|
|
|
|
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
|
|
on_state:
|
|
then:
|
|
- if:
|
|
condition:
|
|
lambda: return id(charging).state;
|
|
then:
|
|
- lvgl.widget.show:
|
|
id: charging_icon_widget
|
|
else:
|
|
- lvgl.widget.hide:
|
|
id: charging_icon_widget
|
|
|
|
- platform: gpio
|
|
id: headphone_detect
|
|
name: "Headphone Detect"
|
|
pin:
|
|
pi4ioe5v6408: pi4ioe1
|
|
number: 7
|
|
- platform: lvgl
|
|
widget: volume_up_widget
|
|
name: Volume Up Button
|
|
on_press:
|
|
then:
|
|
- logger.log: "Button pressed"
|
|
- media_player.volume_up:
|
|
id: tab5_media_player
|
|
- delay: 100ms
|
|
- lvgl.label.update:
|
|
id: lbl_volume
|
|
text: !lambda return to_string(int(id(tab5_media_player).volume * 100));
|
|
- light.turn_on:
|
|
id: backlight
|
|
brightness: !lambda |-
|
|
float current_value = id(backlight).current_values.get_brightness();
|
|
return current_value < 0.6 ? 0.6 : current_value + 0.2;
|
|
- platform: lvgl
|
|
widget: volume_down_widget
|
|
name: Volume Down Button
|
|
on_press:
|
|
then:
|
|
- logger.log: "Button pressed"
|
|
- media_player.volume_down:
|
|
id: tab5_media_player
|
|
- lvgl.label.update:
|
|
id: lbl_volume
|
|
text: !lambda return to_string(int(id(tab5_media_player).volume * 100));
|
|
- light.turn_on:
|
|
id: backlight
|
|
brightness: !lambda |-
|
|
float current_value = id(backlight).current_values.get_brightness();
|
|
return current_value < 0.6 ? 0.6 : current_value - 0.2;
|
|
|
|
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: "50%"
|
|
|
|
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
|
|
- file: "images/charging.png"
|
|
id: charging_icon
|
|
resize: 64x64
|
|
|
|
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:
|
|
- obj:
|
|
align: TOP_MID
|
|
width: 100%
|
|
height: 100%
|
|
layout:
|
|
type: flex
|
|
flex_flow: column
|
|
flex_align_main: START
|
|
flex_align_track: center
|
|
flex_align_cross: center
|
|
widgets:
|
|
- label:
|
|
align: TOP_MID
|
|
id: lbl_status
|
|
text_font: montserrat_48
|
|
text: "CONNECTING..."
|
|
- label:
|
|
align: TOP_MID
|
|
id: lbl_ap
|
|
text_font: montserrat_22
|
|
text: "CONNECTING..."
|
|
- label:
|
|
align: TOP_MID
|
|
id: lbl_ip
|
|
text_font: montserrat_22
|
|
text: "CONNECTING..."
|
|
- image:
|
|
id: listen_icon_widget
|
|
src: va_idle
|
|
align: CENTER
|
|
- label:
|
|
align: BOTTOM_LEFT
|
|
id: lbl_version
|
|
text_font: montserrat_12
|
|
text: "v0.6"
|
|
- label:
|
|
align: BOTTOM_RIGHT
|
|
id: lbl_battery
|
|
text_font: montserrat_28
|
|
text: Loading...
|
|
- image:
|
|
id: charging_icon_widget
|
|
src: charging_icon
|
|
align: TOP_RIGHT
|
|
- button:
|
|
id: volume_up_widget
|
|
widgets:
|
|
- label:
|
|
text: "\uF028"
|
|
text_font: montserrat_48
|
|
text_align: CENTER
|
|
align: CENTER
|
|
x: 20
|
|
y: 20
|
|
width: 100
|
|
height: 100
|
|
pad_all: 8
|
|
- button:
|
|
id: volume_down_widget
|
|
widgets:
|
|
- label:
|
|
text: "\uF027"
|
|
text_font: montserrat_48
|
|
text_align: CENTER
|
|
align: CENTER
|
|
x: 20
|
|
y: 140
|
|
width: 100
|
|
height: 100
|
|
pad_all: 8
|
|
- label:
|
|
x: 20
|
|
y: 260
|
|
id: lbl_volume
|
|
text_font: montserrat_28
|
|
text: !lambda return "%.1f",to_string(id(tab5_media_player).volume);
|
|
|
|
# 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:
|