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>
This commit is contained in:
+12
@@ -0,0 +1,12 @@
|
||||
# Arduino / build artifacts
|
||||
build/
|
||||
*.bin
|
||||
*.elf
|
||||
*.hex
|
||||
.vscode/
|
||||
# OS
|
||||
Thumbs.db
|
||||
Desktop.ini
|
||||
.DS_Store
|
||||
# Secrets (Wi-Fi creds are set via WiFiManager, not committed)
|
||||
secrets.h
|
||||
@@ -0,0 +1,168 @@
|
||||
# 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 → ~24–48 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).
|
||||
Reference in New Issue
Block a user