You didn’t reply to anyone specific, but some of the code I use in this thread is here
The dial_lvgl is essentially what is in the video above.
You didn’t reply to anyone specific, but some of the code I use in this thread is here
The dial_lvgl is essentially what is in the video above.
Do you have something to share from Squareline?
Hey all. I’m very close to finishing up programming my first Dial. I have pages working with the dial, etc. I am basically setting up a timer that is “supposed” to buzz when it expires. For whatever reason, the buzzer isn’t making any sound. I went back to the default firmware and I can hear it beep when I click on things, so I don’t think it’s a hardware issue.
output:
- platform: ledc
pin: GPIO3
id: buzzer
sensor:
- platform: rotary_encoder
id: encoder
pin_a: GPIO40
pin_b: GPIO41
on_clockwise:
then:
- output.turn_on: buzzer
- logger.log: "Next page"
on_anticlockwise:
then:
- output.turn_off: buzzer
- logger.log: "Previous page"
I tried the above code just to simply test the buzzer, but nothing happens. In the past, I’ve used ESP dev boards and attached passive buzzers to pins and that is how I turned them on/off. Does anyone have any experiences with the buzzer on the Dial? Any thoughts/tips?
The buzzer needs to be controlled with rtttl
https://esphome.io/components/rtttl.html
on_clockwise:
- rtttl.play: quick_e:d=4,o=5,b=100:16e6
Unfortunately, there is a fair bit of blocking code so it doesn’t work perfectly.
Gotcha. I was hoping to use it without rttl. I need something that will continue to make noise until a user interacts with it. I’ll play with it though. Thanks for the response.
Any idea if there is a way to start rtttl from inside a lambda? With my countdown, it tests for the end of the countdown and takes actions inside lambdas. Oddly, Google isn’t helping me much.
Here is the section of yaml. I commented where I need the rtttl to start (and hopefully continue non-stop until the user presses a button).
lambda: |-
int mins = 0;
int secs = 0;
if (id(esptime).now().day_of_week == 1) { // it's Sunday, do nothing.
it.fill(id(Color::WHITE));
it.image(120, 60, id(cfa_logo), ImageAlign::CENTER);
it.print(120, 120, id(roboto20), id(cfa_black), TextAlign::CENTER_HORIZONTAL, "It's a day of rest!");
it.print(120, 160, id(roboto20), id(cfa_black), TextAlign::CENTER_HORIZONTAL, "No alarms until tomorrow.");
id(backlight_output).set_level(0.2);
} else if (id(esptime).now().hour < id(starttime) || id(esptime).now().hour > id(endtime)) { // After Hours
it.fill(id(Color::WHITE));
it.image(120, 60, id(cfa_logo), ImageAlign::CENTER);
it.print(120, 120, id(roboto20), id(cfa_black), TextAlign::CENTER_HORIZONTAL, "Good night!");
it.print(120, 160, id(roboto20), id(cfa_black), TextAlign::CENTER_HORIZONTAL, "No alarms");
it.print(120, 180, id(roboto20), id(cfa_black), TextAlign::CENTER_HORIZONTAL, "until tomorrow.");
id(countdown) = ${countdown_length};
id(backlight_output).set_level(0.2);
} else if (id(countdown) > 0) { // Countdown is active
id(countdown)--;
secs = id(countdown) % 60;
mins = (id(countdown) - secs) / 60;
it.fill(id(Color::WHITE));
it.image(120, 60, id(cfa_logo), ImageAlign::CENTER);
it.printf(120, 120, id(roboto32), id(cfa_black), TextAlign::CENTER_HORIZONTAL, "%2d:%02d", mins, secs);
it.print(120, 175, id(roboto20), id(cfa_black), TextAlign::CENTER_HORIZONTAL, "Current Time");
it.strftime(120, 200, id(roboto20), id(cfa_black), TextAlign::CENTER_HORIZONTAL, "%I:%M %p", id(esptime).now());
id(backlight_output).set_level(0.6);
} else { // Countdown has expired. Let's make some noise!
id(alarming) = "true";
// start rtttl
it.fill(id(Color::WHITE));
it.image(120, 60, id(cfa_logo), ImageAlign::CENTER);
it.print(120, 120, id(roboto32), id(cfa_black), TextAlign::CENTER_HORIZONTAL, "Time to clean!");
it.print(120, 195, id(roboto16), id(cfa_black), TextAlign::CENTER_HORIZONTAL, "Rotate for tasks");
id(backlight_output).set_level(1.0);
}
Without going through all that code, I would think something like
id(my_rtttl).play("success:d=24,o=5,b=100:c,g,b");
Replace my_rtttl with whatever the id of your rtttl component is, and the string is the audio that is played
That should work, but if I was thinking about doing it, I’d create a script that plays the rtttl (and anything else I needed to do at the expiry of the countdown) and then just put
id(my_script).execute();
in the lambda.
Hi there,
is someone managed to reproduce or approach the sound that rotary encoder do on stock M5dial firmware.
I’m using this one for my tests, but it sounds like the 80’s …
rtttl.play: 'one_short:d=32,o=4,b=900:a'
I made some progress on LVGL component, and this is FASTEEEEEEEEEER than lambdas, and even look better to me!
lvgl:
# -------------------------------------------------------------------- general
displays:
- my_display
touchscreens:
- my_touchscreen
rotary_encoders:
sensor: rotaryencoder
enter_button: m5_button
theme:
obj:
scrollbar_mode: "OFF"
scrollable: false
bg_color: pri_color
border_width: 0
border_color: orange_color
radius: 10
arc:
arc_color: pri_color
knob:
bg_color: nova_color
indicator:
arc_color: dark_nova_color
btn:
bg_color: pri_color
checked:
bg_color: nova_color
label:
align: CENTER
text_font: montserrat_18
text_color: text_color
clickable: false
on_idle:
timeout: !lambda "return (id(backlight_timeout).state * 1000);"
then:
- logger.log: "LVGL is idle"
- light.turn_off: backlight
- lvgl.pause:
# ------------------------------------------------------------------ top layer
top_layer:
widgets:
- obj:
id: boot_screen
width: SIZE_CONTENT
height: SIZE_CONTENT
bg_color: 0x000000
bg_opa: COVER
radius: 0
pad_all: 0
border_width: 0
on_press:
- lvgl.widget.hide: boot_screen
widgets:
- img:
align: CENTER
src: boot_logo
y: -30
- spinner:
align: CENTER
y: 70
height: 50
width: 50
spin_time: 2s
arc_length: 60deg
arc_rounded: true
arc_color: sec_color
arc_width: 7
indicator:
arc_color: blue_color
arc_width: 7
# ---------------------------------------------------------------------- pages
pages:
# _____________________________________________________ page welcome
- id: page_welcome
<<: &page_config
bg_color: sec_color
scrollbar_mode: "OFF"
scrollable: false
widgets:
# time
- label:
id: label_rtc_time
align: TOP_MID
text: "Heure"
y: 5
# date
- label:
id: label_rtc_date
align: TOP_MID
text_font: montserrat_16
text: "Date"
y: 28
# MIDDLE_CONTAINER
- obj:
id: object_alarm_state
align: BOTTOM_MID
x: 0
y: -150
width: 250
height: 36
# clickable: true
# on_press:
# - lvgl.page.show: page_alarm
# - homeassistant.service:
# service: input_select.select_option
# data:
# entity_id: $ha_page_selector
# option: page_alarm
widgets:
- label:
id: label_alarm_text
text: "Alarme"
text_color: sec_color
# LEFT_CONTAINER_1
- obj:
width: 150
height: 95
align: TOP_RIGHT
x: -101
y: 98
widgets:
######################### COLUMN 01
# garage
- label:
id: icon_garage_state
<<: &icon_40_config
clickable: true
text_font: grandstander_40_regular
text: "x"
<<: &column_01
x: -60
<<: &row_01
align: TOP_RIGHT
y: -8
clickable: false
# on_long_press:
# - <<: &bip
# rtttl.play: 'one_short:d=32,o=4,b=900:a'
# cargate
- label:
id: icon_cargate_text
<<: *icon_40_config
<<: *column_01
<<: &row_02
align: BOTTOM_RIGHT
y: 2
clickable: false
# on_long_press:
# - <<: *bip
######################### COLUMN 02
# light
- label:
id: icon_light_cour
<<: *icon_40_config
<<: &column_02
x: 0
<<: *row_01
on_long_press:
- <<: &bip
rtttl.play: 'one_short:d=24,o=5,b=100:g'
- homeassistant.service:
service: light.toggle
data:
entity_id: $ha_light_cour
# handgate
- label:
id: icon_handgate_text
<<: *icon_40_config
<<: *column_02
<<: *row_02
y: 4 # SPE handgate
on_long_press:
- <<: *bip
- homeassistant.service:
service: lock.unlock
data_template:
entity_id: lock.gate
# LEFT_CONTAINER_2
- obj:
bg_opa: TRANSP
border_opa: TRANSP
width: 150
height: 45
align: TOP_RIGHT
x: -100
y: 195
widgets:
# outside temperature
- label:
id: label_outside_temperature
x: 41
text_font: montserrat_20
text: "Temp"
# meteo
- label:
id: icon_weather_sensor
x: 41
text_font: grandstander_36_regular
text: "x"
# RIGHT_1_CONTAINER
- obj:
bg_opa: TRANSP
border_opa: TRANSP
width: 110
height: 45
align: TOP_LEFT
x: 147
y: 98
widgets:
- label:
id: icon_front_door
<<: &icon_36_config
text_font: grandstander_36_regular
text: "x"
align: LEFT_MID
x: -5
- label:
id: icon_window_group
<<: *icon_36_config
align: LEFT_MID
x: 40
# RIGHT_2_CONTAINER
- obj:
width: 110
height: 100
align: TOP_LEFT
x: 147
y: 151
on_long_press:
- <<: *bip
- lvgl.page.show: page_thermostat
- homeassistant.service:
service: input_select.select_option
data:
entity_id: $ha_page_selector
option: page_thermostat
- homeassistant.service:
service: climate.set_hvac_mode
data:
entity_id: $ha_climate_heating
hvac_mode: heat
widgets:
# temp
- label:
id: label_climate_heating_current_0
y: -5
align: TOP_LEFT
text_font: montserrat_20
text: "Temp"
# climate icon
- label:
id: icon_climate_heating
align: TOP_LEFT
x: -3
y: 22
text_font: grandstander_32_regular
text: "x"
# __________________________________________________ page thermostat
- id: page_thermostat
<<: *page_config
widgets:
- meter:
id: meter_climate_heating_target
width: 210
height: 210
align: CENTER
bg_opa: TRANSP
border_width: 0
text_color: text_color
scales:
range_from: 16 # = template_sensor, and arc values
range_to: 24 # = template_sensor, and arc values
angle_range: 250
rotation: 145 # = arc start_angle
ticks:
count: 9
width: 1
length: 3
color: sec_color
major:
stride: 1
length: 1
color: dark_nova_color
label_gap: 18
- arc:
id: arc_climate_heating_target
width: 210
height: 210
align: CENTER
start_angle: 145 # = meter rotation value
end_angle: 35
min_value: 160 # idem meter range_from value * 10
max_value: 240 # idem meter range_to value * 10
adjustable: false
- obj:
id: button_climate_state_off
align: CENTER
width: 60
height: 60
radius: 60
on_long_press:
- <<: *bip
- lvgl.page.show: page_welcome
- homeassistant.service:
service: input_select.select_option
data:
entity_id: $ha_page_selector
option: page_welcome
- homeassistant.service:
service: climate.set_hvac_mode
data:
entity_id: $ha_climate_heating
hvac_mode: "off"
widgets:
- label:
<<: *icon_36_config
text: "\U000F0425" # mdi:power
- label:
id: label_climate_heating_current_1
text: ""
y: 70
text_font: montserrat_26
Have to work on the alarm page
now.
EDIT : Done
Here’s the main part of the code (had to split code to post here):
packages:
wifi: !include common/esp_common_wifi.yaml
device_base: !include common/esp_common_device_base.yaml
<<: !include m5dial_files/colors_and_fonts.yaml
# <<: !include m5dial_files/lvgl_images_and_icons.yaml
# ----------------------------------------------------------------------- images
image:
- id: boot_logo
file: m5dial_files/cs_smiley.png
type: RGB565
use_transparency: true
resize: 100x100
wifi:
manual_ip:
static_ip: 192.168.2.63
ap:
ssid: "ip063-tab-m5stack-dial-fallback"
esphome:
on_boot:
priority: 600
then:
- pcf8563.read_time: rtc_time
- light.turn_on: backlight
esp32:
board: esp32-s3-devkitc-1
framework:
type: arduino
api:
on_client_connected:
- if:
condition:
lambda: 'return (0 == client_info.find("Home Assistant "));'
then:
- delay: 1s
- lvgl.widget.hide: boot_screen
- lvgl.page.show: page_welcome
- homeassistant.service:
service: input_select.select_option
data:
entity_id: $ha_page_selector
option: page_welcome
on_client_disconnected:
- if:
condition:
lambda: 'return (0 == client_info.find("Home Assistant "));'
then:
- lvgl.widget.show: boot_screen
external_components:
- source: github://clydebarrow/esphome@lvgl
refresh: 10min
components: [ lvgl ]
# ======================================================================================
# ======================================================================================
# =========================================================================== components
i2c:
- id: bus_internal #required by touchscreen.ft5x06
sda: GPIO11
scl: GPIO12
scan: False
touchscreen:
platform: ft5x06
address: 0x38
id: my_touchscreen
on_release:
- if:
condition: lvgl.is_paused
then: &lvgl_resume
- logger.log: "LVGL resuming"
- lvgl.resume:
- lvgl.widget.redraw:
- light.turn_on: backlight
uart:
tx_pin: GPIO2
rx_pin: GPIO1
baud_rate: 256000
parity: NONE
stop_bits: 1
spi:
mosi_pin: GPIO5
clk_pin: GPIO6
display:
- platform: ili9xxx
model: gc9a01a
auto_clear_enabled: false
update_interval: never
reset_pin: GPIO8
id: my_display
cs_pin: GPIO7
dc_pin: GPIO4
dimensions:
height: 240
width: 240
output:
- platform: ledc
id: lcd_backlight
pin: GPIO9
min_power: 0
max_power: 1
- platform: ledc
id: rtttl_out
pin: GPIO3
light:
- platform: monochromatic
id: backlight
name: "Backlight"
output: lcd_backlight
default_transition_length: 250ms
rtttl:
output: rtttl_out
id: my_rtttl
# ======================================================================================
# ======================================================================================
# ============================================================================= specials
# -------------------------------------------------------------- substitutions
substitutions:
name: ip063_tab_m5stack_dial
friendly_name: M5Stack Dial
comment: M5stack Dial / esp32-s3 (lvgl)
log_level: DEBUG # NONE / ERROR / WARN / INFO / DEBUG (default) / VERBOSE / VERY_VERBOSE (not recommended)
ha_presence_sensor: binary_sensor.ip030_mmw_aqara_living_presence_sensor_6
ha_light_cour: light.shelly_one_cour
ha_climate_heating: climate.heatpump_sdgs_ebusd
ha_weather_sensor: weather.84_main_city
ha_outside_temperature: sensor.ebusd_bass2_displayedoutsidetemp_tempv
ha_page_selector: input_select.tab_m5stack_dial_page_selector
ha_alarm_text: sensor.tplt_alarmo
ha_alarm_state: alarm_control_panel.alarme_maison
ha_front_door: binary_sensor.magnet_aqara_front_door_contact
ha_window_group: binary_sensor.windows_upstairs_bedrooms
ha_handgate_text: binary_sensor.tplt_gate_open_too_long
ha_cargate_text: input_boolean.test
ha_garage_state: binary_sensor.io_frient_garage_09c6_input_1
# -------------------------------------------------------------------- globals
globals:
- id: lambda_nova_color
type: lv_color_t
restore_value: no
initial_value: 'lv_color_hex(0xe38de3)'
- id: lambda_blue_color
type: lv_color_t
restore_value: no
initial_value: 'lv_color_hex(0x6b93e3)'
- id: lambda_green_color
type: lv_color_t
restore_value: no
initial_value: 'lv_color_hex(0xa6da95)'
- id: lambda_yellow_color
type: lv_color_t
restore_value: no
initial_value: 'lv_color_hex(0xffd17a)'
- id: lambda_orange_color
type: lv_color_t
restore_value: no
initial_value: 'lv_color_hex(0xe0752b)'
- id: lambda_red_color
type: lv_color_t
restore_value: no
initial_value: 'lv_color_hex(0xede455c)'
- id: lambda_off_color
type: lv_color_t
restore_value: no
initial_value: 'lv_color_hex(0x85b6078)'
- id: lambda_text_color
type: lv_color_t
restore_value: no
initial_value: 'lv_color_hex(0xcad3f5)'
# ======================================================================================
# ======================================================================================
# =============================================================================== number
number:
# __________________________________________________ backlight timeout
- platform: template
name: Backlight Timeout
optimistic: true
id: backlight_timeout
unit_of_measurement: "s"
initial_value: 30
restore_value: true
min_value: 10
max_value: 90
step: 10
mode: auto # auto / box / slider
# ======================================================================================
# ======================================================================================
# ================================================================================= time
switch:
- platform: template
id: switch_antiburn
icon: mdi:television-shimmer
optimistic: true
entity_category: "config"
turn_on_action:
- logger.log: "Starting Antiburn"
- if:
condition: lvgl.is_paused
then:
- lvgl.resume:
- lvgl.widget.redraw:
- delay: 1s
- lvgl.pause:
show_snow: true
turn_off_action:
- logger.log: "Stopping Antiburn"
- if:
condition: lvgl.is_paused
then:
- lvgl.resume:
- lvgl.widget.redraw:
- delay: 1s
- lvgl.pause:
# ======================================================================================
# ======================================================================================
# =============================================================================== switch
time:
- platform: homeassistant
on_time_sync:
then:
- pcf8563.write_time: rtc_time
- logger.log: "Time Synced"
- platform: pcf8563
id: rtc_time
address: 0x38
update_interval: never
on_time:
- minutes: '*'
seconds: 0
then:
- script.execute: time_update
- hours: 2,3,4,5
minutes: 5
seconds: 0
then:
- switch.turn_on: switch_antiburn
- hours: 2,3,4,5
minutes: 35
seconds: 0
then:
- switch.turn_off: switch_antiburn
- minutes: '*'
seconds: 0,10,20,30,40,50
then:
- lvgl.widget.hide: label_outside_temperature
- lvgl.widget.show: icon_weather_sensor
- minutes: '*'
seconds: 5,15,25,35,45,55
then:
- lvgl.widget.show: label_outside_temperature
- lvgl.widget.hide: icon_weather_sensor
# ======================================================================================
# ======================================================================================
# =============================================================================== script
script:
- id: time_update
then:
- lvgl.label.update:
id: label_rtc_time
text: !lambda |-
static char time_buf[10];
auto now = id(rtc_time).now();
int hour = now.hour;
int minute = now.minute;
snprintf(time_buf, sizeof(time_buf), "%02d:%02d", hour, minute);
return time_buf;
- lvgl.label.update:
id: label_rtc_date
text: !lambda |-
static const char * const month_names[] = {"Janvier", "Fevrier", "Mars", "Avril", "Mai", "Juin", "Juillet", "Aout", "Sept.", "Oct.", "Nov.", "Dec."};
static const char * const day_names[] = {"Dimanche", "Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi"};
static char combined_buf[20];
auto now = id(rtc_time).now();
snprintf(combined_buf, sizeof(combined_buf), "%s %2d %s", day_names[now.day_of_week - 1] , now.day_of_month , month_names[now.month-1]);
return combined_buf;
- id: climate_set_target_temperature
mode: restart
then:
- delay: 5s
- homeassistant.service:
service: climate.set_temperature
data:
entity_id: $ha_climate_heating
temperature: !lambda "return id(climate_heating_new_target).state;"
# ======================================================================================
# ======================================================================================
# ========================================================================== text sensor
text_sensor:
# ------------------------------------------------------------- home assistant
# ______________________________________________________ page selector
- platform: homeassistant
id: page_selector_state
entity_id: $ha_page_selector
on_value:
- if:
condition: lvgl.is_paused
then: *lvgl_resume
- if:
condition:
- lambda: 'return id(page_selector_state).state == "page_welcome";'
then:
- lvgl.page.show: page_welcome
- if:
condition:
- lambda: 'return id(page_selector_state).state == "page_thermostat";'
then:
- lvgl.page.show: page_thermostat
# ________________________________________________________ alarm state
- platform: homeassistant
id: alarm_state
entity_id: $ha_alarm_state
on_value:
- if:
condition: lvgl.is_paused
then: *lvgl_resume
- lvgl.widget.update:
id: object_alarm_state
bg_color: !lambda |-
if (x == "armed_away") {
return id(lambda_nova_color);
} else if (x == "armed_home") {
return id(lambda_blue_color);
} else if (x == "armed_night") {
return id(lambda_nova_color);
} else if (x == "arming" or x == "pending") {
return id(lambda_yellow_color);
} else if (x == "triggered") {
return id(lambda_red_color);
} else if (x == "disarmed") {
return id(lambda_text_color);
} else {
return id(lambda_off_color);
}
# _________________________________________________________ alarm text
- platform: homeassistant
id: alarm_text
entity_id: $ha_alarm_text
on_value:
- lvgl.label.update:
id: label_alarm_text
text:
format: "%s"
args: [ 'x.c_str()' ]
# ___________________________________________________ front door state
- platform: homeassistant
id: front_door # off / on
entity_id: $ha_front_door
on_value:
- if:
condition: lvgl.is_paused
then: *lvgl_resume
- lvgl.widget.update:
id: icon_front_door
text_color: !lambda |-
if (x == "off") {
return id(lambda_text_color);
} else if (x == "on") {
return id(lambda_blue_color);
} else {
return id(lambda_off_color);
}
- lvgl.label.update:
id: icon_front_door
text: !lambda |-
if (x == "off") {
return "\U000F10AF"; // mdi:door-closed-lock
} else if (x == "on") {
return "\U000F081C"; // mdi:door-open
} else {
return "x";
}
# _________________________________________________ window group state
- platform: homeassistant
id: window_group # off / on
entity_id: $ha_window_group
on_value:
- if:
condition: lvgl.is_paused
then: *lvgl_resume
- lvgl.widget.update:
id: icon_window_group
text_color: !lambda |-
if (x == "off") {
return id(lambda_text_color);
} else if (x == "on") {
return id(lambda_yellow_color);
} else {
return id(lambda_off_color);
}
- lvgl.label.update:
id: icon_window_group
text: !lambda |-
if (x == "off") {
return "\U000F11DB"; // mdi:window-closed-variant
} else if (x == "on") {
return "\U000F11DC"; // mdi:window-open-variant
} else {
return "x";
}
# _______________________________________________________ garage state
- platform: homeassistant
id: garage_state # off / on
entity_id: $ha_garage_state
on_value:
- if:
condition: lvgl.is_paused
then: *lvgl_resume
- lvgl.widget.update:
id: icon_garage_state
text_color: !lambda |-
if (x == "off") {
return id(lambda_text_color);
} else if (x == "on") {
return id(lambda_yellow_color);
} else {
return id(lambda_off_color);
}
- lvgl.label.update:
id: icon_garage_state
text: !lambda |-
if (x == "off") {
return "\U000F12D3"; // mdi:garage-variant
} else if (x == "on") {
return "\U000F12D4"; // mdi:garage-open-variant
} else {
return "x";
}
# ______________________________________________________ cargate state
- platform: homeassistant
id: cargate_text # off / on
entity_id: $ha_cargate_text
on_value:
- if:
condition: lvgl.is_paused
then: *lvgl_resume
- lvgl.widget.update:
id: icon_cargate_text
text_color: !lambda |-
if (x == "off") {
return id(lambda_text_color);
} else if (x == "on") {
return id(lambda_yellow_color);
} else {
return id(lambda_off_color);
}
- lvgl.label.update:
id: icon_cargate_text
text: !lambda |-
if (x == "off") {
return "\U000F0E8B"; // mdi:boom-gate-outline
} else if (x == "on") {
return "\U000F0E87"; // mdi:boom-gate-alert
} else {
return "x";
}
# ______________________________________________________ handgate text
- platform: homeassistant
id: handgate_text # closed / open / alert
entity_id: $ha_handgate_text
attribute: esphome_text_sensor
filters:
- map:
- closed -> Ferme
- open -> Ouvert
- alert -> Defaut
on_raw_value:
- if:
condition: lvgl.is_paused
then: *lvgl_resume
- lvgl.label.update:
id: icon_handgate_text
text: !lambda |-
if (x == "closed") {
return "\U000F0299"; // mdi:gate
} else if (x == "open") {
return "\U000F116A"; // mdi:gate-open
} else if (x == "alert") {
return "\U000F17F8"; // mdi:gate-alert
} else {
return "x";
}
- lvgl.widget.update:
id: icon_handgate_text
text_color: !lambda |-
if (x == "closed") {
return id(lambda_text_color);
} else if (x == "open") {
return id(lambda_yellow_color);
} else if (x == "alert") {
return id(lambda_red_color);
} else {
return id(lambda_off_color);
}
# ______________________________________________________ climate state
- platform: homeassistant
id: climate_heating_state
entity_id: $ha_climate_heating
on_value:
- lvgl.label.update:
id: icon_climate_heating
text: !lambda |-
if (x == "auto") {
return "\U000F1B17"; // mdi:thermostat-auto
} else if (x == "heat") {
return "\U000F0238"; // mdi:fire
} else if (x == "off") {
return "\U000F0AD8"; // mdi:radiator-off
} else {
return "x";
}
- lvgl.widget.update:
id: icon_climate_heating
text_color: !lambda |-
if (x == "auto") {
return id(lambda_green_color);
} else if (x == "heat") {
return id(lambda_orange_color);
} else if (x == "off") {
return id(lambda_text_color);
} else {
return id(lambda_off_color);
}
# _____________________________________________________ weather sensor
- platform: homeassistant
id: weather_sensor
entity_id: $ha_weather_sensor
on_value:
- lvgl.label.update:
id: icon_weather_sensor
text: !lambda |-
if (x == "clear-night") {
return "\U000F0594";
} else if (x == "cloudy") {
return "\U000F0590";
} else if (x == "exceptional") {
return "\U000F0F2F";
} else if (x == "fog") {
return "\U000F0591";
} else if (x == "hail") {
return "\U000F0592";
} else if (x == "lightning") {
return "\U000F0593";
} else if (x == "lightning-rainy") {
return "\U000F067E";
} else if (x == "partlycloudy") {
return "\U000F0595";
} else if (x == "pouring") {
return "\U000F0596";
} else if (x == "rainy") {
return "\U000F0597";
} else if (x == "snowy") {
return "\U000F0598";
} else if (x == "snowy-rainy") {
return "\U000F067F";
} else if (x == "sunny") {
return "\U000F0599";
} else if (x == "windy") {
return "\U000F059D";
} else if (x == "windy-variant") {
return "\U000F059E";
} else if (x == "sunny-off") {
return "\U000F14E4";
} else {
return "x";
}
# _________________________________________________________ light cour
- platform: homeassistant
id: light_cour
entity_id: $ha_light_cour
on_value:
- if:
condition: lvgl.is_paused
then: *lvgl_resume
- lvgl.label.update:
id: icon_light_cour
text: !lambda |-
if (x == "on") {
return "\U000F06E8"; // mdi:lightbulb-on
} else if (x == "off") {
return "\U000F0336"; // mdi:lightbulb-outline
} else {
return "x";
}
- lvgl.widget.update:
id: icon_light_cour
text_color: !lambda |-
if (x == "on") {
return id(lambda_yellow_color);
} else if (x == "off") {
return id(lambda_text_color);
} else {
return id(lambda_off_color);
}
# ======================================================================================
# ======================================================================================
# ======================================================================== binary sensor
binary_sensor:
# --------------------------------------------------------------------- button
- platform: gpio
pin:
number: GPIO42
inverted: true
id: m5_button
name: M5 Button
on_press:
- if:
condition: lvgl.is_paused
then: *lvgl_resume
- lvgl.page.show: page_welcome
- homeassistant.service:
service: input_select.select_option
data:
entity_id: $ha_page_selector
option: page_welcome
# ------------------------------------------------------------- home assistant
# ____________________________________________________ presence sensor
- platform: homeassistant
id: presence_sensor
entity_id: $ha_presence_sensor
publish_initial_state: true
on_state:
- if:
condition:
- binary_sensor.is_on: presence_sensor
then:
- if:
condition: lvgl.is_paused
then: *lvgl_resume
- lvgl.page.show: page_welcome
- homeassistant.service:
service: input_select.select_option
data:
entity_id: $ha_page_selector
option: page_welcome
# ======================================================================================
# ======================================================================================
# =============================================================================== sensor
sensor:
# ------------------------------------------------------------- rotary encoder
- platform: rotary_encoder
id: rotaryencoder
resolution: 1
pin_a:
number: GPIO40
mode:
input: true
pullup: true
pin_b:
number: GPIO41
mode:
input: true
pullup: true
accuracy_decimals: 0
on_value:
- if:
condition: lvgl.is_paused
then: *lvgl_resume
# ________________________________________________________ clockwise
on_clockwise:
- if:
condition:
- lambda: 'return id(page_selector_state).state == "page_thermostat";'
then:
- lambda: |-
return id(climate_heating_new_target).publish_state(id(climate_heating_new_target).state + 0.5);
# ___________________________________________________ anti-clockwise
on_anticlockwise:
- if:
condition:
- lambda: 'return id(page_selector_state).state == "page_thermostat";'
then:
- lambda: |-
return id(climate_heating_new_target).publish_state(id(climate_heating_new_target).state - 0.5);
# ------------------------------------------------------------- home assistant
# _____________________________________________ climate heating target
- platform: homeassistant
id: climate_heating_target
entity_id: $ha_climate_heating
attribute: temperature
on_value:
- if:
condition: lvgl.is_paused
then: *lvgl_resume
- lambda: |-
id(climate_heating_new_target).publish_state(x);
# ____________________________________________ climate new targetvalue
- platform: template
id: climate_heating_new_target
icon: mdi:thermometer-lines
filters:
- clamp:
min_value: 16 # idem meter range_from value
max_value: 24 # idem meter range_from value
on_value:
- lvgl.arc.update:
id: arc_climate_heating_target
value: !lambda return x * 10;
- script.execute: climate_set_target_temperature
# ____________________________________________ climate heating current
- platform: homeassistant
id: climate_heating_current
entity_id: $ha_climate_heating
attribute: current_temperature
on_value:
- lvgl.label.update:
id: label_climate_heating_current_0
text:
format: "%2.1f°C"
args: [ 'x' ]
- lvgl.label.update:
id: label_climate_heating_current_1
text:
format: "%2.1f°C"
args: [ 'x' ]
# ________________________________________________ outside temperature
- platform: homeassistant
id: outside_temperature
entity_id: $ha_outside_temperature
on_value:
- lvgl.label.update:
id: label_outside_temperature
text:
format: "%2.1f°C"
args: [ 'x' ]
color:
# Nova Colors
- id: nova_color # pink
hex: "e38de3"
- id: dark_nova_color # pink
hex: "764a76"
- id: pri_color # light (mantle)
hex: "24273a"
- id: sec_color # dark (crust)
hex: "181926"
- id: text_color
hex: "cad3f5"
- id: off_color
hex: "5b6078"
# Color Colors
- id: blue_color
hex: "6b93e3"
- id: dark_blue_color
hex: "344b79"
- id: green_color
hex: "a6da95"
- id: dark_green_color
hex: "374825"
- id: yellow_color
hex: "ffd17a"
- id: orange_color
hex: "e0752b"
- id: dark_orange_color
hex: "5f3e25"
- id: red_color
hex: "de455c"
- id: dark_red_color
hex: "642b2b"
font:
- id: roboto_16_bold
file:
type: gfonts
family: Roboto
weight: bold
size: 16
<<: &extras
extras:
- file: "fonts/materialdesignicons-webfont.ttf"
glyphs: [
"\U000F1999", # mdi:rotate-360
"\U000F0741", # mdi:gesture-tap
"\U000F0046", # mdi:arrow-down-thick
"\U000F0594", # clear-night
"\U000F0590", # cloudy
"\U000F0F2F", # exceptional
"\U000F0591", # fog
"\U000F0592", # hail
"\U000F0593", # lightning
"\U000F067E", # lightning-rainy
"\U000F0595", # partlycloudy
"\U000F0596", # pouring
"\U000F0597", # rainy
"\U000F0598", # snowy
"\U000F067F", # snowy-rainy
"\U000F0599", # sunny
"\U000F059D", # windy
"\U000F059E", # windy-variant
"\U000F14E4", # sunny-off
"\U000F073A", # mdi:cancel
"\U000F0425", # mdi:power
"\U000F0238", # mdi:fire
"\U000F1B17", # mdi:thermostat-auto
"\U000F0AD8", # mdi:radiator-off
"\U000F0299", # mdi:gate
"\U000F116A", # mdi:gate-open
"\U000F17F8", # mdi:gate-alert
"\U000F0E8B", # mdi:boom-gate-outline
"\U000F0E87", # mdi:boom-gate-alert
"\U000F10AF", # mdi:door-closed-lock
"\U000F081C", # mdi:door-open
"\U000F11DB", # mdi:window-closed-variant
"\U000F11DC", # mdi:window-open-variant
"\U000F12D3", # mdi:garage-variant
"\U000F12D4", # mdi:garage-open-variant
"\U000F06E8", # mdi:lightbulb-on
"\U000F0336", # mdi:lightbulb-outline
]
- id: roboto_20_regular
file:
type: gfonts
family: Roboto
weight: regular
size: 20
<<: *extras
- id: roboto_20_bold
file:
type: gfonts
family: Roboto
weight: bold
size: 20
<<: *extras
- id: roboto_24_regular
file:
type: gfonts
family: Roboto
weight: regular
size: 24
<<: *extras
- id: roboto_24_bold
file:
type: gfonts
family: Roboto
weight: bold
size: 24
<<: *extras
- id: roboto_48_bold
file:
type: gfonts
family: Roboto
weight: bold
size: 48
<<: *extras
- id: grandstander_32_regular
file:
type: gfonts
family: Grandstander
weight: regular
size: 32
<<: *extras
- id: grandstander_36_regular
file:
type: gfonts
family: Grandstander
weight: regular
size: 36
<<: *extras
- id: grandstander_40_regular
file:
type: gfonts
family: Grandstander
weight: regular
size: 40
<<: *extras
Hello! I have this simplified code in which I need to use the internal bus and the A bus.
i2c:
- id: busi
sda: GPIO11
scl: GPIO12
scan: True
frequency: 400kHz
- id: busa
sda: GPIO13
scl: GPIO15
scan: True
frequency: 400kHz
sensor:
- platform: vl53l0x
i2c_id: busa
name: "VL53L0x Distance"
update_interval: 1s
touchscreen:
platform: ft5x06
i2c_id: busi
address: 0x38
spi:
mosi_pin: GPIO5
clk_pin: GPIO6
display:
- platform: ili9xxx
model: gc9a01a
reset_pin: GPIO8
cs_pin: GPIO7
dc_pin: GPIO4
When I run it and it reaches the device on the A bus, it restarts.
[14:12:28][I][app:029]: Running through setup()...
[14:12:28][I][i2c.arduino:218]: Performing I2C bus recovery
[14:12:28][I][i2c.arduino:218]: Performing I2C bus recovery
[14:12:28][D][spi:039]: Setting up SPI bus...
[14:12:28][D][ili9xxx:034]: Setting up ILI9xxx
[14:12:28][D][spi_device:379]: mode 0, data_rate 40000kHz
[14:12:28][D][ili9xxx:030]: Wrote MADCTL 0x48
[14:12:28][D][vl53l0x:034]: 'VL53L0x Distance' - setup BEGIN
[14:12:33]E (6003) task_wdt: Task watchdog got triggered. The following tasks did not reset the watchdog in time:
[14:12:33]E (6003) task_wdt: - loopTask (CPU 1)
[14:12:33]E (6003) task_wdt: Tasks currently running:
[14:12:33]E (6003) task_wdt: CPU 0: IDLE
[14:12:33]E (6003) task_wdt: CPU 1: IDLE
[14:12:33]E (6003) task_wdt: Aborting.
[14:12:33]ESP-ROM:esp32s3-20210327
[14:12:33]Build:Mar 27 2021
[14:12:33]rst:0xc (RTC_SW_CPU_RST),boot:0x2b (SPI_FAST_FLASH_BOOT)
[14:12:33]Saved PC:0x4037793c
WARNING Decoded 0x4037793c: esp_restart_noos at /Users/ficeto/Desktop/ESP32/ESP32S2/esp-idf-public/components/esp_system/port/soc/esp32s3/system_internal.c:143 (discriminator 1)
[14:12:33]SPIWP:0xee
[14:12:33]mode:DIO, clock div:1
[14:12:33]load:0x3fce3808,len:0x43c
[14:12:33]load:0x403c9700,len:0xbec
[14:12:33]load:0x403cc700,len:0x2a3c
[14:12:33]entry 0x403c98d8
[14:12:34]E (188) psram: PSRAM ID read error: 0x00ffffff
If I remove the touch, it doesn’t work. Then, if I remove the display, it doesn’t work. Finally, when I remove SPI, it works.
[14:22:54][I][app:029]: Running through setup()...
[14:22:54][I][i2c.arduino:218]: Performing I2C bus recovery
[14:22:54][I][i2c.arduino:218]: Performing I2C bus recovery
[14:22:54][D][vl53l0x:034]: 'VL53L0x Distance' - setup BEGIN
[14:22:54][D][vl53l0x:258]: 'VL53L0x Distance' - setup END
[14:22:54][D][vl53l0x:310]: 'VL53L0x Distance' - Got distance 0.054 m
[14:22:54][D][sensor:094]: 'VL53L0x Distance': Sending state 0.05400 m with 2 decimals of accuracy
[14:22:55][D][vl53l0x:310]: 'VL53L0x Distance' - Got distance 0.052 m
Please help, I don’t know what else to do.
Couldn’t help myself, and instead of completing this project, I bought one of these to test…
Amoled screen… should look great.
Let us know!
Hi, i have some compilation probleme since a few days with lvgl.
esphome say me that the “btn” config must be rename into “button”.
and after that, i have no config error but compilation errors.
Have you any ideas ?
.piolibdeps/knob-salle-a-manger/lvgl/src/extra/widgets/animimg/lv_animimg.h:22:2: error: #error “lv_animimg: lv_img is required. Enable it in lv_conf.h (LV_USE_IMG 1)”
#error “lv_animimg: lv_img is required. Enable it in lv_conf.h (LV_USE_IMG 1)”
^~~~~
Compiling .pioenvs/knob-salle-a-manger/lib18f/WiFi/WiFiUdp.cpp.o
Compiling .pioenvs/knob-salle-a-manger/lib6ca/FS/FS.cpp.o
Compiling .pioenvs/knob-salle-a-manger/lib6ca/FS/vfs_api.cpp.o
Compiling .pioenvs/knob-salle-a-manger/libb83/Update/HttpsOTAUpdate.cpp.o
Archiving .pioenvs/knob-salle-a-manger/lib6ca/libFS.a
Compiling .pioenvs/knob-salle-a-manger/libb83/Update/Updater.cpp.o
.piolibdeps/knob-salle-a-manger/lvgl/src/extra/widgets/animimg/lv_animimg.h:37:5: error: ‘lv_img_t’ does not name a type; did you mean ‘lv_btn_t’?
lv_img_t img;
^~~~~~~~
lv_btn_t
Compiling .pioenvs/knob-salle-a-manger/libff1/ESPAsyncWebServer-esphome/AsyncEventSource.cpp.o
Archiving .pioenvs/knob-salle-a-manger/libb83/libUpdate.a
Compiling .pioenvs/knob-salle-a-manger/libff1/ESPAsyncWebServer-esphome/AsyncWebSocket.cpp.o
Compiling .pioenvs/knob-salle-a-manger/libff1/ESPAsyncWebServer-esphome/WebAuthentication.cpp.o
Archiving .pioenvs/knob-salle-a-manger/lib18f/libWiFi.a
Compiling .pioenvs/knob-salle-a-manger/libff1/ESPAsyncWebServer-esphome/WebHandlers.cpp.o
Compiling .pioenvs/knob-salle-a-manger/libff1/ESPAsyncWebServer-esphome/WebRequest.cpp.o
*** [.pioenvs/knob-salle-a-manger/src/main.cpp.o] Error 1
I’ve not done an update for a while, but I’d try a clean build files to see if it can force an update of all the backend/lvgl components
Have you received it yet? How does it compare to the M5Stack Dial in terms of screen?
Hard to get a great shot, but it’s sharper and better contrast. But it’s also noticeably smaller.
The dial is probably better overall, just an ugly orange and grey
Can you share your code. I love that background image
I’ve had much time to work on it unfortunately. The touchscreen is still not working, and I’ve not really had an opportunity to work on converting the driver into an esphome component (also, I am most definitely not a competent c++ coder).