--- ############################################################################### # MicroEnv v1.0 ESPHome configuration ############################################################################### # # Copyright (C) 2025 Joshua M. Boniface # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, version 3. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # ############################################################################### esphome: name: microenv name_add_mac_suffix: true friendly_name: "MicroEnv Sensor" project: name: "Joshua Boniface.microenv" version: "1.0" min_version: 2025.5.0 dashboard_import: package_import_url: github://joshuaboniface/microenv/microenv.yaml esp32: board: esp32-c3-devkitm-1 variant: esp32c3 framework: type: esp-idf preferences: flash_write_interval: 15sec globals: # Defaults to -5 due to heating from the ESP - id: temperature_offset type: float restore_value: true initial_value: "-5.0" - id: humidity_offset type: float restore_value: true initial_value: "0.0" logger: level: INFO baud_rate: 115200 api: reboot_timeout: 15min ota: platform: esphome web_server: port: 80 captive_portal: mdns: disabled: false wifi: ap: {} domain: "" output_power: 8.5dB reboot_timeout: 15min power_save_mode: none i2c: - id: i2c_bus sda: GPIO21 scl: GPIO20 scan: true sensor: - platform: sgp4x voc: name: "SGP41 VOC Index" id: sgp41_voc_index accuracy_decimals: 0 icon: mdi:molecule filters: - sliding_window_moving_average: # We take a reading every 15 seconds, but calculate the sliding window_size: 12 # average over 12 readings i.e. 60 seconds/1 minute to normalize send_every: 3 # brief spikes while still sending a value every 15 seconds. nox: name: "SGP41 NOx Index" id: sgp41_nox_index accuracy_decimals: 0 icon: mdi:molecule filters: - sliding_window_moving_average: window_size: 12 send_every: 3 compensation: temperature_source: sht45_temperature humidity_source: sht45_humidity store_baseline: true update_interval: 5s - platform: template name: "SGP41 TVOC (µg/m³)" id: sgp41_tvoc_ugm3 lambda: |- float i = id(sgp41_voc_index).state; if (i < 1) return NAN; float tvoc = (log(501.0 - i) - 6.24) * -878.53; return tvoc; unit_of_measurement: "µg/m³" accuracy_decimals: 0 - platform: template name: "SGP41 TVOC (ppb)" id: sgp41_tvoc_ppb lambda: |- float tvoc_ugm3 = id(sgp41_tvoc_ugm3).state; float tvoc_ppm = tvoc_ugm3 * 0.436; // ppb estimated using isobutylene MW (56.1 g/mol) return tvoc_ppm; unit_of_measurement: "ppb" accuracy_decimals: 0 - platform: template name: "SGP41 eCO2 (approx ppm)" id: sgp41_eco2_ppm lambda: |- float tvoc_ppb = id(sgp41_tvoc_ppb).state; float eco2_ppm = 400.0 + 1.5 * tvoc_ppb; if (eco2_ppm > 2000) eco2_ppm = 2000; return eco2_ppm; unit_of_measurement: "ppm" accuracy_decimals: 0 - platform: sht4x temperature: name: "SHT45 Temperature" id: sht45_temperature accuracy_decimals: 1 filters: - offset: !lambda return id(temperature_offset); - sliding_window_moving_average: window_size: 4 send_every: 1 humidity: name: "SHT45 Relative Humidity" id: sht45_humidity accuracy_decimals: 1 filters: - offset: !lambda return id(humidity_offset); - sliding_window_moving_average: window_size: 4 send_every: 1 heater_max_duty: 0.0 update_interval: 15s - platform: absolute_humidity name: "SHT45 Absolute Humidity" temperature: sht45_temperature humidity: sht45_humidity id: sht45_absolute_humidity - platform: template name: "SHT45 Dew Point" icon: mdi:thermometer-water id: sht45_dew_point unit_of_measurement: "°C" lambda: |- float temp = id(sht45_temperature).state; float rh = id(sht45_humidity).state; if (isnan(temp) || isnan(rh)) return NAN; float a = 17.27, b = 237.7; float alpha = ((a * temp) / (b + temp)) + log(rh / 100.0); return (b * alpha) / (a - alpha); update_interval: 15s - platform: wifi_signal name: "WiFi Signal" update_interval: 60s entity_category: diagnostic - platform: uptime name: "Uptime" update_interval: 60s entity_category: diagnostic text_sensor: - platform: version name: "ESPHome Version" entity_category: diagnostic - platform: wifi_info ip_address: name: "WiFi IP Address" ssid: name: "WiFi SSID" bssid: name: "WiFi BSSID" mac_address: name: "WiFi MAC Address" button: - platform: restart name: "ESP32 Restart" icon: mdi:power-cycle entity_category: diagnostic - platform: factory_reset name: "ESP32 Factory Reset" icon: mdi:restart-alert entity_category: diagnostic number: # Temperature offset: # A calibration from -30 to +5 for the temperature sensor - platform: template name: "Temperature Offset" id: temperature_offset_setter min_value: -30 max_value: 10 step: 0.1 lambda: |- return id(temperature_offset); set_action: then: - globals.set: id: temperature_offset value: !lambda 'return float(x);' # Humidity offset: # A calibration from -20 to +20 for the humidity sensor - platform: template name: "Humidity Offset" id: humidity_offset_setter min_value: -20 max_value: 20 step: 0.1 lambda: |- return id(humidity_offset); set_action: then: - globals.set: id: humidity_offset value: !lambda 'return float(x);'