Closed erik3rik closed 1 year ago
I was diagnosing a bunch of ip esphome conflicts with eof orors, ping timeouts and of cursed api key changes then got "[Errno 111] Connect call failed ('
Dependency downloads take unuasually long time after downgrading right now, hopefully servers stay up.
Hey there @esphome/core, mind taking a look at this issue as it has been labeled with an integration (spi
) you are listed as a code owner for? Thanks!
(message by CodeOwnersMention)
Same issue here with ESPHome 2023.9.1, SPI display st7789v
Looking into it...
Can you share the whole yaml? The display on its own does not seem to cause an issue - I took your sample and can build and run that no problem. Any other SPI devices in there? Anything that might be trying to access the display before everything is set up?
Same issue here with ESPHome 2023.9.1, SPI display st7789v
I just tested on an ESP32S3 with st7789v (LilyGo T-Embed) with no issues.
How much RAM is free? The new SPI code does use a DMA buffer, it's possible that RAM usage is higher than before.
You want three backticks, on a line by themselves, before and after the yaml.
Bare board, powered by usb. Will also upload logs when I'll have physical access to it again.
esp32:
board: wemos_d1_mini32
framework:
type: arduino
esphome:
name: esp32-4
friendly_name: esp32-4
logger:
level: very_verbose
api:
encryption:
key: "ahvDDjMvo+CtqnrbjYg7PCr2aGZ/BRkdX9nNp5jyg0E="
ota:
password: "56b68f4eb517a5a1123c39441e9899a3"
wifi:
ssid:
password:
manual_ip:
static_ip: 192.168.0.138
gateway: 192.168.0.1
subnet: 255.255.255.0
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "Esp32-4 Fallback Hotspot"
password: "RRxZqKsCQdZ4"
captive_portal:
mdns:
spi:
clk_pin: 22
mosi_pin: 23
display:
- platform: max7219
cs_pin: 21
num_chips: 1
lambda: |-
it.print("01234567");
Ok, I have reproduced it. Stand by...
Ok, for the MAX7219 adding this to the yaml will fix it:
external_components:
source: github://pr#5446
components: [ max7219 ]
It's a bug in the MAX7219 component, was not exposed until the new SPI code landed which is a bit stricter.
Don't know about the other reports until I get a full YAML to reproduce.
I figured out why the problem caused a crash, and have pushed to the PR. So adding this to the YAML should work-around any other instances of the problem:
external_components:
source: github://pr#5446
components: [ spi ]
However, please report here if you find this necessary and/or if you see the "SPI Device not initialised" error message.
The underlying cause will be an error in another component and it will be nice to fix those rather than just papering over the cracks.
I had a problem with the max7219 dot display. Adding `
external_components: source: github://pr#5446 components: [ spi ]`
fixed the problem. The first solution, with max7219 between the brackets did not fix the problem. The ESP8266 restarted again and again. Thanks so far for this solution
Is that (5446) really fixing all issues? It seems to fix problems with max7219 as per the example that samuelolteanu showed (platform: max7219), but my original problem that I reported came from platform: ssd1306_spi, is that also fixed by 5446? It only mentions max7219...
If ssd1306_spi is not fixed by this, then this bug report should not be closed. @jesserockz
It should stop the ESP crashing. You may still see the "SPI not initialised error" which should be reported, but is technically a different bug.
Can you try it and see?
I will try after work today. Can't really test it remotely as if it does not work the device becomes bricked and needs cable connected to it to update.
@erik3rik the issue was auto-closed because it was mentioned in the PR (which was merged). Still, please test latest dev (or you can add the PR directly, as mentioned above) and let us know if the issue persists.
max7219 7digit did not crash anymore on esp32s2 wih pr#5446 max7219 or spi components separately.
Using:
external_components:
source: github://pr#5446
components: [ spi ]
While also having the newer ESPHome 2023.9.1, I still get the [E][spi:078]: SPIDevice not initialised - did you call spi_setup()?
error, twice. See the log below. But it is at least improving in the sense that the ESP32 no longer panics during boot and thus is no longer bricked after update.
Yet some kind of problem still exist, and I am unsure what to do about it.
Can you provide the entire YAML?
Yes, but its quite long and contain a lot of stuff. I'm sorry anyone else but me have to see this. Anyhow, here goes 1300 rows:
substitutions:
friendly_name: ESP Clock Radio
fixed_ip: "192.168.0.123"
esphome:
name: esp-clock-radio
esp32:
board: az-delivery-devkit-v4
framework:
type: arduino
preferences:
flash_write_interval: 5min
# Enable logging
logger:
external_components:
source: github://pr#5446
components: [ spi ]
font:
# gfonts://family[@weight]
- file: "gfonts://Roboto"
id: roboto_large
size: 28
- file: "gfonts://Roboto@500"
id: roboto_xlarge
size: 50
- file: "fonts/fira-sans.two.ttf" #"gfonts://Roboto@300"
id: roboto_xlargeThin
size: 55 # 50
- file: "gfonts://Roboto@100"
id: roboto_small
size: 18
- file: "gfonts://Roboto@100"
id: roboto_xsmall
size: 12
- file: "gfonts://Roboto@100"
id: roboto_xxsmall
size: 9
# - file: "gfonts://Carrois Gothic"
# id: big_value_font
# size: 27
#https://pictogrammers.com/library/mdi/
- file: "fonts/mdi.ttf"
id: mdi
size: 38
glyphs:
- "" # Warning
- "" # Drop off
- "" # Drop on
- "" # Thermometer
- "" # Cloud off
- "" # Cloud on
- "" # Happy
- "" # Sad
- "" # Sun
- "" # Night
- "" # Arrow Up
- "" # Arrow Down
- "" # Fan on
- "" # Fan off
- "" # Clock
- "" # Help
- "" # Check
- "" # Watering Can
- "" #Humidity
- "" #Alarm
- "" # Lightbulb
- "" # Sunset up
- "" # Candle
- file: "fonts/mdi.ttf"
id: mdi_xs
size: 15
glyphs:
- "" #Alarm
- "" # forward-10
- "" # rewind-10
- "" # Reset
globals:
- id: has_ever_had_wifi
type: bool
restore_value: no
initial_value: 'false'
- id: error_level
type: int
restore_value: no
initial_value: '0'
- id: has_custom_page
type: bool
restore_value: no
initial_value: 'false'
- id: display_sequence
type: int
restore_value: no
initial_value: '0'
- id: action_mode
type: int
restore_value: no
initial_value: '0'
- id: is_night_mode
type: bool
restore_value: no
initial_value: 'true'
# Enable Home Assistant API
api:
encryption:
key: !secret api_encryption_key
services:
- service: set_contrast
variables:
target: int
then:
- lambda: id(oled_display).set_contrast(target/100.0);
- service: play_rtttl
variables:
song_str: string
then:
- rtttl.play:
rtttl: !lambda 'return song_str;'
ota:
password: !secret ota_password
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
reboot_timeout: 15min
use_address: $fixed_ip
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: $friendly_name Fallback HS
password: !secret wifi_ap_password
captive_portal:
output:
- platform: ledc
pin: GPIO13
id: rtttl_out
- platform: ledc
pin: GPIO25
id: output_red
- platform: ledc
pin: GPIO26
id: output_green
- platform: ledc
pin: GPIO27
id: output_blue
spi:
clk_pin: GPIO18
mosi_pin: GPIO23
sensor:
- platform: uptime
name: $friendly_name Uptime
force_update: false
unit_of_measurement: s
icon: mdi:timer
update_interval: 300s
accuracy_decimals: 0
- platform: wifi_signal
name: $friendly_name WiFi Signal
update_interval: 300s
- platform: adc
pin: GPIO36
attenuation: auto
id: illuminance
name: $friendly_name Illuminance
update_interval: 10s
accuracy_decimals: 0
unit_of_measurement: lx
device_class: illuminance
filters:
- median:
window_size: 7
send_every: 6
send_first_at: 6
- lambda: |-
return (x * 320.0);
- platform: dht
pin: GPIO21
model: DHT22
temperature:
name: $friendly_name Temperature
id: internal_temperature
accuracy_decimals: 1
humidity:
name: $friendly_name Humidity
id: internal_humidity
accuracy_decimals: 0
update_interval: 60s
rtttl:
output: rtttl_out
display:
- platform: ssd1306_spi
model: "SH1106 128x64"
cs_pin: GPIO05
dc_pin: GPIO22
reset_pin: GPIO19
contrast: 1%
id: oled_display
flip_y: true
pages:
- id: page_default
lambda: |-
if(id(is_night_mode)) {
// it.printf(64, -10, id(roboto_xlargeThin), TextAlign::TOP_CENTER, "%s", id(current_time).state.c_str());
it.printf(64, -15, id(roboto_xlargeThin), TextAlign::TOP_CENTER, "%s", id(current_time).state.c_str());
}else{
it.printf(64, -10, id(roboto_xlarge), TextAlign::TOP_CENTER, "%s", id(current_time).state.c_str());
}
it.print(1, 62, id(mdi_xs), TextAlign::BOTTOM_LEFT, "");
it.printf(16, 62, id(roboto_xsmall), TextAlign::BOTTOM_LEFT, "%s", id(wake_time).state.c_str());
it.printf(126, 62, id(roboto_xsmall), TextAlign::BOTTOM_RIGHT, "%s", id(room_temperature).state.c_str());
- id: page_alarm
lambda: |-
it.printf(0, 0, id(mdi_xs), TextAlign::TOP_LEFT, "%s", "");
it.printf(64,0 , id(mdi_xs), TextAlign::TOP_CENTER, "%s", "");
it.printf(127, 0, id(mdi_xs), TextAlign::TOP_RIGHT, "%s", "");
it.print(1, 63, id(mdi), TextAlign::BOTTOM_LEFT, "");
it.printf(43, 60, id(roboto_large), TextAlign::BOTTOM_LEFT, "%s", id(wake_time).state.c_str());
- id: page_lighting
lambda: |-
it.printf(0, 0, id(roboto_xsmall), TextAlign::TOP_LEFT, "%s", "Cozy");
it.printf(64,0 , id(roboto_xsmall), TextAlign::TOP_CENTER, "%s", "Auto");
it.printf(127, 0, id(roboto_xsmall), TextAlign::TOP_RIGHT, "%s", "High");
it.print(1, 63, id(mdi), TextAlign::BOTTOM_LEFT, "");
it.printf(43, 60, id(roboto_large), TextAlign::BOTTOM_LEFT, "%s", id(room_scene).state.c_str());
- id: page_fan
lambda: |-
it.printf(0, 0, id(roboto_xsmall), TextAlign::TOP_LEFT, "%s", "Off");
it.printf(64,0 , id(roboto_xsmall), TextAlign::TOP_CENTER, "%s", "On");
it.printf(127, 0, id(roboto_xsmall), TextAlign::TOP_RIGHT, "%s", "Turbo");
it.print(1, 63, id(mdi), TextAlign::BOTTOM_LEFT, "");
it.printf(43, 60, id(roboto_large), TextAlign::BOTTOM_LEFT, "%s", id(room_fan).state.c_str());
- id: page_wifi_ok
lambda: |-
it.print(64, -1, id(mdi), TextAlign::CENTER_HORIZONTAL, "");
it.print(64, 36, id(roboto_large), TextAlign::CENTER_HORIZONTAL, "WiFi OK");
- id: page_wifi_err
lambda: |-
it.print(64, -1, id(mdi), TextAlign::CENTER_HORIZONTAL, "");
it.print(64, 36, id(roboto_large), TextAlign::CENTER_HORIZONTAL, "No WiFi");
- id: page_check
lambda: |-
it.print(64, -1, id(mdi), TextAlign::CENTER_HORIZONTAL, "");
it.print(64, 36, id(roboto_large), TextAlign::CENTER_HORIZONTAL, "Done");
- id: page_sleep
lambda: |-
it.print(64, -1, id(mdi), TextAlign::CENTER_HORIZONTAL, "");
it.print(64, 36, id(roboto_large), TextAlign::CENTER_HORIZONTAL, "Sleep");
- id: page_wake
lambda: |-
it.print(64, -1, id(mdi), TextAlign::CENTER_HORIZONTAL, "");
it.print(64, 36, id(roboto_large), TextAlign::CENTER_HORIZONTAL, "Wakeup");
- id: page_cozy
lambda: |-
it.print(64, -1, id(mdi), TextAlign::CENTER_HORIZONTAL, "");
it.print(64, 36, id(roboto_large), TextAlign::CENTER_HORIZONTAL, "Cozy");
- id: page_unknown_page
lambda: |-
it.print(64, -1, id(mdi), TextAlign::CENTER_HORIZONTAL, "");
it.print(64, 36, id(roboto_large), TextAlign::CENTER_HORIZONTAL, "Unknown");
- id: page_boot
lambda: |-
it.print(64, -1, id(mdi), TextAlign::CENTER_HORIZONTAL, "");
it.print(64, 51, id(roboto_xsmall), TextAlign::BOTTOM_CENTER, "Clock Radio");
it.printf(64, 63, id(roboto_xxsmall), TextAlign::BOTTOM_CENTER, "%s", id(version_string).state.c_str());
- id: page_blank
lambda: ""
# - OFF for at least 350ms
binary_sensor:
- platform: gpio
id: button_1
pin:
number: GPIO39
mode:
input: true
#pullup: true (external pull-down)
inverted: false
on_multi_click:
- timing:
- ON for at most 399ms
then:
- if:
condition:
- lambda: return !id(display_switch).state;
then:
- switch.turn_on: display_switch
else:
- script.execute: toggle_mode
- timing:
- ON for at least 400ms
then:
- script.execute: confirm
- platform: gpio
id: button_2
pin:
number: GPIO34
mode:
input: true
#pullup: true (external pull-down)
inverted: false
on_multi_click:
- timing:
- ON for at most 399ms
then:
- script.execute: button_2_short_press
- timing:
- ON for at least 400ms
then:
- script.execute: button_2_long_press
- platform: gpio
id: button_3
pin:
number: GPIO35
mode:
input: true
#pullup: true (external pull-down)
inverted: false
on_multi_click:
- timing:
- ON for at most 399ms
then:
- script.execute: button_3_short_press
- timing:
- ON for at least 400ms
then:
- script.execute: button_3_long_press
- platform: gpio
id: button_4
on_press:
then:
script.execute: button_4_short_press
pin:
number: GPIO32
mode:
input: true
pulldown: true
inverted: false
- platform: gpio
id: button_5
on_multi_click:
- timing:
- ON for at most 399ms
then:
- if:
condition:
text_sensor.state:
id: room_scene
state: 'Sleeping'
then:
- homeassistant.service:
service: script.turn_on
data:
entity_id: script.trigger_bedroom_wakeup
- script.execute:
id: show_status_page
page: page_wake
- delay: 5s
- lambda: 'id(action_mode) = 0;'
- script.execute: show_default_page
else:
- homeassistant.service:
service: script.turn_on
data:
entity_id: script.trigger_bedroom_sleep
- script.execute:
id: show_status_page
page: page_sleep
- delay: 5s
- lambda: 'id(action_mode) = 0;'
- script.execute: show_default_page
- timing:
- ON for at least 400ms
then:
- homeassistant.service:
service: script.turn_on
data:
entity_id: script.trigger_bedroom_cozy
- script.execute:
id: show_status_page
page: page_cozy
- delay: 5s
- lambda: 'id(action_mode) = 0;'
- script.execute: show_default_page
pin:
number: GPIO33
mode:
input: true
pulldown: true
inverted: false
- platform: gpio
id: button_6
name: $friendly_name Extra Button
pin:
number: GPIO4
mode:
input: true
pullup: true
inverted: true
light:
- platform: rgb
name: $friendly_name RGB
id: status_light
restore_mode: ALWAYS_OFF
red: output_red
green: output_green
blue: output_blue
effects:
- strobe:
name: Strobe
colors:
- state: true
brightness: 100%
red: 100%
green: 100%
blue: 100%
duration: 100ms
- state: false
duration: 100ms
- state: true
brightness: 100%
red: 100%
green: 100%
blue: 100%
duration: 100ms
- state: false
duration: 100ms
- state: true
brightness: 100%
red: 100%
green: 100%
blue: 100%
duration: 100ms
- state: false
duration: 500ms
- state: true
brightness: 100%
red: 100%
green: 100%
blue: 100%
duration: 500ms
- state: false
duration: 500ms
- platform: neopixelbus
type: GRB
variant: WS2811
pin: GPIO16
num_leds: 8
name: "$friendly_name NeoPixel"
id: neopoxel
effects:
- addressable_fireworks:
name: Fireworks Effect
update_interval: 32ms
spark_probability: 20%
use_random_color: false
fade_out_rate: 120
- addressable_random_twinkle:
name: Random Twinkle Effect
twinkle_probability: 5%
progress_interval: 32ms
- strobe:
name: Strobe
colors:
- state: true
brightness: 100%
red: 100%
green: 100%
blue: 100%
duration: 50ms
- state: false
duration: 50ms
- state: true
brightness: 100%
red: 100%
green: 100%
blue: 100%
duration: 50ms
- state: false
duration: 50ms
- state: true
brightness: 100%
red: 100%
green: 100%
blue: 100%
duration: 50ms
- state: false
duration: 50ms
- state: true
brightness: 100%
red: 100%
green: 100%
blue: 100%
duration: 50ms
- state: false
duration: 500ms
- state: true
brightness: 100%
red: 100%
green: 100%
blue: 100%
duration: 500ms
- state: false
duration: 500ms
- addressable_flicker:
name: Flicker Effect With Custom Values
update_interval: 16ms
intensity: 20%
- addressable_color_wipe:
name: Color Wipe Effect With Custom Values
colors:
- red: 50%
green: 50%
blue: 50%
num_leds: 1
- red: 100%
green: 100%
blue: 100%
num_leds: 1
- red: 50%
green: 50%
blue: 50%
num_leds: 1
- red: 0%
green: 0%
blue: 0%
num_leds: 7
- red: 50%
green: 0%
blue: 0%
num_leds: 1
- red: 100%
green: 0%
blue: 0%
num_leds: 1
- red: 50%
green: 0%
blue: 0%
num_leds: 1
- red: 0%
green: 0%
blue: 0%
num_leds: 7
- red: 0%
green: 0%
blue: 50%
num_leds: 1
- red: 0%
green: 0%
blue: 100%
num_leds: 1
- red: 0%
green: 0%
blue: 50%
num_leds: 1
- red: 0%
green: 0%
blue: 0%
num_leds: 7
- red: 50%
green: 50%
blue: 0%
num_leds: 1
- red: 100%
green: 100%
blue: 0%
num_leds: 1
- red: 50%
green: 50%
blue: 0%
num_leds: 1
- red: 0%
green: 0%
blue: 0%
num_leds: 7
- red: 0%
green: 50%
blue: 50%
num_leds: 1
- red: 0%
green: 100%
blue: 100%
num_leds: 1
- red: 0%
green: 50%
blue: 50%
num_leds: 1
- red: 0%
green: 0%
blue: 0%
num_leds: 7
- red: 50%
green: 0%
blue: 50%
num_leds: 1
- red: 100%
green: 0%
blue: 100%
num_leds: 1
- red: 50%
green: 0%
blue: 50%
num_leds: 1
- red: 0%
green: 0%
blue: 0%
num_leds: 7
add_led_interval: 150ms
reverse: false
- addressable_scan:
name: Bounce
move_interval: 100ms
scan_width: 1
- automation:
name: Strobe Automation 1
sequence:
- light.addressable_set:
id: neopoxel
range_from: 0
range_to: 3
red: 0%
green: 0%
blue: 0%
- light.addressable_set:
id: neopoxel
range_from: 4
range_to: 7
red: 100%
green: 100%
blue: 100%
- delay: 100ms
- light.addressable_set:
id: neopoxel
range_from: 0
range_to: 7
red: 0%
green: 0%
blue: 0%
- delay: 100ms
- light.addressable_set:
id: neopoxel
range_from: 0
range_to: 3
red: 100%
green: 100%
blue: 100%
- light.addressable_set:
id: neopoxel
range_from: 4
range_to: 7
red: 0%
green: 0%
blue: 0%
- delay: 100ms
- light.addressable_set:
id: neopoxel
range_from: 0
range_to: 7
red: 0%
green: 0%
blue: 0%
- delay: 300ms
- light.addressable_set:
id: neopoxel
range_from: 0
range_to: 3
red: 0%
green: 0%
blue: 0%
- light.addressable_set:
id: neopoxel
range_from: 4
range_to: 7
red: 100%
green: 100%
blue: 100%
- delay: 200ms
- light.addressable_set:
id: neopoxel
range_from: 4
range_to: 7
red: 0%
green: 0%
blue: 0%
- light.addressable_set:
id: neopoxel
range_from: 0
range_to: 3
red: 100%
green: 100%
blue: 100%
- delay: 200ms
- light.addressable_set:
id: neopoxel
range_from: 0
range_to: 7
red: 0%
green: 0%
blue: 0%
- delay: 300ms
- strobe:
name: Strobe Automation 2
colors:
- state: true
brightness: 100%
red: 0%
green: 100%
blue: 100%
duration: 50ms
- state: false
duration: 50ms
- state: true
brightness: 100%
red: 0%
green: 100%
blue: 100%
duration: 50ms
- state: false
duration: 50ms
- state: true
brightness: 100%
red: 0%
green: 100%
blue: 100%
duration: 50ms
- state: false
duration: 50ms
- state: true
brightness: 100%
red: 0%
green: 100%
blue: 100%
duration: 50ms
- state: false
duration: 500ms
- state: true
brightness: 100%
red: 0%
green: 100%
blue: 100%
duration: 500ms
- state: false
duration: 500ms
script:
- id: toggle_mode
mode: single
then:
- logger.log:
format: "Mode before %i"
args: [ 'id(action_mode)']
- lambda: 'id(action_mode) = (id(action_mode) +1) % 4;'
- logger.log:
format: "Mode after %i"
args: [ 'id(action_mode)']
- script.execute: update_page
- id: update_page
mode: single
then:
- if:
condition:
- lambda: return id(action_mode) == 0;
then:
- script.execute:
id: show_default_page
- if:
condition:
- lambda: return id(action_mode) == 1;
then:
- script.execute:
id: show_status_page
page: page_alarm
- if:
condition:
- lambda: return id(action_mode) == 2;
then:
- script.execute:
id: show_status_page
page: page_lighting
- if:
condition:
- lambda: return id(action_mode) == 3;
then:
- script.execute:
id: show_status_page
page: page_fan
- id: show_status_page
mode: single
parameters:
page: string
then:
- globals.set:
id: has_custom_page
value: 'true'
- display.page.show: !lambda |-
if (page == "page_check") {
return id(page_check);
}
if (page == "page_sleep") {
return id(page_sleep);
}
if (page == "page_wake") {
return id(page_wake);
}
if (page == "page_cozy") {
return id(page_cozy);
}
if (page == "page_wifi_ok") {
return id(page_wifi_ok);
}
if (page == "page_wifi_err") {
return id(page_wifi_err);
}
if (page == "page_alarm") {
return id(page_alarm);
}
if (page == "page_lighting") {
return id(page_lighting);
}
if (page == "page_fan") {
return id(page_fan);
}
if (page == "page_boot") {
return id(page_boot);
}
if (page == "page_blank") {
return id(page_blank);
}
return id(page_unknown_page);
- component.update: oled_display
- id: show_default_page
mode: single
then:
- globals.set:
id: has_custom_page
value: 'false'
- display.page.show: page_default
- component.update: oled_display
- id: confirm
mode: single
then:
- light.turn_on:
id: status_light
red: 0
green: 100%
blue: 0
brightness: 25%
transition_length: 100ms
- script.execute:
id: show_status_page
page: page_check
- delay: 300ms
- light.turn_off: status_light
- delay: 1700ms
- lambda: 'id(action_mode) = 0;'
- script.execute: show_default_page
- id: button_2_short_press
mode: queued
then:
- logger.log: "Button 2 short press"
- if:
condition:
- lambda: return id(action_mode) == 1; // Alarm
then:
- logger.log: 'Mode is 1'
- homeassistant.service:
service: script.turn_on
data:
entity_id: script.wakeup_earlier
- delay: 100ms
- component.update: oled_display
- if:
condition:
- lambda: return id(action_mode) == 2; // Lighting
then:
- logger.log: 'Mode is 2'
- homeassistant.service:
service: switch.turn_on
data:
entity_id: switch.bedroom_cozy
- if:
condition:
- lambda: return id(action_mode) == 3; // Fan
then:
- logger.log: 'Mode is 3'
- homeassistant.service:
service: switch.turn_on
data:
entity_id: switch.ir_electrolux_state_off
- if:
condition:
- lambda: return id(action_mode) == 0; // Main
then:
- logger.log: 'Mode is 0'
- lambda: 'id(action_mode) = 1;'
- delay: 100ms
- script.execute: update_page
- id: button_2_long_press
mode: queued
then:
- if:
condition:
- lambda: return id(action_mode) == 1; // Alarm
then:
- homeassistant.service:
service: script.turn_on
data:
entity_id: script.wakeup_earlier_5m
- id: button_3_short_press
mode: queued
then:
- if:
condition:
- lambda: return id(action_mode) == 1; // Alarm
then:
- homeassistant.service:
service: script.turn_on
data:
entity_id: script.wakeup_later
- delay: 100ms
- component.update: oled_display
- if:
condition:
- lambda: return id(action_mode) == 2; // Lighting
then:
- homeassistant.service:
service: switch.turn_on
data:
entity_id: switch.bedroom_auto
- if:
condition:
- lambda: return id(action_mode) == 3; // Fan
then:
- homeassistant.service:
service: switch.turn_on
data:
entity_id: switch.ir_electrolux_state_normal
- if:
condition:
- lambda: return id(action_mode) == 0; // Main
then:
- logger.log: 'Mode is 0'
- lambda: 'id(action_mode) = 2;'
- delay: 100ms
- script.execute: update_page
- id: button_3_long_press
mode: queued
then:
- if:
condition:
- lambda: return id(action_mode) == 1; // Alarm
then:
- homeassistant.service:
service: script.turn_on
data:
entity_id: script.wakeup_later_5m
- if:
condition:
- lambda: return id(action_mode) == 3; // Fan
then:
- homeassistant.service:
service: switch.turn_on
data:
entity_id: switch.ir_electrolux_fan_speed
- id: button_4_short_press
mode: queued
then:
- if:
condition:
- lambda: return id(action_mode) == 2; // Lighting
then:
- homeassistant.service:
service: switch.turn_on
data:
entity_id: switch.bedroom_high
- if:
condition:
- lambda: return id(action_mode) == 3; // Fan
then:
- homeassistant.service:
service: switch.turn_on
data:
entity_id: switch.ir_electrolux_state_turbo
- if:
condition:
- lambda: return id(action_mode) == 0; // Main
then:
- logger.log: 'Mode is 0'
- lambda: 'id(action_mode) = 3;'
- delay: 100ms
- script.execute: update_page
button:
- platform: template
name: $friendly_name Play Mario
on_press:
then:
- rtttl.play: 'Mario:d=4,o=5,b=100:16e6,16e6,32p,8e6,16c6,8e6,8g6,8p,8g,8p,8c6,16p,8g,16p,8e,16p,8a,8b,16a#,8a,16g.,16e6,16g6,8a6,16f6,8g6,8e6,16c6,16d6,8b,16p,8c6,16p,8g,16p,8e,16p,8a,8b,16a#,8a,16g.,16e6,16g6,8a6,16f6,8g6,8e6,16c6,16d6,8b,8p,16g6,16f#6,16f6,16d#6,16p,16e6,16p,16g#,16a,16c6,16p,16a,16c6,16d6,8p,16g6,16f#6,16f6,16d#6,16p,16e6,16p,16c7,16p,16c7,16c7,p,16g6,16f#6,16f6,16d#6,16p,16e6,16p,16g#,16a,16c6,16p,16a,16c6,16d6,8p,16d#6,8p,16d6,8p,16c6'
- platform: template
name: $friendly_name Play Simpsons
on_press:
then:
- rtttl.play: 'Simpsons:d=4,o=5,b=160:c.6,e6,f#6,8a6,g.6,e6,c6,8a,8f#,8f#,8f#,2g,8p,8p,8f#,8f#,8f#,8g,a#.,8c6,8c6,8c6,c6'
- platform: template
name: $friendly_name Play Starwars
on_press:
then:
- rtttl.play: 'StarWars:d=4,o=5,b=45:32p,32f#,32f#,32f#,8b.,8f#.6,32e6,32d#6,32c#6,8b.6,16f#.6,32e6,32d#6,32c#6,8b.6,16f#.6,32e6,32d#6,32e6,8c#.6,32f#,32f#,32f#,8b.,8f#.6,32e6,32d#6,32c#6,8b.6,16f#.6,32e6,32d#6,32c#6,8b.6,16f#.6,32e6,32d#6,32e6,8c#6'
- platform: template
name: $friendly_name Play Bond
on_press:
then:
- rtttl.play: 'Bond:d=4,o=5,b=80:32p,16c#6,32d#6,32d#6,16d#6,8d#6,16c#6,16c#6,16c#6,16c#6,32e6,32e6,16e6,8e6,16d#6,16d#6,16d#6,16c#6,32d#6,32d#6,16d#6,8d#6,16c#6,16c#6,16c#6,16c#6,32e6,32e6,16e6,8e6,16d#6,16d6,16c#6,16c#7,c.7,16g#6,16f#6,g#.6'
- platform: template
name: $friendly_name Play Adams Family
on_press:
then:
- rtttl.play: 'AdamsFamily:d=8,o=5,b=160,b=160:c,4f,a,4f,c,4b4,2g,f,4e,g,4e,g4,4c,2f,c,4f,a,4f,c,4b4,2g,f,4e,c,4d,e,1f,c,d,e,f,1p,d,e,f#,g,1p,d,e,f#,g,4p,d,e,f#,g,4p,c,d,e,f'
- platform: template
name: $friendly_name Play Popcorn
on_press:
then:
- rtttl.play: 'Popcorn:d=16,o=5,b=160,b=160:a,p,g,p,a,p,e,p,c,p,e,p,8a4,8p,a,p,g,p,a,p,e,p,c,p,e,p,8a4,8p,a,p,b,p,c6,p,b,p,c6,p,a,p,b,p,a,p,b,p,g,p,a,p,g,p,a,p,f,8a,8p,a,p,g,p,a,p,e,p,c,p,e,p,8a4,8p,a,p,g,p,a,p,e,p,c,p,e,p,8a4,8p,a,p,b,p,c6,p,b,p,c6,p,a,p,b,p,a,p,b,p,g,p,a,p,g,p,a,p,b,4c6'
- platform: template
name: $friendly_name Play Happy Birthday
on_press:
then:
- rtttl.play: 'HappyBirthday:d=4,o=5,b=125:8g.,16g,a,g,c6,2b,8g.,16g,a,g,d6,2c6,8g.,16g,g6,e6,c6,b,a,8f6.,16f6,e6,c6,d6,2c6,8g.,16g,a,g,c6,2b,8g.,16g,a,g,d6,2c6,8g.,16g,g6,e6,c6,b,a,8f6.,16f6,e6,c6,d6,2c6'
switch:
- platform: template
name: "$friendly_name Night Mode"
id: night_mode_switch
restore_mode: ALWAYS_ON
lambda: |-
return id(is_night_mode);
turn_on_action:
- globals.set:
id: is_night_mode
value: 'true'
- lambda: id(oled_display).set_contrast(0.01);
- component.update: oled_display
turn_off_action:
- globals.set:
id: is_night_mode
value: 'false'
- lambda: id(oled_display).set_contrast(0.95);
- component.update: oled_display
- platform: template
id: display_switch
name: "$friendly_name Display"
lambda: |-
return id(oled_display).get_active_page() != id(page_blank);
turn_on_action:
- lambda: 'id(action_mode) = 0;'
- script.execute:
id: show_default_page
turn_off_action:
- script.execute:
id: show_status_page
page: page_blank
interval:
- interval: 6sec
then:
- globals.set:
id: display_sequence
value: !lambda |-
return (id(display_sequence) + 1);
- if:
condition:
wifi.connected:
then:
- if:
condition:
- lambda: |-
return !id(has_ever_had_wifi);
then:
- logger.log: "WiFi OK!"
- light.turn_on:
id: neopoxel
red: 0
green: 100%
blue: 0
brightness: 50%
- globals.set:
id: has_ever_had_wifi
value: 'true'
- script.execute:
id: show_status_page
page: page_wifi_ok
- delay: 2s
- light.turn_off:
id: neopoxel
- if:
condition:
- lambda: |-
return id(display_sequence) < 3;
then:
- script.execute:
id: show_status_page
page: page_boot
else:
- script.execute:
id: show_default_page
else:
- if:
condition:
- lambda: |-
return !id(has_custom_page);
then:
- script.execute:
id: show_default_page
else:
- logger.log: No WiFi"
- if:
condition:
- lambda: |-
return id(display_sequence) < 2;
then:
- light.turn_on:
id: neopoxel
red: 100%
green: 0
blue: 100%
brightness: 50%
- script.execute:
id: show_status_page
page: page_boot
else:
- light.turn_on:
id: neopoxel
red: 100%
green: 0
blue: 0
brightness: 60%
- script.execute:
id: show_status_page
page: page_wifi_err
- globals.set:
id: has_ever_had_wifi
value: 'false'
text_sensor:
- platform: version
id: version_string
name: $friendly_name Version
- platform: wifi_info
ip_address:
name: $friendly_name IP
ssid:
name: $friendly_name SSID
- platform: homeassistant
id: current_time
entity_id: sensor.clock_radio_time
- platform: homeassistant
id: wake_time
entity_id: sensor.clock_radio_alarm
- platform: homeassistant
id: room_fan
entity_id: sensor.clock_radio_fan
- platform: homeassistant
id: room_temperature
entity_id: sensor.clock_radio_temperature
- platform: homeassistant
id: room_scene
entity_id: sensor.clock_radio_scene
Ok, found the problem. In your YAML:
switch:
- platform: template
name: "$friendly_name Night Mode"
id: night_mode_switch
restore_mode: ALWAYS_ON
lambda: |-
return id(is_night_mode);
turn_on_action:
- globals.set:
id: is_night_mode
value: 'true'
- lambda: id(oled_display).set_contrast(0.01); <-------------
- component.update: oled_display
The switch gets turned on as part of after-boot restore, so set_contrast
call is done before the display has been setup, so the SPI is not initialised at that time.
It might be argued that the ssd1306 driver is structured incorrectly, as it probably should not write directly to the SPI when values are changed, but simply store the value and update it when its update()
method is called (which will be after setup.)
For your YAML you might want to defer setting contrast or any other direct call to the display in lambdas until after setup is complete.
I would note that the initial on-restore set_contrast()
probably never worked anyway, it just silently failed.
I tried commenting out that line with set_contrast() and the error disappeared.
I would note that the initial on-restore set_contrast() probably never worked anyway, it just silently failed.
Perhaps.
Yet, I want the behaviour of that switch to adjust the contrast of the display. Both the turn_on_action and the turn_off_action adjusts the contrast of the display. And that is how I want it to be. And since the state is binary (it is either on or off) the button will be restored to any of those two states, and both of them will set the contrast --> error message.
I could of course wrap that row in an additional if-clause to prevent that row to happen too early, yet be there in all other situations. It would not really have an impact on the behaviour of the device as it is essentially always connected to power (it typically only reboots to bump the ESPHome software). But it would make an already messy code even messier.
It might be argued that the ssd1306 driver is structured incorrectly, as it probably should not write directly to the SPI when values are changed, but simply store the value and update it when its update() method is called (which will be after setup.)
I totally agree. And since that is unfortunately not the current behaviour then I guess I would have to go for that if-clause...
Or you can just leave things as they are and ignore the messages in the log. Other than that message, nothing now behaves differently to what it did before (now that the crashing, which was totally my fault, has been fixed.)
That's probably what I'd do for now at least.
Aha, I found another solution - add a line to your yaml to make the display have higher setup priority than the switch.
display:
- platform: ssd1306_spi
setup_priority: 950
The display by default gets set up after the switches. Template switches have priority HARDWARE
which seems odd since they are not hardware (if I were King I would call them "virtual" switches, not templates :-) Displays, or at least the ssd1306, have priority PROCESSOR
which also makes little sense to me.
Anyway, in your case you want the display to have a higher priority than anything that touches it.
The problem
After update to 2023.9.0 (from 2023.8.3), all my units that has a display with SPI interface are bricked. Not the screen itself, the entire ESP32 refuses to boot. Neither power cycling nor pressing the reset button solves the issue, and the unit is no longer available for OTA updates.
Upon connecting a device using USB, I was able to retrieve the logs.
Rolling back to ESP Home 2023.8.3 and upload the software by USB fixes the issue (with working display). Removing the display: block (see below) also fixes the issue and works with ESP Home 2023.9.0 but for obvious reasons the display does not work in this case.
Logs:
The device reboots every second and the logs looks like in the screenshot above.
Which version of ESPHome has the issue?
2023.9.0
What type of installation are you using?
Home Assistant Add-on
Which version of Home Assistant has the issue?
2023.9.3
What platform are you using?
ESP32
Board
az-delivery-devkit-v4
Component causing the issue
display (SPI?)
Example YAML snippet
Anything in the logs that might be useful for us?
Additional information
No response