Okay, this is getting ridiculous. I had written a minimal yaml file for the new setup which allowed me to test all connected devices. That yaml code already had the 270° display rotation:
esphome:
name: quinled1
esp32:
board: mhetesp32minikit
framework:
type: arduino
# Enable logging
logger:
# Enable Home Assistant API
api:
password: ""
ota:
password: ""
wifi:
ssid: "xxxxxxxxx"
password: "xxxxxxxxxx"
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "Quinled1 Fallback Hotspot"
password: "xxxxxxxx"
captive_portal:
uart:
rx_pin: 21
tx_pin: 22
baud_rate: 9600
spi:
clk_pin: 16
mosi_pin: 23
light:
- platform: neopixelbus
type: GRB
variant: WS2812X
pin: 13
num_leds: 3
name: "qLED notification hallway"
id: qled_notification_hallway
effects:
- addressable_twinkle:
name: "Twinkle"
twinkle_probability: 5%
progress_interval: 4ms
sensor:
- platform: dht
pin: 17
model: DHT22
temperature:
name: "qHallway Temperature"
id: qhallwaytemp
humidity:
name: "qHallway Humidity"
id: qhallwayhum
update_interval: 60s
- platform: mhz19
co2:
name: "qhallway co2"
id: qhallwayco2
temperature:
name: "MH-Z19 Temperature"
id: qm19temp
update_interval: 60s
automatic_baseline_calibration: false
binary_sensor:
- platform: gpio
pin:
number: 4
mode:
input: true
pullup: true
inverted: true
name: qbutton1
filters:
- delayed_on: 10ms
on_press:
- light.turn_on:
id: qled_notification_hallway
brightness: 20%
red: 50%
green: 30%
blue: 0%
- platform: gpio
pin:
number: 12
mode:
input: true
pullup: true
inverted: true
name: qbutton2
filters:
- delayed_on: 10ms
on_press:
- light.turn_off:
id: qled_notification_hallway
display:
- platform: waveshare_epaper
cs_pin: 19
dc_pin: 18
busy_pin: 26
reset_pin: 33
model: 2.90inv2
rotation: 270°
update_interval: 90s
full_update_every: 1
#reset_duration: 2ms
id: qeink
lambda: |-
it.line(0, 0, 50, 50);
When all of that worked fine, I finished the new housing and put all components in, still with the test code above. Still everyone running smooth.
So now I took the old yaml file of the original node, and changed all board and pin settings to the new quinled board.
Flashed that, worked fine, but of course still had the screen the wrong way around. So I did the same thing that got me here 2 weeks ago: changed “rotation: 90°” to “rotation: 270°”, compiled flashed, and the display IS DEAD AGAIN!
The log shows this:
[21:51:18][E][waveshare_epaper:119]: Timeout while displaying image!
I have to miss something, but I don’t know what. It cannot be the 270 itself, because that works fine in the test code. But once I switch to 270 in the proper code, the display stops working. Frustration galore.
This is the code that works fine with 90°, but breaks the display when switched to 270°. Any ideas what the issue could be?
esphome:
name: epaper
esp32:
board: mhetesp32minikit
framework:
type: arduino
# Enable logging
logger:
json:
# Enable Home Assistant API
api:
password: ""
ota:
password: ""
wifi:
ssid: "xxxxxxxxx"
password: "xxxxxxxxxx"
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "Epaper Fallback Hotspot"
password: "xxxxxxxx"
captive_portal:
light:
- platform: neopixelbus
type: GRB
variant: WS2812X
pin: 13
num_leds: 3
name: "LED notification hallway"
id: led_notification_hallway
effects:
- addressable_twinkle:
name: "Twinkle"
twinkle_probability: 5%
progress_interval: 4ms
uart:
rx_pin: 21
tx_pin: 22
baud_rate: 9600
font:
- file: 'arial.ttf'
id: font1
size: 24
- file: 'arial.ttf'
id: font2
size: 30
- file: 'arial.ttf'
id: fontsmall
size: 12
- file: 'arial.ttf'
id: fontbig
size: 30
glyphs:
['&', '@', '!', ',', '.', '"', '%', '(', ')', '+', '-', '_', ':', '°', '0',
'1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E',
'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
'T', 'U', 'V', 'W', 'X', 'Y', 'Z', ' ', 'a', 'b', 'c', 'd', 'e', 'f',
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
'u', 'v', 'w', 'x', 'y', 'z','å', 'ä', 'ö', '/']
- file: 'DejaVuSansMono-Bold.ttf'
id: dejamonobold
size: 44
glyphs:
['&', '@', '!', ',', '.', '"', '%', '(', ')', '+', '-', '_', ':', '°', '0',
'1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E',
'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
'T', 'U', 'V', 'W', 'X', 'Y', 'Z', ' ', 'a', 'b', 'c', 'd', 'e', 'f',
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
'u', 'v', 'w', 'x', 'y', 'z','å', 'ä', 'ö', '/']
- file: 'DejaVuSansMono-Bold.ttf'
id: dejamonoboldsmall
size: 24
glyphs:
['&', '@', '!', ',', '.', '"', '%', '(', ')', '+', '-', '_', ':', '°', '0',
'1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E',
'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
'T', 'U', 'V', 'W', 'X', 'Y', 'Z', ' ', 'a', 'b', 'c', 'd', 'e', 'f',
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
'u', 'v', 'w', 'x', 'y', 'z','å', 'ä', 'ö', '/']
image:
- file: "puppy30.bmp"
id: puppy
- file: "puppy30left.bmp"
id: puppyleft
- file: "moonthick.bmp"
id: moonthick
- file: "moonthin.bmp"
id: moonthin
- file: "clear-night.bmp"
id: clear_night
- file: "cloudy.bmp"
id: cloudy
- file: "exceptional.bmp"
id: exceptional
- file: "fog.bmp"
id: fog
- file: "hail.bmp"
id: hail
- file: "lightning.bmp"
id: lightning
- file: "lightning-rainy.bmp"
id: lightning_rainy
- file: "partlycloudy.bmp"
id: partlycloudy
- file: "pouring.bmp"
id: pouring
- file: "rainy.bmp"
id: rainy
- file: "snowy.bmp"
id: snowy
- file: "snowy-rainy.bmp"
id: snowy_rainy
- file: "sunny.bmp"
id: sunny
- file: "windy.bmp"
id: windy
- file: "windyvariant.bmp"
id: windy_variant
- file: "clearnight45.bmp"
id: clear_night45
- file: "cloudy45.bmp"
id: cloudy45
- file: "exceptional45.bmp"
id: exceptional45
- file: "fog45.bmp"
id: fog45
- file: "hail45.bmp"
id: hail45
- file: "lightning45.bmp"
id: lightning45
- file: "lightningrainy45.bmp"
id: lightning_rainy45
- file: "partlycloudy45.bmp"
id: partlycloudy45
- file: "pouring45.bmp"
id: pouring45
- file: "rainy45.bmp"
id: rainy45
- file: "snowy45.bmp"
id: snowy45
- file: "snowy-rainy45.bmp"
id: snowy_rainy45
- file: "sunny45.bmp"
id: sunny45
- file: "windy45.bmp"
id: windy45
- file: "windy-variant45.bmp"
id: windy_variant45
globals:
- id: dogmeter
type: int
restore_value: no
initial_value: '1'
time:
- platform: homeassistant
id: esptime
on_time:
- hours: 6
minutes: 0
seconds: 0
then:
- globals.set:
id: dogmeter
value: '2'
- hours: 9
minutes: 0
seconds: 0
then:
- globals.set:
id: dogmeter
value: '1'
- hours: 17
minutes: 0
seconds: 0
then:
- globals.set:
id: dogmeter
value: '2'
- hours: 21
minutes: 0
seconds: 0
then:
- globals.set:
id: dogmeter
value: '0'
sensor:
- platform: homeassistant
id: outside_temperature
entity_id: sensor.lumi_lumi_weather_a5f3bb07_temperature
internal: true
- platform: homeassistant
id: windspeed
entity_id: sensor.openweathermap_wind_speed
internal: true
- platform: homeassistant
id: maxtemp
entity_id: sensor.openweathermap_forecast_temperature_2
internal: true
- platform: homeassistant
id: mintemp
entity_id: sensor.openweathermap_forecast_temperature_low_2
internal: true
- platform: dht
pin: 17
model: DHT22
temperature:
name: "Hallway Temperature"
id: hallwaytemp
humidity:
name: "Hallway Humidity"
id: hallwayhum
update_interval: 60s
- platform: mhz19
co2:
name: "hallway co2"
id: hallwayco2
on_value_range:
- above: 800
below: 1000
then:
- light.turn_on:
id: led_notification_hallway
brightness: 20%
red: 50%
green: 30%
blue: 0%
- above: 999
then:
- light.turn_on:
id: led_notification_hallway
brightness: 20%
red: 100%
green: 0%
blue: 0%
- below: 800
then:
- light.turn_off:
id: led_notification_hallway
temperature:
name: "MH-Z19 Temperature"
update_interval: 60s
automatic_baseline_calibration: false
text_sensor:
- platform: homeassistant
id: outside_weather
entity_id: sensor.openweathermap_condition
internal: true
- platform: homeassistant
id: owm_forecast
entity_id: weather.openweathermap
internal: true
attribute: forecast
- platform: homeassistant
id: owm_forecast_days
entity_id: weather.openweathermap_2
internal: true
attribute: forecast
binary_sensor:
- platform: gpio
pin:
number: 32
mode:
input: true
pullup: true
inverted: true
name: button1
filters:
- delayed_on: 10ms
on_press:
- display.page.show: page1
- delay: 1s
- component.update: eink
- platform: gpio
pin:
number: 12
mode:
input: true
pullup: true
inverted: true
name: button2
filters:
- delayed_on: 10ms
on_press:
- display.page.show: page2
- delay: 1s
- component.update: eink
- platform: gpio
pin:
number: 4
mode:
input: true
pullup: true
inverted: true
name: button3
filters:
- delayed_on: 10ms
on_press:
- display.page.show: page3
- delay: 1s
- component.update: eink
- platform: gpio
pin:
number: 27
mode:
input: true
pullup: true
inverted: true
name: button4
filters:
- delayed_on: 10ms
on_press:
- display.page.show: page1
- delay: 1s
- component.update: eink
- platform: gpio
pin:
number: 25
mode:
input: true
pullup: true
inverted: true
name: button5
filters:
- delayed_on: 10ms
- platform: homeassistant
id: bathroom_window
entity_id: binary_sensor.lumi_lumi_sensor_magnet_aq2_4420d107_on_off
internal: true
on_state:
- display.page.show: page1
- delay: 1s
- component.update: eink
spi:
clk_pin: 16
mosi_pin: 23
display:
- platform: waveshare_epaper
cs_pin: 19
dc_pin: 18
busy_pin: 26
reset_pin: 33
model: 2.90inv2
rotation: 90°
update_interval: 300s
full_update_every: 1
#reset_duration: 2ms
id: eink
pages:
- id: page1
lambda: |-
std::map<std::string, Image *> imgDict;
imgDict["clear-night"] = id(clear_night);
imgDict["cloudy"] = id(cloudy);
imgDict["fog"] = id(fog);
imgDict["hail"] = id(hail);
imgDict["lightning"] = id(lightning);
imgDict["lightning-rainy"] = id(lightning_rainy);
imgDict["partlycloudy"] = id(partlycloudy);
imgDict["pouring"] = id(pouring);
imgDict["rainy"] = id(rainy);
imgDict["snowy"] = id(snowy);
imgDict["snowy-rainy"] = id(snowy_rainy);
imgDict["sunny"] = id(sunny);
imgDict["windy"] = id(windy);
imgDict["windy-variant"] = id(windy_variant);
imgDict["exceptional"] = id(exceptional);
it.line(1, 33, 33, 1);
it.line(1, 34, 34, 1);
it.line(1, 35, 35, 1);
it.line(35, 1, 80, 45);
it.line(36, 1, 81, 45);
it.line(37, 1, 82, 45);
it.line(80, 45, 80, 126);
it.line(81, 45, 81, 126);
it.line(80, 125, 206, 125);
it.line(80, 126, 206, 126);
if (id(bathroom_window).has_state()) {
if (id(bathroom_window).state == true) {
it.rectangle(80, 55, 20, 30);
it.rectangle(81, 56, 18, 28);
}
}
if (id(outside_temperature).has_state()) {
it.printf(90, 5, id(dejamonobold), TextAlign::TOP_LEFT, "%2.0f", id(outside_temperature).state);
it.printf(160, 5, id(dejamonobold), TextAlign::TOP_RIGHT, "°");
it.printf(200, 8, id(dejamonoboldsmall), TextAlign::TOP_RIGHT, "%.0f°", id(maxtemp).state);
it.printf(200, 28, id(dejamonoboldsmall), TextAlign::TOP_RIGHT, "%.0f°", id(mintemp).state);
}
if (id(hallwayco2).has_state()) {
it.printf(10, 35, id(dejamonobold), TextAlign::TOP_LEFT, "%2.0f", id(hallwaytemp).state);
it.printf(80, 35, id(dejamonobold), TextAlign::TOP_RIGHT, "°");
it.printf(10, 75, id(dejamonoboldsmall), "%.0f%%", id(hallwayhum).state);
it.printf(10, 96, id(dejamonoboldsmall), "%.0f", id(hallwayco2).state);
}
if (id(outside_weather).has_state()) {
it.image(206, 2, imgDict[id(outside_weather).state]);
}
if (id(owm_forecast).has_state())
{
DynamicJsonDocument doc(5048);
deserializeJson(doc, (id(owm_forecast).state.c_str()));
JsonArray root = doc.as<JsonArray>();
int linestart = 192;
int startX = 206;
int startY = 126;
for (int d=0; d <= 7; ++d)
{
JsonObject root_1 = root[d];
float root_1_precipitation_probability = root_1["precipitation_probability"];
int heighthelper = (2 + (int)root_1_precipitation_probability) / 2;
int offsethelper = 120 - heighthelper;
it.line(startX, startY, startX+12, offsethelper);
it.line(startX, startY-1, startX+12, offsethelper-1);
linestart += 12;
startX += 12;
startY = offsethelper;
}
int dogstart = 175;
for (int dog=0; dog <= id(dogmeter); ++dog)
{
it.image(dogstart, 94, id(puppyleft));
dogstart -= 30;
}
}
- id: page2
lambda: |-
std::map<std::string, Image *> imgDict;
imgDict["clear-night"] = id(clear_night45);
imgDict["cloudy"] = id(cloudy45);
imgDict["fog"] = id(fog45);
imgDict["hail"] = id(hail45);
imgDict["lightning"] = id(lightning45);
imgDict["lightning-rainy"] = id(lightning_rainy45);
imgDict["partlycloudy"] = id(partlycloudy45);
imgDict["pouring"] = id(pouring45);
imgDict["rainy"] = id(rainy45);
imgDict["snowy"] = id(snowy45);
imgDict["snowy-rainy"] = id(snowy_rainy45);
imgDict["sunny"] = id(sunny45);
imgDict["windy"] = id(windy45);
imgDict["windy-variant"] = id(windy_variant45);
imgDict["exceptional"] = id(exceptional45);
std::map<int, const char *> dayDict;
dayDict[1] = "MO";
dayDict[2] = "TU";
dayDict[3] = "WE";
dayDict[4] = "TH";
dayDict[5] = "FR";
dayDict[6] = "SA";
dayDict[7] = "SU";
int day = id(esptime).now().day_of_week;
if (id(owm_forecast_days).has_state())
{
DynamicJsonDocument doc(5048);
deserializeJson(doc, (id(owm_forecast_days).state.c_str()));
JsonArray root = doc.as<JsonArray>();
int linestarticon = 3;
for (int i=1; i <= 6; ++i)
{
if (day > 7)
{
day = 1;
}
JsonObject root_0 = root[i];
float maxtempforecast = root_0["temperature"];
float chanceofrainforecast = root_0["precipitation_probability"];
it.printf(linestarticon, -2, id(dejamonoboldsmall), TextAlign::TOP_LEFT, "%s", dayDict[day]);
it.image(linestarticon, 22, imgDict[root_0["condition"]]);
it.printf(linestarticon, 70, id(dejamonoboldsmall), TextAlign::TOP_LEFT, "%.0f°", maxtempforecast);
if (chanceofrainforecast == 100)
{
it.printf(linestarticon, 93, id(dejamonoboldsmall), TextAlign::TOP_LEFT, "%.0f", chanceofrainforecast);
}
else
{
it.printf(linestarticon, 93, id(dejamonoboldsmall), TextAlign::TOP_LEFT, "%.0f%%", chanceofrainforecast);
}
linestarticon += 48;
day += 1;
}
}
- id: page3
lambda: |-
it.printf(5, 5, id(dejamonoboldsmall), "co2:");
if (id(hallwayco2).has_state()) {
it.printf(5, 30, id(dejamonobold), "%.0f", id(hallwayco2).state);
}
it.printf(130, 5, id(dejamonoboldsmall), "temp:");
if (id(hallwaytemp).has_state()) {
it.printf(130, 30, id(dejamonobold), "%.0f°", id(hallwaytemp).state);
}
it.printf(220, 5, id(dejamonoboldsmall), "hum:");
if (id(hallwayhum).has_state()) {
it.printf(220, 30, id(dejamonobold), "%.0f%%", id(hallwayhum).state);
}