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.

AufbauV2.jpg

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.

Lüfter.png   DisplayB.png

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:
SignalCO2PWM5000.jpg

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);          
        }
      }