update: improve documentation and restructure code for modular hardware integration, add CAN communication to HAL, and update KiCad layouts
This commit is contained in:
@@ -5,24 +5,47 @@ draft: false
|
||||
description: "a description"
|
||||
tags: ["firmeware", "upload"]
|
||||
---
|
||||
# Prebuild
|
||||
1. Download image from
|
||||
2. todo something espflash tool here
|
||||
|
||||
# From source
|
||||
# From Source
|
||||
## Preconditions
|
||||
* rustup with current version
|
||||
* espup with current version
|
||||
* npm /npx
|
||||
* Connect the board via usb to the computer
|
||||
* Ensure the esp is running (eg not in deepsleep if prior version was installed)
|
||||
# Compiling and uploading
|
||||
1. Clone the gitea
|
||||
2. go to the rust/src_webroot
|
||||
3. npm -i
|
||||
4. cd ..
|
||||
5. cargo run
|
||||
* **Rust:** Current version of `rustup`.
|
||||
* **ESP32 Toolchain:** `espup` installed and configured.
|
||||
* **espflash:** Installed via `cargo install espflash`.
|
||||
* **Node.js:** `npm` installed (for the web interface).
|
||||
|
||||
Depending on the setup of the cargo runner, either a OTA image is build or the firmware is directly flashed to the esp.
|
||||
## Flashing via USB
|
||||
1. Connect the MainBoard to your computer via USB.
|
||||
2. Ensure the board is powered and not in deep sleep.
|
||||
3. Build the web interface (only required once or if you changed something in `src_webpack`):
|
||||
```bash
|
||||
cd Software/MainBoard/rust/src_webpack
|
||||
npm install
|
||||
npx webpack
|
||||
cd ..
|
||||
```
|
||||
4. Flash the firmware:
|
||||
```bash
|
||||
espflash flash --monitor --partition-table partitions.csv
|
||||
```
|
||||
*Note: If the flashing fails, you might need to put the ESP32-C6 into bootloader mode by holding the BOOT button while resetting or connecting USB.*
|
||||
|
||||
Note: If the bootloader is currently booting from ota_2, flashing ota_1 via usb will not make it switch. You might need to manually erase it in this case prior.
|
||||
### Simplified Flashing with Scripts
|
||||
You can use the provided bash scripts to automate the build and flash process:
|
||||
* **`./flash.sh`**: Cleans temporary files, builds the web interface, compiles the firmware, and flashes it to the board.
|
||||
* **`./all.sh`**: Similar to `flash.sh`, but also saves a local `image.bin` of the firmware.
|
||||
|
||||
## OTA (Over-the-Air) Update
|
||||
You can also update the firmware wirelessly if the system is already running and connected to your network.
|
||||
|
||||
1. Generate the OTA binary:
|
||||
```bash
|
||||
cargo build --release
|
||||
```
|
||||
2. The binary will be at `target/riscv32imac-unknown-none-elf/release/plant-ctrl2`.
|
||||
3. Open the PlantCtrl web interface in your browser.
|
||||
4. Navigate to the **OTA** section.
|
||||
5. Upload the `plant-ctrl2` file.
|
||||
6. The system will reboot into the new firmware once the upload and verification are complete.
|
||||
|
||||
## Troubleshooting
|
||||
* **Bootloader Partition:** If the bootloader is currently booting from `ota_2`, flashing to the factory partition via USB might not automatically switch the active partition. You can use `espflash erase-parts otadata` to reset the OTA state.
|
||||
* **Serial Terminal:** Use `espflash monitor` to view the serial logs for debugging.
|
||||
|
||||
@@ -16,11 +16,11 @@ Connect to the AccessPoint and browse to http://192.168.71.1 to set it up
|
||||
3. The ESP will now try to connect to a WIFI station if configured and start the webserver, if the connection to the station cannot be made, it will open an AccessPoint instead.
|
||||
|
||||
# MQTT
|
||||
It is possible to use the topic /stay/alive to enter the config mode.
|
||||
It is possible to use the MQTT topic `{base_topic}/stay_alive` to enter the config mode remotely.
|
||||
|
||||
If this topic contains a retained message with the value true, the ESP will enter ConfigMode during it's next cycle and stay there.
|
||||
If this topic contains a retained message with the value `true` or `1`, the ESP will enter ConfigMode during its next cycle and stay there.
|
||||
|
||||
Note: You must set /stay/alive to retained false again after this, otherwise it will always enter configmode, even if you exist it via the webui.
|
||||
Note: You must set `{base_topic}/stay_alive` to `false` or `0` (or clear the retained message) after this, otherwise it will always enter configmode, even if you exit it via the webui.
|
||||
|
||||
# USB reboot
|
||||
By connecting to the USB Terminal via a Serial Monitor, the ESP is reset and will enter configmode as if the button for normal operation was pressed
|
||||
|
||||
@@ -6,22 +6,84 @@ description: "a description"
|
||||
tags: ["mqtt", "esp"]
|
||||
---
|
||||
# MQTT
|
||||
An Mqtt server can be configured and will be used to dump all kinds of statistical data.
|
||||
A configured MQTT server will receive statistical and status data from the controller.
|
||||
|
||||
|Topic|Example|Description|
|
||||
|/firmware/address|
|
||||
### Topics
|
||||
|
||||
| Topic | Example | Description |
|
||||
|----------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------|
|
||||
| firmware/address | 192.168.1.2 | The Ip address in station mode |
|
||||
| firmware/githash | feature/esp32c6@1ce4d74a | The branch and hash during build time |
|
||||
| firmware/buildtime | 2025-01-21T20:56:18.168163570Z | Compile time |
|
||||
| firmware/last_online | 2025-01-22T08:56:46.664+01:00 | Last time this board was online |
|
||||
| firmware/ota_state | Partition state is ESP_OTA_IMG_VALID | The OTA state, relevant for rollback |
|
||||
| firmware/partition_address | 0x10000 | The OTA partition used, 0x10000 is ota_1 |
|
||||
| state | online | Current State, expected are online or sleep |
|
||||
| battery | {<br/>"voltage_milli_volt":"12860",<br/>"current_milli_ampere":"-16",<br/>"cycle_count":"12",<br/>"design_milli_ampere":"6000",<br/>"remaining_milli_ampere":"806",<br/>"state_of_charge":"15",<br/>"state_of_health":"93",<br/>"temperature":"2957"<br/>} | Dump of battery data |
|
||||
| water | {<br/>"enough_water":true,<br/>"warn_level":false,<br/>"left_ml":1337,<br/>"sensor_error":false,<br/>"raw":0,"water_frozen":<br/>"tank sensor error"<br/>} | Water Status dump |
|
||||
| plant1 | {<br/>"a":"disabled",<br/>"a_raw":"0",<br/>"b":"disabled",<br/>"b_raw":"0",<br/>"mode":"OFF",<br/>"consecutive_pump_count":0,<br/>"dry":false,<br/>"active":false,<br/>"pump_error":false,<br/>"not_effective":false,<br/>"cooldown":false,<br/>"out_of_work_hour":false,<br/>"last_pump":"N/A",<br/>"next_pump":"N/A"<br/>} | Plant status dump |
|
||||
| light | {<br/>"active":false,<br/>"out_of_work_hour":true,<br/>"battery_low":true,<br/>"is_day":false<br/>} | Light status dump |
|
||||
| deepsleep | night 1h | Why and how long the ESP will sleep |
|
||||
| Topic | Example | Description |
|
||||
|-------|---------|-------------|
|
||||
| `firmware/address` | `192.168.1.2` | IP address in station mode |
|
||||
| `firmware/state` | `VersionInfo { ... }` | Debug information about the current firmware and OTA slots |
|
||||
| `firmware/last_online` | `2025-01-22T08:56:46.664+01:00` | Last time the board was online |
|
||||
| `state` | `online` | Current state of the controller |
|
||||
| `mppt` | `{"current_ma":1200,"voltage_ma":18500}` | MPPT charging metrics |
|
||||
| `battery` | `{"Info":{"voltage_milli_volt":12860,"average_current_milli_ampere":-16,...}}` | Battery health and charge data |
|
||||
| `water` | `{"enough_water":true,"warn_level":false,"left_ml":1337,...}` | Water tank status |
|
||||
| `plant{1-8}` | `{"sensor_a":...,"sensor_b":...,"mode":"TargetMoisture",...}` | Detailed status for each plant slot |
|
||||
| `pump{1-8}` | `{"enabled":true,"pump_ineffective":false,...}` | Metrics for the last pump activity |
|
||||
| `light` | `{"enabled":true,"active":true,...}` | Night light status |
|
||||
| `deepsleep` | `night 1h` | Why and how long the ESP will sleep |
|
||||
|
||||
### Data Structures
|
||||
|
||||
#### Firmware State (`firmware/state`)
|
||||
Contains a debug dump of the `VersionInfo` struct:
|
||||
- `git_hash`: Branch and commit hash
|
||||
- `build_time`: Compilation timestamp
|
||||
- `current`: Current running partition
|
||||
- `slot0_state`: State of OTA slot 0
|
||||
- `slot1_state`: State of OTA slot 1
|
||||
|
||||
#### MPPT (`mppt`)
|
||||
- `current_ma`: Solar charging current in mA
|
||||
- `voltage_ma`: Solar panel voltage in mV
|
||||
|
||||
#### Battery (`battery`)
|
||||
Can be `"Unknown"` or an `Info` object:
|
||||
- `voltage_milli_volt`: Battery voltage
|
||||
- `average_current_milli_ampere`: Current draw/charge
|
||||
- `design_milli_ampere_hour`: Battery capacity
|
||||
- `remaining_milli_ampere_hour`: Remaining capacity
|
||||
- `state_of_charge`: Charge percentage (0-100)
|
||||
- `state_of_health`: Health percentage (0-100)
|
||||
- `temperature`: Temperature in degrees Celsius
|
||||
|
||||
#### Water (`water`)
|
||||
- `enough_water`: Boolean, true if level is above empty threshold
|
||||
- `warn_level`: Boolean, true if level is below warning threshold
|
||||
- `left_ml`: Estimated remaining water in ml
|
||||
- `percent`: Estimated fill level in percent
|
||||
- `raw`: Raw sensor voltage in mV
|
||||
- `sensor_error`: Details if the level sensor fails
|
||||
- `water_frozen`: Boolean, true if temperature is below freezing
|
||||
- `water_temp`: Water temperature in degrees Celsius
|
||||
- `temp_sensor_error`: Details if the temperature sensor fails
|
||||
|
||||
#### Plant (`plant{1-8}`)
|
||||
- `sensor_a` / `sensor_b`: Moisture sensor status
|
||||
- `Disabled`
|
||||
- `{"MoistureValue":{"raw_hz":5000,"moisture_percent":65}}`
|
||||
- `{"SensorError":{"ShortCircuit":{"hz":...,"max":...}}}`
|
||||
- `mode`: Watering mode (`Off`, `TargetMoisture`, `MinMoisture`, `TimerOnly`)
|
||||
- `do_water`: Boolean, true if watering is currently required
|
||||
- `dry`: Boolean, true if moisture is below target
|
||||
- `cooldown`: Boolean, true if the pump is in cooldown period
|
||||
- `out_of_work_hour`: Boolean, true if currently outside allowed watering hours
|
||||
- `consecutive_pump_count`: Number of pump cycles without reaching target
|
||||
- `pump_error`: Details if the pump is failing
|
||||
- `last_pump`: Timestamp of last activity
|
||||
- `next_pump`: Estimated timestamp for next allowed activity
|
||||
|
||||
#### Pump (`pump{1-8}`)
|
||||
- `enabled`: Boolean, pump was active
|
||||
- `pump_ineffective`: Boolean, no flow detected during pumping
|
||||
- `median_current_ma`: Median pump current
|
||||
- `max_current_ma`: Peak pump current
|
||||
- `min_current_ma`: Minimum pump current
|
||||
|
||||
#### Light (`light`)
|
||||
- `enabled`: Boolean, is enabled in config
|
||||
- `active`: Boolean, led is currently on
|
||||
- `out_of_work_hour`: Boolean, led should not be on at this time of day
|
||||
- `battery_low`: Boolean, battery is low so led usage is restricted
|
||||
- `is_day`: Boolean, the sun is up (determined by solar panel voltage)
|
||||
@@ -5,37 +5,57 @@ draft: false
|
||||
description: "How to compile the project"
|
||||
tags: ["clone", "compile"]
|
||||
---
|
||||
# Preconditons:
|
||||
* NPM is installed
|
||||
* rustup is installed
|
||||
* espup is installed
|
||||
# Preconditions:
|
||||
* **Rust:** `rustup` installed.
|
||||
* **ESP32 Toolchain:** `espup` installed.
|
||||
* **Build Utilities:** `ldproxy` and `espflash` installed.
|
||||
* **Node.js:** `npm` installed (for the web interface).
|
||||
|
||||
# Cloning the Repository
|
||||
Clone the repository including submodules:
|
||||
```bash
|
||||
git clone --recursive https://git.mannheim.ccc.de/C3MA/PlantCtrl.git
|
||||
cd PlantCtrl/Software/MainBoard/rust
|
||||
```
|
||||
|
||||
# Cloning Git
|
||||
Clone the git via the tool of your choice to your local computer
|
||||
```
|
||||
git clone https://git.mannheim.ccc.de/C3MA/PlantCtrl.git
|
||||
```
|
||||
switch to the newly cloned folder
|
||||
```
|
||||
cd PlantCtrl/rust
|
||||
```
|
||||
# Install rust
|
||||
rustup description
|
||||
install ldproxy
|
||||
```
|
||||
cargo install ldproxy
|
||||
```
|
||||
# Esp Toolchain
|
||||
espup description
|
||||
# Webpack install
|
||||
The buildin config website is currently build inline via npm - typescript - webpack and then directly embedded into the binary, so it is required to have webpack build working.
|
||||
```
|
||||
# Toolchain Setup
|
||||
1. **Install Rust:** If not already done, visit [rustup.rs](https://rustup.rs/).
|
||||
2. **Install ldproxy:**
|
||||
```bash
|
||||
cargo install ldproxy
|
||||
```
|
||||
3. **Install espup:**
|
||||
```bash
|
||||
cargo install espup
|
||||
```
|
||||
4. **Install ESP toolchain:**
|
||||
```bash
|
||||
espup install
|
||||
```
|
||||
5. **Install espflash:**
|
||||
```bash
|
||||
cargo install espflash
|
||||
```
|
||||
|
||||
# Building the Web Interface
|
||||
The configuration website is built using TypeScript and Webpack, then embedded into the Rust binary.
|
||||
```bash
|
||||
cd src_webpack/
|
||||
npm install
|
||||
```
|
||||
Check the webpack build is working
|
||||
```
|
||||
npx webpack
|
||||
cd ..
|
||||
```
|
||||
# Cargo Build
|
||||
|
||||
# Compiling the Firmware
|
||||
Build the project using Cargo:
|
||||
```bash
|
||||
cargo build --release
|
||||
```
|
||||
The resulting binary will be located in `target/riscv32imac-unknown-none-elf/release/plant-ctrl2`.
|
||||
|
||||
# Using Build Scripts
|
||||
To simplify the process, several bash scripts are provided in the `Software/MainBoard/rust` directory:
|
||||
|
||||
* **`image_build.sh`**: Automatically builds the web interface, compiles the Rust firmware in release mode, and creates a flashable `image.bin`.
|
||||
* **`all.sh`**: Performs all steps from `image_build.sh` and additionally flashes the firmware to a connected device and starts the serial monitor.
|
||||
* **`wokwi_build.sh`**: Builds a debug version of the firmware and creates a full 16MB flash image for use with the [Wokwi simulator](https://wokwi.com).
|
||||
|
||||
@@ -2,13 +2,50 @@
|
||||
title: "Software"
|
||||
date: 2025-01-24
|
||||
draft: false
|
||||
description: "Information about the Firmware"
|
||||
tags: ["software"]
|
||||
description: "Information about the PlantCtrl Firmware"
|
||||
tags: ["software", "rust", "esp32-c6", "firmware"]
|
||||
---
|
||||
* esp-idf-hal based rust project
|
||||
* can be run standalon or with wifi
|
||||
* MQTT
|
||||
* SNTP to sync the RTC/Clock
|
||||
* Abitrary file upload and download into SPIFS volume
|
||||
* Flash Battery Controller from file in Flash
|
||||
* Flash Firmware via OTA directly from website
|
||||
|
||||
The PlantCtrl firmware is a modern, reliable, and efficient system designed specifically for the ESP32-C6 RISC-V microcontroller. It is written entirely in **Rust**, leveraging the power of asynchronous programming to ensure low power consumption and high responsiveness.
|
||||
|
||||
## Core Technology Stack
|
||||
|
||||
* **Language:** [Rust](https://www.rust-lang.org/) (no_std)
|
||||
* **Async Runtime:** [Embassy](https://embassy.dev/)
|
||||
* **Hardware Abstraction:** `esp-hal` for ESP32-C6
|
||||
* **Filesystem:** [LittleFS2](https://github.com/littlefs-project/littlefs) for robust persistent storage
|
||||
* **Web Framework:** `edge-http` for the integrated web server
|
||||
|
||||
## Key Features
|
||||
|
||||
### Intelligent Watering
|
||||
The software manages up to 8 independent watering zones.
|
||||
* **Moisture-Based Control:** Automatically triggers pumps when soil moisture drops below a configurable threshold.
|
||||
* **Safety Limits:** Includes pump time limits, volume limits (requires flow sensor), and mandatory cooldown periods.
|
||||
* **Scheduling:** Define specific hours during which watering is allowed to occur.
|
||||
* **Pump Protection:** Monitors pump current to detect dry running or blockages (using INA219).
|
||||
|
||||
### Modular Sensor Integration
|
||||
The firmware communicates with the new **CAN bus-based sensor modules**.
|
||||
* **Digital Accuracy:** Receives precise moisture data over the robust CAN bus protocol.
|
||||
* **Multi-Sensor Support:** Supports A and B sensor pairs for each plant to provide better averaging in large containers.
|
||||
|
||||
### Networking & IoT
|
||||
* **WiFi:** Supports both Station mode (connecting to your home network) and Access Point mode (for initial setup).
|
||||
* **MQTT & Home Assistant:** Full integration with Home Assistant via the `mcutie` crate. Reports battery status, moisture levels, tank levels, and allows remote configuration.
|
||||
* **Time Sync:** Uses **SNTP** to keep the internal Real-Time Clock (RTC) accurate.
|
||||
* **OTA Updates:** Firmware can be updated wirelessly via the web interface.
|
||||
|
||||
### Power Management
|
||||
* **Solar Optimized:** Works in tandem with the MPPT module to maximize solar charging.
|
||||
* **Battery Aware:** Monitors battery State of Charge (SoC). It can automatically disable non-essential features (like the nightlight) or enter a deep-sleep "rescue mode" if the battery is critically low.
|
||||
* **Low Power:** Uses ESP32-C6 power-saving features to ensure long autonomous operation.
|
||||
|
||||
### Integrated Web Interface
|
||||
The firmware hosts a comprehensive web dashboard built with **TypeScript** and **Webpack**.
|
||||
* **Real-time Monitoring:** View current moisture, battery health, and solar production.
|
||||
* **Easy Configuration:** Change all system settings (WiFi, MQTT, watering rules) directly from your browser.
|
||||
* **Diagnostics:** Access system logs and hardware status information.
|
||||
|
||||
## Emergency Rescue Mode
|
||||
If the system detects a missing configuration or an invalid system time, it automatically enters **Emergency Rescue Mode**. In this mode, it opens a WiFi Access Point ("PlantCtrl Init") allowing you to perform initial setup or recover the system.
|
||||
|
||||
Reference in New Issue
Block a user