Remote Humidity Monitor

Humidity monitor
Small ESP32-based humidity monitor.

Goal: track bathroom humidity. React early to prevent mold. Keep it simple, autonomous, readable months later.

Two parts:

MicroPython. No blocking loops. Clear states.


Desired behavior


Hardware

Main unit

Remote sensor

Design


Wiring

Two I²C buses to avoid glitches. OLED updates frequently; RTC stays stable.

   ┌────────────────────────────┐
   │           ESP32 S3         │
   │                            │
   │       3V3 ───────────┐     │
   │       GND ───┐       │     │
   │              ▼       ▼     │
   │        ┌──────────────┐    │
   │        │   SH1106     │    │
   │        │    OLED      │    │
   │        └──────────────┘    │
   │         SDA ←──── Pin 10   │
   │         SCL ←──── Pin 11   │
   │         VCC ←──── 3V3      │
   │         GND ←──── GND      │
   │                            │
   │        ┌──────────────┐    │
   │        │  DS3231 RTC  │    │
   │        └──────────────┘    │
   │         SDA ←──── Pin 13   │
   │         SCL ←──── Pin 12   │
   │         VCC ←──── 3V3      │
   │         GND ←──── GND      │
   │                            │
   │       ┌──────────────────┐ │
   │       │     RGB LED      │ │
   │       └──────────────────┘ │
   │   R (red)   ←──── Pin 7    │
   │   G (green) ←──── Pin 5    │
   │   B (blue)  ←──── Pin 6    │
   │   GND       ←──── GND      │
   └────────────────────────────┘

Operating Model

states, not procedures.

Main variables:

Display reads state only.


Humidity Logic

Thresholds: Safe / Warning / Critical

LED:

LED depends only on humidity. No display code here.


Sensor Messages

Remote sends simple messages:

H=63%
H=71%
OK

Strict parsing.

Missing sensor updates:


Stale Sensor Handling

Condition:

now - last_sensor_update > timeout

Actions: dim LED (~5%), clear alarms, reset notifications. Silent sensor → no false warnings.


Display

OLED shows:

Rendering reads state only:

render(state)

Night Mode

Brightness drops at night (22:00–06:00). Applied to OLED and LED. Subtle illumination.


Weather Forecast

Optional, from DWD.


Timekeeping

Primary: NTP Fallback: DS3231 RTC

Workflow: boot → Wi-Fi → NTP → RTC → offline fallback


Main Loop

Non-blocking, timed ticks:

loop:
    handle_sensor_messages()
    handle_events()
    update_led()
    update_display()

every 5 min:
    fetch_forecast_if_needed()
    attempt_ntp_sync()

Lessons

  1. Separate logic from rendering
  2. Handle missing sensors gracefully
  3. Dim LED signals sensor failure
  4. Keep messages small (H=XX%)
  5. Avoid blocking operations

Repository

Source

codeberg.org/duras/feuchtemelder

License

License

All third-party components under MIT: