diff --git a/README.md b/README.md index f2714e7..1c8020b 100644 --- a/README.md +++ b/README.md @@ -1,70 +1,73 @@ -# 🌦️ Rust Weather Station +# Rust Weather Station
Weather Station Demo
--- +This repository contains the firmware for a solar-powered weather station based on an ESP32. The software is implemented entirely in Rust using the `esp-hal` hardware abstraction layer and the `embassy` async ecosystem. Sensor data is collected concurrently, published over MQTT, and the device returns to deep sleep to preserve the battery between sampling windows. -## πŸ“Œ About +## Hardware overview -This project is a weather station built with **Rust** and embedded hardware. It collects environmental data like **temperature**, **humidity**, **pressure**, **wind speed**, **wind direction**, and **rainfall**, and sends that data to an **MQTT** server for use in systems like **Home Assistant**. +The firmware targets the following hardware stack: ---- +- ESP32 module serving as the main controller. +- AS5600 magnetic rotary sensor that tracks wind direction. +- DHT22 digital temperature and humidity sensor connected on a single data line. +- Anemometer and tipping-bucket rain gauge driven by hall-effect sensors. +- INA219 current and voltage monitor for battery telemetry. +- 18650 Li-ion battery with a CN3791-based charge controller and a 12 V solar panel. -## πŸ”§ Hardware Components +The enclosure, mast adapters, and sensor mounts are designed for 3D printing. STL files are available on Printables: [YAWS (Yet Another Weather Station)](https://www.printables.com/model/729382-yaws-yet-another-weather-station/files). -- **ESP32** – The main microcontroller running the code. -- **AS5600** – Magnetic rotary sensor for wind direction. -- **BME680** – Sensor for temperature, humidity, pressure, and gas. -- **Hall Effect Sensors** – Used in the anemometer and rain gauge. -- **18650 Li-ion Battery** – Power supply. -- **12V Solar Panel** – Charges the battery during the day. -- **CN3791 Solar Charger** – Manages charging and battery protection. +## Software architecture ---- +### Async task layout -## 🌟 Features +The application runs under `esp-rtos` with the `embassy` executor: -- Publishes sensor data to an **MQTT** broker. -- Handles interrupts from wind and rain sensors using GPIO. -- Uses **deep sleep** to save power when idle. -- Supports multiple sensors over a shared I2C bus using Rust's embedded-hal tools. +- `wifi_task` brings up the Wi-Fi station interface and keeps the radio connected. +- `mqtt_task` drains a multi-producer queue and publishes each payload to the configured MQTT broker using the `rust-mqtt` client. +- `dht_task`, `anemo_task`, `as5600_task`, and `ina210_task` (INA219) sample their respective sensors and push structured readings onto the shared MQTT channel. +- Interrupt-driven peripherals (the anemometer and rain gauge) use debounce logic to ensure clean counts, while the AS5600 task averages multiple I2C readings to derive wind direction and cardinal labels. ---- +Shared resources, such as the I2C bus, are coordinated through `embassy-embedded-hal` mutexes so multiple async tasks can safely communicate with their devices. -## πŸ› οΈ Implementation Details +### Power management and scheduling -### πŸ”Œ Sensor Integration +The main task supervises all worker tasks for a configurable active window, feeds the watchdog, and then disconnects nonessential peripherals before putting the ESP32 into deep sleep. Wakeups occur either on the deep-sleep timer or on the external interrupt used for the rain gauge, which allows single tips to be published immediately. -- **AS5600 (Wind Direction)**: Measures the position of a magnet to get the wind direction using I2C. -- **BME680 (Environmental Data)**: Reads temperature, humidity, pressure, and gas. Also I2C. -- Since Rust doesn't allow multiple mutable references, the [`embedded-hal-bus`](https://docs.rs/embedded-hal-bus/latest/embedded_hal_bus/) crate is used to safely share the I2C bus between devices. +## Configuration -### ⚑ Interrupts +Compile-time configuration values (Wi-Fi credentials, MQTT broker details, task durations, and channel sizes) are defined in `src/config.rs` through the `toml-cfg` macro. Provide a `cfg.toml` file in the project root with entries such as: -- **Anemometer & Rain Gauge**: Use magnets and hall sensors to trigger interrupts. -- When triggered, an interrupt sets a flag (`rotation_flag` or `rain_flag`), which is checked and handled later in the main loop. -- Interrupts must be manually re-enabled after they fire, due to how the API works. +```toml +[default] +ssid = "your-ssid" +wifi_pass = "your-password" +broker_ip = "192.168.1.10" +broker_port = 1883 +mqtt_user = "station" +mqtt_pass = "secret" +topic = "weather_station" +``` -### πŸ“€ MQTT +Adjust `deep_sleep_dur_secs`, `main_task_dur_secs`, and `task_dur_secs` to control how long the station stays awake, how often readings are taken, and how frequently MQTT packets are sent. -- Data is published via functions like `publish_wifi_data()`, `publish_bme_data()`, etc. -- A separate thread manages the MQTT connection to keep it stable. -- Data is sent at regular intervals, and the ESP32 sleeps between cycles to save battery. +## Building and flashing -### πŸ’€ Deep Sleep Mode +1. Install the ESP32 Rust toolchain specified in `rust-toolchain.toml` and ensure you have `cargo-espflash` available. +2. Connect the ESP32 over USB and place it into bootloader mode (usually by holding BOOT while pressing EN). +3. Build and flash the firmware: -- **Active (~1min)**: ESP32 wakes up, handles interrupts, checks if it’s time to send data. -- **Sleep (~20min)**: ESP32 goes into deep sleep to reduce power usage. - ---- + ```bash + cargo espflash flash --release /dev/ttyUSB0 + ``` -## 🧱 Resources + Replace the serial port path with the one that matches your workstation. -You can download the 3D printable parts (STL files) here: -πŸ‘‰ [Printables - YAWS (Yet Another Weather Station)](https://www.printables.com/model/729382-yaws-yet-another-weather-station/files) +After flashing, the station will connect to the configured Wi-Fi network, stream sensor values to the MQTT broker, and fall back to deep sleep between sampling intervals. -### πŸ”„ Thread-to-thread queue example +## Thread-to-thread queue example -Check `examples/dht_mqtt_queue.rs` for a minimal snippet that shows how a DHT sampling task can push readings into a FreeRTOS queue that a dedicated MQTT publisher drains using `esp-idf-svc` primitives. +For a smaller example demonstrating the same queueing pattern between tasks, see `examples/dht_mqtt_queue.rs`. It shows how a sensor sampling task can push readings into a FreeRTOS queue that an MQTT publisher drains using `esp-idf-svc` primitives.