Zuerst ein HINWEIS ACHTUNG
Das neue Design scheint ein kleines Problem zu verursachen. Der Radarsensor löst manchmal grundlos aus.
Ich vermute Störungen durch den Zigbee Temperatursensor weil beide übereinander liegen.
Zuerst mal habe ich die Versorgungsspannung mit einem 100nF Kondensator abgeblockt und einen Spindeltrimmer 1M zur Reduzierung der Empfindlichkeit eingebaut.
Ich teste das noch mal längere Zeit.
Nachdem die erste Version in der Küche hängt. Nun eine Version fürs Schlafzimmer.
Dort muss ich nichts steuern,
möchte aber den CO2-Wert messen und bei zu hohen Werten die Belüftungsanlage schalten.
Zum Messen dient der Sensor MH-Z19B mit einem Messbereich 400 - 5000 ppm.
Dieser hat einen analogen Ausgang, eine serielle Schnittstelle und einen PWM-Ausgang.
Gute Beschreibung hier: http://web.archive.org/web/20230324092606/https://unsinnsbasis.de/co2-sensor-mhz19b/
Ich benutze den PWM-Ausgang. Hier eine Messung mit dem Logikanalyser:
Eine Sekunde entspricht bei meinem Sensor 5000ppm. Also habe ich momentan etwa 620ppm.
Das ist OK - bei 800ppm sollte man lüften.
Hier der ESPHome YAML-Code
esphome:
name: displayb
friendly_name: displayB
esp32:
board: esp32dev
framework:
type: arduino
# Enable logging
logger:
# Enable Home Assistant API
api:
encryption:
key: "yHSIH1xcp2AQ/iMKVDJAmzpwWOYM1BHkW4CFO6yZvU8="
ota:
- platform: esphome
password: "270515ea098d8f5e3c20a7c4448ffad4"
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "Displayb Fallback Hotspot"
password: "m7D7zBsUKHGB"
captive_portal:
globals:
- id: show_return_page
type: bool
restore_value: yes
initial_value: "false"
# Setup a pin to control the backlight and the LED
output:
- platform: ledc
pin: GPIO21
id: backlight_pwm
- platform: ledc
id: output_red
pin: GPIO4
inverted: true
- platform: ledc
id: output_green
pin: GPIO16
inverted: true
- platform: ledc
id: output_blue
pin: GPIO17
inverted: true
light:
- platform: monochromatic
output: backlight_pwm
name: Display Backlight
id: backlight
restore_mode: ALWAYS_ON
- platform: rgb
name: LED
id: led
red: output_red
green: output_green
blue: output_blue
restore_mode: ALWAYS_OFF
# Setup SPI for the display. The ESP32-2432S028R uses separate SPI buses for display and touch
spi:
- id: tft
clk_pin: GPIO14
mosi_pin: GPIO13
miso_pin: GPIO12
- id: touch
clk_pin: GPIO25
mosi_pin: GPIO32
miso_pin: GPIO39
touchscreen:
platform: xpt2046
spi_id: touch
cs_pin: GPIO33
interrupt_pin: GPIO36
update_interval: 50ms
threshold: 400
calibration:
x_min: 280
x_max: 3860
y_min: 340
y_max: 3860
transform:
swap_xy: false
# verwendete Schriften
font:
- file: "gfonts://Roboto"
id: fetcha
size: 25
- file: "gfonts://Kanit"
id: hora
size: 60
- file: "gfonts://Roboto"
id: info
size: 15
- file: "gfonts://Roboto"
id: info2
size: 20
- file: "gfonts://Roboto"
id: botones
size: 11
# Verwendtet Farben
color:
- id: black
hex: '000000'
- id: orange
hex: 'eb9c17'
- id: red
hex: 'b20b23'
- id: green
hex: '148e23'
- id: grey
hex: '464646'
# verwendete icons
image:
- file: mdi:home-thermometer
id: hometemperature
resize: 40x40
- file: mdi:weather-partly-cloudy
id: weather
resize: 40x40
- file: mdi:window-shutter-open
id: offen
resize: 40x40
- file: mdi:window-shutter
id: zu
resize: 40x40
- file: mdi:lightbulb
id: licht
resize: 40x40
- file: mdi:page-previous
id: back
resize: 40x40
# Replace the home gif as you want.
#animation:
# - file: "habbit.gif"
# id: ha
# resize: 70x70
# type: TRANSPARENT_BINARY
# This will fetch time from Home Assistant
time:
- platform: homeassistant
id: esptime
# Create sensors from HA you want to use and show.
sensor:
- platform: homeassistant
id: innentemperatur
entity_id: sensor.temp_kuche_temperature
internal: true
- platform: homeassistant
id: innenluftfeuchte
entity_id: sensor.temp_kuche_humidity
internal: true
- platform: homeassistant
id: absolutinnen
entity_id: sensor.absolute_feuchte_innen
internal: true
- platform: homeassistant
id: aussentemperatur
entity_id: sensor.aussen_temperatur
internal: true
- platform: homeassistant
id: aussenfeuchte
entity_id: sensor.aussen_luftfeuchtigkeit
internal: true
- platform: homeassistant
id: absolutaussen
entity_id: sensor.absolute_feuchte_aussen
internal: true
- platform: homeassistant
id: totalstrom
entity_id: sensor.strom_verbrauch
internal: true
- platform: pulse_width
pin: GPIO27 # Der gelbe Draht
name: "Pulslänge Roh"
id: raw_pulse_width # Sensor-ID für die Weiterverarbeitung
update_interval: 5s
- platform: template
name: "co2wert"
id: co2wert
unit_of_measurement: "ppm"
accuracy_decimals: 0
update_interval: 5s
lambda: |-
if (id(raw_pulse_width).state > 0) {
return id(raw_pulse_width).state * 5000;
} else {
return 0; // Wenn kein Wert vorhanden ist, gib 0 zurück
}
text_sensor:
- platform: homeassistant
id: Licht
entity_id: switch.licht
internal: true
# Hier wird geschaltet!
binary_sensor:
- platform: gpio
device_class: motion
pin:
number: 22
name: bewegung_kueche
- platform: touchscreen
name: Button 1
x_min: 140
x_max: 280
y_min: 0
y_max: 65
on_press:
then:
- if:
condition:
lambda: 'return !id(show_return_page);'
then:
- globals.set:
id: show_return_page
value: !lambda "return !id(show_return_page);"
else:
- homeassistant.service:
service: cover.open_cover
data:
entity_id: cover.rolladen_1
- homeassistant.service:
service: cover.open_cover
data:
entity_id: cover.rolladen_2
- platform: touchscreen
name: Button 2
x_min: 0
x_max: 140
y_min: 0
y_max: 65
on_press:
then:
- if:
condition:
lambda: 'return !id(show_return_page);'
then:
- globals.set:
id: show_return_page
value: !lambda "return !id(show_return_page);"
else:
- homeassistant.service:
service: cover.close_cover
data:
entity_id: cover.rolladen_1
- homeassistant.service:
service: cover.close_cover
data:
entity_id: cover.rolladen_2
- platform: touchscreen
name: Button 3
x_min: 140
x_max: 280
y_min: 65
y_max: 130
on_press:
then:
- if:
condition:
lambda: 'return !id(show_return_page);'
then:
- globals.set:
id: show_return_page
value: !lambda "return !id(show_return_page);"
else:
- homeassistant.service:
service: cover.open_cover
data:
entity_id: cover.rolladen3
- platform: touchscreen
name: Button 4
x_min: 0
x_max: 140
y_min: 65
y_max: 130
on_press:
then:
- if:
condition:
lambda: 'return !id(show_return_page);'
then:
- globals.set:
id: show_return_page
value: !lambda "return !id(show_return_page);"
else:
- homeassistant.service:
service: cover.close_cover
data:
entity_id: cover.rolladen3
- platform: touchscreen
name: Button 5
x_min: 140
x_max: 280
y_min: 130
y_max: 195
on_press:
then:
- if:
condition:
lambda: 'return !id(show_return_page);'
then:
- globals.set:
id: show_return_page
value: !lambda "return !id(show_return_page);"
else:
- homeassistant.service:
service: cover.open_cover
data:
entity_id: cover.rolladen6
- platform: touchscreen
name: Button 6
x_min: 0
x_max: 140
y_min: 130
y_max: 195
on_press:
then:
- if:
condition:
lambda: 'return !id(show_return_page);'
then:
- globals.set:
id: show_return_page
value: !lambda "return !id(show_return_page);"
else:
- homeassistant.service:
service: cover.close_cover
data:
entity_id: cover.rolladen6
- platform: touchscreen
name: Button 7
x_min: 140
x_max: 280
y_min: 195
y_max: 260
on_press:
then:
- if:
condition:
lambda: 'return !id(show_return_page);'
then:
- globals.set:
id: show_return_page
value: !lambda "return !id(show_return_page);"
else:
- homeassistant.service:
service: switch.toggle
data:
entity_id: switch.licht
- platform: touchscreen
name: Button 8
x_min: 0
x_max: 140
y_min: 195
y_max: 260
on_press:
then:
- globals.set:
id: show_return_page
value: !lambda "return !id(show_return_page);"
# Setup the ili9xxx platform
# Display is used as 240x320 by default so we rotate it to 90° model: ili9342 changed to model: ili9341
display:
- platform: ili9xxx
id: esp_display
model: ili9341
spi_id: tft
cs_pin: GPIO15
dc_pin: GPIO2
rotation: 0
invert_colors: false
lambda: |-
if (id(show_return_page)) {
int button_width = 100;
int button_height = 65;
int x_start = 15;
int y_start = 15;
int x_padding = 10;
int y_padding = 10;
// Define los textos para los botones
const char* button_texts[] = {
"Wohnzimmer",
"Wohnzimmer",
"Esszimmer",
"Esszimmer",
"Kueche",
"Kueche",
"Licht WZ",
"Start"
};
for (int row = 0; row < 4; row++) {
for (int col = 0; col < 2; col++) {
int button_index = row * 2 + col;
int x = x_start + col * (button_width + x_padding);
int y = y_start + row * (button_height + y_padding);
it.rectangle(x, y, button_width, button_height, id(grey));
int text_width = strlen(button_texts[button_index]) * 5.5;
int text_height = 16;
it.print(x + (button_width - text_width) / 2, y + (button_height - text_height) / 2 + 20, id(botones), button_texts[button_index]);
}
}
it.image(45, 20, id(offen), id(orange));
it.image(155, 20, id(zu), id(grey));
it.image(45, 95, id(offen), id(orange));
it.image(155, 95, id(zu), id(grey));
it.image(45, 170, id(offen), id(orange));
it.image(155, 170, id(zu), id(grey));
if (id(Licht).state == "on") {
it.image(45, 245, id(licht), id(orange));
} else {
it.image(45, 245, id(licht), id(grey));
}
it.image(155, 245, id(back), id(green));
} else {
static int y = 182;
static int y_direction = 4; // Velocidad del movimiento
const int y_min = 180;
const int y_max = 187;
it.fill(id(black));
it.strftime(120, 12, id(info), TextAlign::CENTER, "%d/%m/%Y", id(esptime).now());
it.strftime(120, 43, id(hora), TextAlign::CENTER, "%H:%M", id(esptime).now());
it.printf(20, 85, id(fetcha), TextAlign::LEFT, "%.0f W", id(totalstrom).state);
it.printf(120, 85, id(fetcha), TextAlign::LEFT, "%.0fppm", id(co2wert).state);
static int current_text_index = 0;
static float text_timer = 0;
const float text_interval = 4.0; // Intervalo para cambiar el texto en segundos
if (current_text_index == 0) {
it.image(15, 130, id(hometemperature), id(green));
it.print(70, 130, id(info), "Innen");
it.printf(175, 130, id(info), "%.1f C", id(innentemperatur).state);
it.print(70, 160, id(info), "Luftfeuchte");
it.printf(175, 160, id(info), "%.1f %%", id(innenluftfeuchte).state);
it.print(70, 190, id(info), "Absolute");
it.printf(175, 190, id(info), "%.1f %%", id(absolutinnen).state);
it.image(15, 230, id(weather), id(orange));
it.print(70, 230, id(info), "Aussen");
it.printf(175, 230, id(info2), "%.1f C", id(aussentemperatur).state);
it.print(70, 260, id(info), "Luftfeuchte");
it.printf(175, 260, id(info), "%.1f %%", id(aussenfeuchte).state);
it.print(70, 290, id(info), "Absolute");
it.printf(175, 290, id(info), "%.1f %%", id(absolutaussen).state);
}
}