chore: make repo an Arduino collection with WeatherPredictor project
Flatten so the repo root is the Arduino sketchbook; the project lives in WeatherPredictor/. Add a collection index README at the root and move the detailed project README into WeatherPredictor/. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -1,114 +1,9 @@
|
|||||||
# Weather Predictor
|
# Arduino
|
||||||
|
|
||||||
An autonomous **barometric weather station** built on a Wemos D1 mini (ESP8266).
|
A collection of Arduino / ESP microcontroller projects.
|
||||||
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
|
## Projects
|
||||||
|
|
||||||
- **Local Zambretti forecast** from the 3-hour sea-level pressure trend (rising / steady / falling), adjusted for season.
|
- **[WeatherPredictor](WeatherPredictor/)** — autonomous barometric weather
|
||||||
- **On-device TFT screen** (160×80): time, date, pressure with trend arrow, temperature, a scaled weather icon, and the station's Wi-Fi/IP.
|
station on a Wemos D1 mini (ESP8266): local Zambretti forecast, TFT display
|
||||||
- **Web interface** served from the device (no external CDNs, works offline):
|
and a self-hosted web interface. See its [README](WeatherPredictor/README.md).
|
||||||
- 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://<ip>/`.
|
|
||||||
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).
|
|
||||||
|
|||||||
@@ -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 `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://<ip>/`.
|
||||||
|
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
|
||||||
|
|
||||||
|
```
|
||||||
|
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).
|
||||||
Reference in New Issue
Block a user