From ab74dc5fbe48732996ed236fe7c87ae57d2cbff4 Mon Sep 17 00:00:00 2001 From: Serge NOEL Date: Wed, 11 Mar 2026 11:50:45 +0100 Subject: [PATCH] Ajout Thermostat --- ESP8266-Station | 1 + Thermostat/README.md | 63 +++++++++++ Thermostat/data/index.html | 32 ++++++ Thermostat/include/mqtt_handler.h | 10 ++ Thermostat/include/preset.h | 8 ++ Thermostat/include/thermostat.h | 21 ++++ Thermostat/include/web_config.h | 19 ++++ Thermostat/platformio.ini | 13 +++ Thermostat/src/main.cpp | 36 ++++++ Thermostat/src/mqtt_handler.cpp | 33 ++++++ Thermostat/src/preset.cpp | 18 +++ Thermostat/src/thermostat.cpp | 35 ++++++ Thermostat/src/web_config.cpp | 29 +++++ wind.md | 178 ++++++++++++++++++++++++++++++ 14 files changed, 496 insertions(+) create mode 160000 ESP8266-Station create mode 100644 Thermostat/README.md create mode 100644 Thermostat/data/index.html create mode 100644 Thermostat/include/mqtt_handler.h create mode 100644 Thermostat/include/preset.h create mode 100644 Thermostat/include/thermostat.h create mode 100644 Thermostat/include/web_config.h create mode 100644 Thermostat/platformio.ini create mode 100644 Thermostat/src/main.cpp create mode 100644 Thermostat/src/mqtt_handler.cpp create mode 100644 Thermostat/src/preset.cpp create mode 100644 Thermostat/src/thermostat.cpp create mode 100644 Thermostat/src/web_config.cpp create mode 100644 wind.md diff --git a/ESP8266-Station b/ESP8266-Station new file mode 160000 index 0000000..0837080 --- /dev/null +++ b/ESP8266-Station @@ -0,0 +1 @@ +Subproject commit 08370809e10db7bf590825e5b013a3a31351b9b4 diff --git a/Thermostat/README.md b/Thermostat/README.md new file mode 100644 index 0000000..e035e09 --- /dev/null +++ b/Thermostat/README.md @@ -0,0 +1,63 @@ +# Thermostat Project for Sonoff Basic R2 + +This project implements a WiFi thermostat using a Sonoff Basic R2, designed for integration with Home Assistant via MQTT. It supports preset modes (confort, eco, off, boost), receives room temperature from an MQTT gateway, and provides a fallback WiFi configuration portal for setup. + +## Features +- MQTT-based Home Assistant integration as a thermostat device (with preset modes) +- Receives room temperature from an external MQTT sensor (e.g., Xiaomi) +- Fallback WiFi configuration page for setting WiFi, MQTT server, preset temperatures, and device ID +- Configurable preset temperatures (confort, eco, boost, hors gel) +- Clean code structure for maintainability + +## Project Structure +- `src/` : Main application logic +- `include/` : Header files +- `data/` : Static files for web configuration portal +- `platformio.ini` : PlatformIO project configuration +- `README.md` : This documentation + +## Getting Started + +### 1. Prerequisites +- PlatformIO extension for VS Code +- Sonoff Basic R2 device +- MQTT broker (e.g., Mosquitto) +- Home Assistant instance + +### 2. Build & Upload +1. Clone this repository or copy the folder to your PlatformIO workspace. +2. Edit `platformio.ini` if needed (WiFi/MQTT credentials can be set via the web portal after first boot). +3. Build and upload the firmware to your Sonoff Basic R2. + +### 3. First Boot & Configuration +- On first boot (or if WiFi/MQTT fails), the device starts a WiFi AP for configuration. +- Connect to the AP and open the captive portal to set: + - WiFi SSID/password + - MQTT server/port/credentials + - Preset temperatures (confort, eco, boost, hors gel) + - Device ID for temperature sensor + +### 4. Home Assistant Integration +- The device publishes/receives via MQTT using the Home Assistant climate platform. +- Preset modes (confort, eco, off, boost) are supported and can be set from Home Assistant. +- The device subscribes to a temperature topic (e.g., from a Xiaomi sensor via Zigbee2MQTT). + +### 5. File Overview +- `src/main.cpp` : Main application entry point +- `src/thermostat.cpp` / `include/thermostat.h` : Thermostat logic +- `src/mqtt_handler.cpp` / `include/mqtt_handler.h` : MQTT communication +- `src/web_config.cpp` / `include/web_config.h` : WiFi/MQTT/web config portal +- `src/preset.cpp` / `include/preset.h` : Preset management +- `data/` : HTML/CSS/JS for configuration portal + +## Example MQTT Topics +- Temperature: `home/room/temperature/` +- State: `home/thermostat//state` +- Command: `home/thermostat//set` + +## Advanced +- Fallback to AP mode if WiFi or MQTT fails +- All configuration is stored in flash and can be reset via the web portal + +## License +MIT diff --git a/Thermostat/data/index.html b/Thermostat/data/index.html new file mode 100644 index 0000000..1ba7da2 --- /dev/null +++ b/Thermostat/data/index.html @@ -0,0 +1,32 @@ + + + + + Thermostat Config + + + + +

Thermostat WiFi & MQTT Config

+
+ + + + + + + + + + + + + +
+ + diff --git a/Thermostat/include/mqtt_handler.h b/Thermostat/include/mqtt_handler.h new file mode 100644 index 0000000..770a336 --- /dev/null +++ b/Thermostat/include/mqtt_handler.h @@ -0,0 +1,10 @@ +#pragma once +#include +#include + +void setup_mqtt(PubSubClient& client); +void mqtt_loop(PubSubClient& client); +void mqtt_publish_state(PubSubClient& client, ThermostatMode mode, float targetTemp, bool heating); +void mqtt_callback(char* topic, byte* payload, unsigned int length); +extern String mqtt_device_id; +extern String mqtt_temp_topic; diff --git a/Thermostat/include/preset.h b/Thermostat/include/preset.h new file mode 100644 index 0000000..6553dc1 --- /dev/null +++ b/Thermostat/include/preset.h @@ -0,0 +1,8 @@ +#pragma once +#include +#include "thermostat.h" + +void load_presets(); +void save_presets(); +float get_preset_temp(ThermostatMode mode); +void set_preset_temp(ThermostatMode mode, float temp); diff --git a/Thermostat/include/thermostat.h b/Thermostat/include/thermostat.h new file mode 100644 index 0000000..921fa3e --- /dev/null +++ b/Thermostat/include/thermostat.h @@ -0,0 +1,21 @@ +#pragma once +#include + +enum ThermostatMode { MODE_OFF, MODE_CONFORT, MODE_ECO, MODE_BOOST, MODE_HORS_GEL }; + +class Thermostat { +public: + Thermostat(); + void setMode(ThermostatMode mode); + void setTemperature(float temp); + void setPresetTemp(ThermostatMode mode, float temp); + void update(float currentTemp); + bool isHeating() const; + ThermostatMode getMode() const; + float getTargetTemp() const; +private: + ThermostatMode mode; + float presetTemps[5]; + float targetTemp; + bool heating; +}; diff --git a/Thermostat/include/web_config.h b/Thermostat/include/web_config.h new file mode 100644 index 0000000..61ce069 --- /dev/null +++ b/Thermostat/include/web_config.h @@ -0,0 +1,19 @@ +#pragma once +#include + +void setup_web_config(); +void handle_web_config(); +bool should_save_config(); +void save_config(); +void load_config(); +extern String wifi_ssid; +extern String wifi_pass; +extern String mqtt_server; +extern int mqtt_port; +extern String mqtt_user; +extern String mqtt_pass; +extern float preset_confort; +extern float preset_eco; +extern float preset_boost; +extern float preset_hors_gel; +extern String temp_sensor_id; diff --git a/Thermostat/platformio.ini b/Thermostat/platformio.ini new file mode 100644 index 0000000..9f6035e --- /dev/null +++ b/Thermostat/platformio.ini @@ -0,0 +1,13 @@ +[env:sonoff_basic_r2] +platform = espressif8266 +board = sonoff_basic_r2 +framework = arduino +monitor_speed = 115200 +upload_speed = 115200 +build_flags = -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY +lib_deps = + knolleary/PubSubClient + tzapu/WiFiManager + bblanchon/ArduinoJson + ESPAsyncWebServer + ESPAsyncTCP diff --git a/Thermostat/src/main.cpp b/Thermostat/src/main.cpp new file mode 100644 index 0000000..eb0e81f --- /dev/null +++ b/Thermostat/src/main.cpp @@ -0,0 +1,36 @@ +#include +#include +#include +#include "thermostat.h" +#include "mqtt_handler.h" +#include "web_config.h" +#include "preset.h" + +WiFiClient espClient; +PubSubClient mqttClient(espClient); +Thermostat thermostat; + +float currentTemp = 0.0; + +void setup() { + Serial.begin(115200); + load_config(); + setup_web_config(); + WiFi.begin(wifi_ssid.c_str(), wifi_pass.c_str()); + mqttClient.setServer(mqtt_server.c_str(), mqtt_port); + setup_mqtt(mqttClient); + load_presets(); + thermostat.setPresetTemp(MODE_CONFORT, preset_confort); + thermostat.setPresetTemp(MODE_ECO, preset_eco); + thermostat.setPresetTemp(MODE_BOOST, preset_boost); + thermostat.setPresetTemp(MODE_HORS_GEL, preset_hors_gel); + thermostat.setMode(MODE_OFF); +} + +void loop() { + handle_web_config(); + mqtt_loop(mqttClient); + thermostat.update(currentTemp); + mqtt_publish_state(mqttClient, thermostat.getMode(), thermostat.getTargetTemp(), thermostat.isHeating()); + delay(1000); +} diff --git a/Thermostat/src/mqtt_handler.cpp b/Thermostat/src/mqtt_handler.cpp new file mode 100644 index 0000000..55620c2 --- /dev/null +++ b/Thermostat/src/mqtt_handler.cpp @@ -0,0 +1,33 @@ +#include "mqtt_handler.h" +#include "thermostat.h" +#include + +String mqtt_device_id = "thermo1"; +String mqtt_temp_topic = "home/room/temperature/thermo1"; + +void setup_mqtt(PubSubClient& client) { + // Setup MQTT connection, subscribe to temp topic + client.setCallback(mqtt_callback); + client.subscribe(mqtt_temp_topic.c_str()); +} + +void mqtt_loop(PubSubClient& client) { + if (!client.connected()) { + // reconnect logic here + } + client.loop(); +} + +void mqtt_publish_state(PubSubClient& client, ThermostatMode mode, float targetTemp, bool heating) { + StaticJsonDocument<128> doc; + doc["mode"] = mode; + doc["target"] = targetTemp; + doc["heating"] = heating; + char buf[128]; + size_t n = serializeJson(doc, buf); + client.publish(("home/thermostat/" + mqtt_device_id + "/state").c_str(), buf, n); +} + +void mqtt_callback(char* topic, byte* payload, unsigned int length) { + // Handle incoming MQTT messages (e.g., set mode, set preset, etc.) +} diff --git a/Thermostat/src/preset.cpp b/Thermostat/src/preset.cpp new file mode 100644 index 0000000..4b06cce --- /dev/null +++ b/Thermostat/src/preset.cpp @@ -0,0 +1,18 @@ +#include "preset.h" +#include + +static float presets[5] = {0, 21.0, 18.0, 23.0, 7.0}; + +void load_presets() { + // Load from EEPROM or SPIFFS +} +void save_presets() { + // Save to EEPROM or SPIFFS +} +float get_preset_temp(ThermostatMode mode) { + return presets[mode]; +} +void set_preset_temp(ThermostatMode mode, float temp) { + presets[mode] = temp; + save_presets(); +} diff --git a/Thermostat/src/thermostat.cpp b/Thermostat/src/thermostat.cpp new file mode 100644 index 0000000..0be578a --- /dev/null +++ b/Thermostat/src/thermostat.cpp @@ -0,0 +1,35 @@ +#include "thermostat.h" + +Thermostat::Thermostat() : mode(MODE_OFF), targetTemp(0), heating(false) { + presetTemps[MODE_CONFORT] = 21.0; + presetTemps[MODE_ECO] = 18.0; + presetTemps[MODE_BOOST] = 23.0; + presetTemps[MODE_HORS_GEL] = 7.0; + presetTemps[MODE_OFF] = 0.0; +} + +void Thermostat::setMode(ThermostatMode m) { + mode = m; + targetTemp = presetTemps[mode]; +} + +void Thermostat::setTemperature(float temp) { + targetTemp = temp; +} + +void Thermostat::setPresetTemp(ThermostatMode m, float temp) { + presetTemps[m] = temp; + if (mode == m) targetTemp = temp; +} + +void Thermostat::update(float currentTemp) { + if (mode == MODE_OFF) { + heating = false; + } else { + heating = (currentTemp < targetTemp); + } +} + +bool Thermostat::isHeating() const { return heating; } +ThermostatMode Thermostat::getMode() const { return mode; } +float Thermostat::getTargetTemp() const { return targetTemp; } diff --git a/Thermostat/src/web_config.cpp b/Thermostat/src/web_config.cpp new file mode 100644 index 0000000..f8c04f4 --- /dev/null +++ b/Thermostat/src/web_config.cpp @@ -0,0 +1,29 @@ +#include "web_config.h" +#include + +String wifi_ssid, wifi_pass, mqtt_server, mqtt_user, mqtt_pass, temp_sensor_id; +int mqtt_port = 1883; +float preset_confort = 21.0, preset_eco = 18.0, preset_boost = 23.0, preset_hors_gel = 7.0; +bool shouldSaveConfigFlag = false; + +void save_config() { + // Save config to SPIFFS or EEPROM +} + +void load_config() { + // Load config from SPIFFS or EEPROM +} + +void setup_web_config() { + WiFiManager wm; + // Add custom parameters for MQTT, presets, sensor id + // On save, set shouldSaveConfigFlag = true + wm.autoConnect("ThermostatConfig"); + if (shouldSaveConfigFlag) save_config(); +} + +void handle_web_config() { + // Handle web config portal if needed +} + +bool should_save_config() { return shouldSaveConfigFlag; } diff --git a/wind.md b/wind.md new file mode 100644 index 0000000..31fba00 --- /dev/null +++ b/wind.md @@ -0,0 +1,178 @@ + +--- + +## 4. Horizontal Wind Turbine (HAWT) Solution and Comparison + +### Example: Commercial HAWT (ManoMano) +- **Product:** 800W, 6-blade HAWT ([link](https://www.manomano.fr/p/eolienne-sans-onduleur-puissance-de-800-w-6-pales-tension-nominale-1224-v-vitesse-du-vent-au-demarrage-1-ms-105-65-cm-89805830)) +- **Rotor Diameter:** ~1.05m (area ≈ 0.87 m²) +- **Rated Power:** 800W (at high wind speeds, e.g., 12-15 m/s) +- **Cut-in Wind Speed:** 1 m/s (starts turning) +- **Nominal Voltage:** 12/24V + +### Realistic Power Output Calculation +- **At 1.5m height:** Wind speed is still low (see VAWT section) +- **Average wind speed used:** Same as VAWT, 3.3 m/s +- **HAWT efficiency:** Typically 30-35% (use 30% for estimate) + +#### Power Formula +$$ +P = 0.5 \times \rho \times A \times v^3 \times \text{efficiency} +$$ +Where: +- $A$ = 0.87 m² +- $v$ = monthly average wind speed (see VAWT table) +- $\rho$ = 1.225 kg/m³ +- Efficiency = 0.30 + +#### Monthly Power Output Table +| Month | v (m/s) | P_avg (W) | kWh/month | +|-----------|---------|-----------|-----------| +| January | 4.0 | 10.3 | 7.7 | +| February | 4.0 | 10.3 | 7.0 | +| March | 3.8 | 8.8 | 6.5 | +| April | 3.5 | 6.9 | 5.0 | +| May | 3.2 | 5.2 | 3.9 | +| June | 3.0 | 4.3 | 3.1 | +| July | 2.8 | 3.5 | 2.6 | +| August | 2.8 | 3.5 | 2.6 | +| September | 3.0 | 4.3 | 3.1 | +| October | 3.3 | 5.4 | 4.1 | +| November | 3.6 | 7.3 | 5.2 | +| December | 3.9 | 8.5 | 6.3 | + +**Annual total:** ~57 kWh/year + +--- + +### Comparison: VAWT vs HAWT + +| Type | Area (m²) | Efficiency | Annual Energy (kWh) | Pros | Cons | +|--------|-----------|------------|---------------------|------|------| +| VAWT | 1.0 | 25% | ~54 | Simple, omni-directional, easy to build | Lower efficiency, less power at low height | +| HAWT | 0.87 | 30% | ~57 | Higher efficiency, more power at same wind | Needs to face wind, more complex, needs tail/yaw | + +- **Both types** at 1.5m height produce similar (low) annual energy due to low wind speed. +- **HAWT** is slightly more efficient, but complexity and need to face wind are drawbacks. +- **Commercial 800W HAWT** will only reach rated power in very strong winds (rare at 1.5m). + +--- + +### Recommendations +- For learning and experimentation, both types are valid. +- For best results, try to raise the turbine higher (wind speed increases rapidly with height). +- Use data logging to compare real output with theoretical predictions. +- Consider safety and local regulations for both types. + +--- + +## Additional References +- [ManoMano HAWT Example](https://www.manomano.fr/p/eolienne-sans-onduleur-puissance-de-800-w-6-pales-tension-nominale-1224-v-vitesse-du-vent-au-demarrage-1-ms-105-65-cm-89805830) +- [HAWT vs VAWT](https://en.wikipedia.org/wiki/Comparison_of_wind_turbines) +# Wind Turbine Experiment in Plounéventer, France (29400) + +## 1. Estimating Wind Power Output + +### Key Parameters +- **Location:** Plounéventer, France (29400) +- **Turbine Type:** Vertical Axis Wind Turbine (VAWT) +- **Height:** 1.5 meters above ground +- **Swept Area:** 1 m² +- **Field:** Open, unobstructed + +### Wind Resource Estimation +- **Average wind speed at 10m in Plounéventer:** ~5.5 m/s (source: wind resource maps) +- **At 1.5m height:** Wind speed is lower due to ground friction. Estimate: ~60% of 10m value ≈ 3.3 m/s + +### Power Calculation Formula +Theoretical wind power: +$$ +P = \frac{1}{2} \cdot \rho \cdot A \cdot v^3 +$$ +Where: +- $P$ = Power (W) +- $\rho$ = Air density (1.225 kg/m³) +- $A$ = Swept area (1 m²) +- $v$ = Wind speed (m/s) + +**Turbine efficiency (Betz limit):** Max 59%, but real VAWT: 20-30%. Use 25% for estimate. + +### Monthly Wind Speed Estimates +| Month | Avg Wind Speed (m/s) | +|-----------|---------------------| +| January | 4.0 | +| February | 4.0 | +| March | 3.8 | +| April | 3.5 | +| May | 3.2 | +| June | 3.0 | +| July | 2.8 | +| August | 2.8 | +| September | 3.0 | +| October | 3.3 | +| November | 3.6 | +| December | 3.9 | + +### Monthly Power Output Calculation +For each month: +$$ +P_{avg} = 0.5 \times 1.225 \times 1 \times v^3 \times 0.25 +$$ + +| Month | v (m/s) | P_avg (W) | kWh/month | +|-----------|---------|-----------|-----------| +| January | 4.0 | 9.8 | 7.3 | +| February | 4.0 | 9.8 | 6.6 | +| March | 3.8 | 8.4 | 6.2 | +| April | 3.5 | 6.6 | 4.8 | +| May | 3.2 | 5.0 | 3.7 | +| June | 3.0 | 4.1 | 3.0 | +| July | 2.8 | 3.3 | 2.5 | +| August | 2.8 | 3.3 | 2.5 | +| September | 3.0 | 4.1 | 3.0 | +| October | 3.3 | 5.2 | 3.9 | +| November | 3.6 | 7.0 | 5.0 | +| December | 3.9 | 8.1 | 6.0 | + +**Annual total:** ~54 kWh/year + +--- + +## 2. Best Practices for Your Experiment + +### A. Turbine Design +- Use a simple, robust VAWT design (e.g., Savonius or Darrieus) +- Ensure the structure is stable and safe at 1.5m height +- Use lightweight, weather-resistant materials + +### B. Site Selection +- Place turbine in the most open, unobstructed area +- Avoid trees, buildings, or other windbreaks within 20m + +### C. Measurement & Data Logging +- Use an anemometer at 1.5m to log real wind speeds +- Install a wattmeter or data logger to record power output +- Record data at least hourly for best results + +### D. Safety & Legal +- Ensure the installation is secure and not a hazard +- Check local regulations for small wind turbines + +### E. Optimization +- Test different blade shapes and angles +- Compare results with theoretical predictions +- Try raising the turbine (if possible) to see the effect on output + +--- + +## 3. Conclusion +- At 1.5m, wind speeds are modest, so expect low power output (max ~10W, average much less) +- Annual energy: ~54 kWh (best case) +- Main value: learning about wind energy, data collection, and optimization + +--- + +## References +- [Global Wind Atlas](https://globalwindatlas.info/) +- [Betz Limit](https://en.wikipedia.org/wiki/Betz%27s_law) +- [VAWT Designs](https://en.wikipedia.org/wiki/Vertical-axis_wind_turbine)