Files
Arduino/docs/superpowers/specs/2026-07-17-weather-predictor-design.md
T
oskarvitaliiandClaude Opus 4.8 ea90ef364f docs: add Weather Predictor design spec
Autonomous barometric weather station on Wemos D1 mini with BMP180,
DS3231 RTC and 0.96" ST7735 TFT. Local Zambretti forecast, web UI,
LittleFS storage, WiFiManager + NTP.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 18:28:17 +07:00

169 lines
6.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Weather Predictor — Design Spec
**Date:** 2026-07-17
**Status:** Approved (design), pending implementation plan
## Overview
An autonomous barometric weather-prediction station built on a Wemos D1 mini
(ESP8266). It measures atmospheric pressure and temperature (BMP180), keeps
accurate time (DS3231 RTC), predicts near-term weather locally using the
**Zambretti algorithm** (pressure trend based, no internet required), and
displays current readings + forecast on a small TFT. A built-in web interface
(served from the device) shows live readings, a 24 h history chart, and
editable settings.
All on-device and web text is in **English**.
## Hardware
| Component | Model |
|-----------|-------|
| MCU | Wemos D1 mini (ESP8266, ~4 MB flash) |
| Pressure/Temp sensor | BMP180 (GY-68), I2C addr 0x77 |
| RTC | DS3231 (HW-022, no EEPROM), I2C addr 0x68, battery-backed |
| Display | 0.96" 80×160 TFT, ST7735S, 4-wire SPI, driver `INITR_MINI160x80` |
### Wiring
Display uses hardware SPI; both I2C modules share one bus (D1/D6).
| Signal | Wemos pin | GPIO |
|--------|-----------|------|
| TFT CS | D8 | 15 |
| TFT DC | D3 | 0 |
| TFT RES | D4 | 2 |
| TFT SDA (MOSI) | D7 | 13 |
| TFT SCL (SCK) | D5 | 14 |
| TFT BLK (backlight) | D2 | 4 |
| I2C SCL (BMP180 + DS3231) | D1 | 5 |
| I2C SDA (BMP180 + DS3231) | D6 | 12 |
Power: all modules on 3.3 V / GND. I2C init: `Wire.begin(D6 /*SDA*/, D1 /*SCL*/)`.
## Software Architecture
Arduino IDE project: main `.ino` sketch + per-module `.h`/`.cpp` tabs.
Each module has one clear responsibility and a small interface.
| Module | Responsibility | Key library |
|--------|----------------|-------------|
| `config.h` | Pins, I2C addresses, timing constants, defaults | — |
| `sensors` | Read BMP180 pressure + temperature | Adafruit_BMP085 |
| `rtc` | Read/set DS3231 time; NTP sync when Wi-Fi up | RTClib |
| `display` | Render the status screen | Adafruit_GFX, Adafruit_ST7735 |
| `forecast` | Zambretti prediction (pure, host-testable) | — |
| `history` | Ring buffer of samples + LittleFS persistence | LittleFS |
| `settings` | Load/save settings JSON | ArduinoJson, LittleFS |
| `wifi` | Connect via WiFiManager captive portal | WiFiManager |
| `webserver` | HTTP server + REST API + static page | ESP8266WebServer |
### Third-party libraries (Arduino Library Manager)
Adafruit_GFX, Adafruit_ST7735, Adafruit_BMP085 (works for BMP180), RTClib,
ArduinoJson, WiFiManager (tzapu). Built-in: SPI, Wire, ESP8266WiFi,
ESP8266WebServer, LittleFS, time.h (NTP/SNTP).
## Forecast Logic (Zambretti)
1. BMP180 reports **absolute** pressure → convert to **mean sea-level (MSL)**
pressure using the configured altitude (barometric formula).
2. Store MSL pressure samples in the history buffer.
3. Compute the **3-hour pressure trend** → rising / steady / falling
(threshold ≈ ±1.6 hPa over 3 h).
4. Zambretti lookup from (MSL pressure, trend, season-from-month) → one of
~26 forecast codes → mapped to a short English label
(e.g. `Sunny`, `Fine`, `Changeable`, `Rain likely`, `Stormy`) + an icon +
trend arrow (↑ / → / ↓).
5. Until ~3 h of data exist after boot, show `Collecting data…`.
Southern-hemisphere handling is not needed (fixed northern location); season
derived from RTC month.
## Display Layout (80×160, portrait)
Top→bottom: large time `HH:MM`; date; MSL pressure (hPa) with trend arrow;
temperature (°C); forecast label + icon. Backlight on D2 (dimming/night mode
is a possible later enhancement, not in initial scope).
## Data Flow
```
BMP180 ──▶ sensors ──▶ MSL convert ──▶ history (RAM ring buffer)
DS3231 ──▶ rtc │
forecast (Zambretti) ──┬──▶ display
└──▶ webserver /api
history ──(every ~15 min)──▶ LittleFS (restored on boot)
settings ◀──▶ LittleFS (edited via web)
```
- Sensor sampling: every ~1 min (display/current values).
- History granularity: one stored sample every ~5 min → ~2448 h in RAM.
- Flash flush: every ~15 min (and buffer capped) to limit flash wear.
## Web Interface
Single page served from the device; **no external CDNs** (works even if the
client has no internet). Vanilla JS + a small self-written inline **SVG chart**.
Pages/sections:
1. **Live** — current time, MSL pressure + trend, temperature, forecast.
2. **History** — 24 h pressure + temperature chart.
3. **Settings** — altitude (m, default 150), timezone/UTC offset, default
coordinates (54.9870, 82.8730) shown; editable and persisted to LittleFS.
REST API:
- `GET /api/current` → time, pressure (abs + MSL), temperature, trend, forecast.
- `GET /api/history` → array of recent samples for the chart.
- `GET /api/settings` / `POST /api/settings` → read/update settings.
## Storage (LittleFS)
- `/settings.json` — altitude, timezone offset, coordinates.
- `/history.dat` (or `.json`) — periodic snapshot of the sample ring buffer,
reloaded on boot so the trend survives restarts.
## Wi-Fi & Time
- **WiFiManager**: on first boot (or no known network) the device opens a
captive-portal AP so Wi-Fi is configured from a phone — no reflashing.
- **NTP**: when Wi-Fi is connected, sync time and write it to the DS3231.
DS3231 (battery-backed) keeps accurate time when offline.
- Default location for timezone context: 54.9870 N, 82.8730 E (Novosibirsk,
UTC+7), altitude 150 m — all editable via web.
## Defaults Summary
| Setting | Default | Editable in web |
|---------|---------|-----------------|
| Altitude | 150 m | yes |
| Coordinates | 54.9870, 82.8730 | yes |
| Timezone | UTC+7 | yes |
| Sensor sample interval | ~60 s | no (constant) |
| History sample interval | ~5 min | no (constant) |
| Flash flush interval | ~15 min | no (constant) |
## Testing
Manual (Arduino IDE, no automated harness):
1. **Sensors** — Serial print of BMP180 pressure/temp; sanity-check values.
2. **RTC** — set time, power-cycle, verify time held by battery; verify NTP
sync updates DS3231.
3. **MSL conversion** — verify computed sea-level pressure is plausible for
150 m (abs ≈ MSL ~18 hPa).
4. **Trend/forecast** — inject synthetic pressure series via Serial or by
editing the buffer; confirm rising/steady/falling classification and
Zambretti label mapping against known reference values.
5. **Display** — verify layout, no overflow, correct icons/arrows.
6. **Web** — load page over LAN, confirm live values, chart renders, settings
save and persist across reboot.
7. **Persistence** — reboot; confirm settings and history restored from flash.
## Out of Scope (initial)
- Online forecast providers (variant B/C hybrid).
- Cyrillic display fonts (English only).
- Backlight night dimming, CSV/JSON export (possible later enhancements).