From fc72f9b0bd95b257e13ff37148bec5dd0cd59c6d Mon Sep 17 00:00:00 2001 From: Vitali Date: Sat, 18 Jul 2026 11:52:33 +0700 Subject: [PATCH] docs: add project README Co-Authored-By: Claude Opus 4.8 --- README.md | 114 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 114 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..9494826 --- /dev/null +++ b/README.md @@ -0,0 +1,114 @@ +# Weather Predictor + +An autonomous **barometric weather station** built on a Wemos D1 mini (ESP8266). +It reads atmospheric pressure and temperature, keeps accurate battery-backed +time, and predicts near-term local weather entirely on-device using the +**Zambretti algorithm** — no internet forecast service required. Readings and +the forecast are shown on a small TFT and on a self-hosted web interface styled +as a barometer instrument. + +## Features + +- **Local Zambretti forecast** from the 3-hour sea-level pressure trend (rising / steady / falling), adjusted for season. +- **On-device TFT screen** (160×80): time, date, pressure with trend arrow, temperature, a scaled weather icon, and the station's Wi-Fi/IP. +- **Web interface** served from the device (no external CDNs, works offline): + - live barometer dial with a needle and a "set hand" ghost at the pressure 3 h ago; + - barograph of pressure & temperature with labelled axes; + - **forecast change log**; + - settings with **city presets** and a UTC-offset time-zone picker. +- **Persistence** in LittleFS: settings, pressure history, and the forecast log all survive reboots. +- **Wi-Fi provisioning** via WiFiManager (captive portal — no credentials in code) and **NTP** time sync to the DS3231. + +## Hardware + +| Component | Part | Bus / notes | +|-----------|------|-------------| +| MCU | Wemos D1 mini (ESP8266, 4 MB flash) | — | +| Pressure & temperature | BMP180 (GY-68) | I²C, addr `0x77` | +| Real-time clock | DS3231 (HW-022, battery-backed) | I²C, addr `0x68` | +| Display | 0.96" 80×160 TFT, ST7735S | 4-wire SPI, run landscape 160×80 | + +### Wiring + +The display uses hardware SPI; the two I²C modules share one bus. + +| Signal | Wemos pin | GPIO | +|--------|-----------|------| +| TFT CS | D8 | 15 | +| TFT DC | D3 | 0 | +| TFT RST | D4 | 2 | +| TFT SDA (MOSI) | D7 | 13 | +| TFT SCL (SCK) | D5 | 14 | +| TFT BLK (backlight) | D2 | 4 | +| I²C SDA (BMP180 + DS3231) | D6 | 12 | +| I²C SCL (BMP180 + DS3231) | D1 | 5 | + +All modules run on 3.3 V / GND. I²C is started with `Wire.begin(D6 /*SDA*/, D1 /*SCL*/)`. + +## Build & flash (Arduino IDE) + +1. Install the **ESP8266** board package; select board **"LOLIN(WEMOS) D1 R2 & mini"**. +2. Set **Tools → Flash Size** to a layout with a filesystem, e.g. **4MB (FS:2MB)**. +3. Install libraries via Library Manager: + *Adafruit GFX*, *Adafruit ST7735 and ST7789*, *Adafruit BMP085*, *RTClib*, + *ArduinoJson* (v7.x), *WiFiManager* (by tzapu). + `ESP8266WiFi`, `ESP8266WebServer`, `LittleFS`, `Wire`, `SPI`, `time` ship with the core. +4. Open `Arduino/WeatherPredictor/WeatherPredictor.ino` and upload. + +## First run + +1. On first boot the device opens a Wi-Fi access point **`WeatherPredictor-Setup`**. + Join it from a phone and pick your network in the captive portal. +2. After connecting, the device syncs time over NTP and writes it to the DS3231. +3. The screen and Serial (115200) print the station's IP — open `http:///`. +4. The forecast shows **"Collecting data…"** until ~3 h of pressure history exists; + that is expected — the Zambretti method needs a trend before its first call. + +Set your **altitude** in the web settings (or pick a city preset): sea-level +pressure — and therefore the forecast — depends on it (~0.12 hPa per metre). + +## REST API + +| Endpoint | Method | Returns | +|----------|--------|---------| +| `/` | GET | Web UI | +| `/api/current` | GET | time, pressure (abs + sea level), temperature, trend, forecast | +| `/api/history` | GET | recent pressure/temperature samples | +| `/api/forecasts` | GET | forecast change log (newest first) | +| `/api/settings` | GET / POST | altitude, time-zone offset, coordinates | + +## Project structure + +``` +Arduino/WeatherPredictor/ + WeatherPredictor.ino scheduler; wires the modules together + config.h pins, addresses, intervals, defaults + state.h shared current-readings struct + sensors.* BMP180 read + sea-level conversion + rtc_time.* DS3231 read/set + NTP sync + display_ui.* ST7735 rendering + weather icons + forecast.* Zambretti forecast + trend classification + history.* pressure ring buffer + LittleFS persistence + flog.* forecast change log + app_settings.* settings struct + LittleFS JSON + net.* WiFiManager connection + web_server.* HTTP server + REST API + web_page.h web UI (HTML/CSS/JS) in PROGMEM + docs/superpowers/ design spec and implementation plan +``` + +## Notes & gotchas + +- **BGR panel:** this 0.96" ST7735S has red/blue swapped, so colours are built + R/B-exchanged in `display_ui.cpp`. If your panel looks wrong, adjust there + (and the `invertDisplay` / `setRotation` in `displayBegin()`). +- **Restrictive networks:** on some LANs the router does not resolve external + hostnames, so NTP uses hard-coded Cloudflare/Google anycast IPs instead of + names. Such networks may also block SSH. +- **Flash wear:** history is flushed every 15 min and the forecast log only on + change, so LittleFS wear leveling keeps flash life at years/decades. + +## Credits + +Zambretti forecast constants and lookup tables adapted from +[G6EJD's ESP Zambretti forecaster](https://github.com/G6EJD/ESP32_Weather_Forecaster_TN061).