From c5eb16707aae834d0308f1fb486f56609e835c41 Mon Sep 17 00:00:00 2001 From: gropi75 Date: Sun, 12 Mar 2023 20:09:09 +0100 Subject: [PATCH 1/4] Updated readme --- README.md | 257 ++++++++++++++++++++++++------------------------------ 1 file changed, 112 insertions(+), 145 deletions(-) diff --git a/README.md b/README.md index 172a922..1198c96 100644 --- a/README.md +++ b/README.md @@ -1,147 +1,114 @@ -# ESP32_r4850g2 -ESP32 project to control the Huawei R4850G2 Power Supply and a Soyosource inverter for a solar powered LIFEPO4 48V battery pack - - -Information: - -Power Equation for the whole house: ActGridPower + ActBatPower + SolProd = Used Power - -Hardware components: - -Inverter: - Type: GNT 1200LIM 48 - MAX: Const. Power: 800W (1200W solar operation) -Charger: - Type: Huawei R4850G2 -BMS: - Type: JK-BD6A20S8P - Software V.: V10.XY - Serial No: 2032812241 -Battary cells: - Type: EVE LF90 (3,2V 90AH, Nominal) - Datasheet No.: LF90-73103 - Cut off Voltage: 3.65V/2.5V - Std. charge/Discharge: 1.0C - - -Controller: ESPRESSIF ESP32-WROOM-32U (with ext. Antenna) -CAN Driver: - Driver IC: SN65HVD230 -Serial Driver: - Driver IC: Max485 CSA (2 pcs. for BMS and Inverter) -Display: - Driver: SSD1306 - Description: 4 Pin 0.96 Zoll OLED IIC Display Modul 128x64; - I2C Addr.: 0x3C -Temperature Sensors: - 1-Wire - Type: DS18B20 waterproof - -Connectors: -USB upper: - Pin 2 (RXD/D-) Output A Max 485 USB Driver for inverter, Inverter Input A+ - Pin 3 (TXD/D+) Output B Max 485 USB Driver for inverter, Inverter Input B- - -USB Lower: - Pin 2 (RXD/D-) CAN L - Pin 3 (TXD/D+) CAN H - -RJ45 - Pin 1 (Pair 3) Output A Max 485 USB Driver for BMS, BMS Input A+ - Pin 2 (Pair 3) Output B Max 485 USB Driver for BMS, BMS Input B- +# ESP32_R4850g2 + +![GitHub stars](https://img.shields.io/github/stars/gropi75/ESP32_r4850g2) +![GitHub forks](https://img.shields.io/github/forks/gropi75/ESP32_r4850g2) +![GitHub watchers](https://img.shields.io/github/watchers/gropi75/ESP32_r4850g2) + +ESP32 project to control the Huawei R4850G2 Power Supply and a Soyosource GNT1200 inverter for a solar powered LIFEPO4 48V battery pack + +[TOC] + +# Main features: +- control of inverter to minimize power usage of the grid (over RS485) +- control of charger to maximize own usage of solar power (over CAN-bus) +- adjustable power thresholds +- optional manual control of charging power +- access to JK-BMS data (over RS485) +- web GUI +- wifi configuration portal +- MQTT client +- scalable code for new features +- CAN dbc file for the charger + +## Hardware components: + +**Inverter:** +Type: GNT 1200LIM 48 +MAX: Const. Power: 800W (1200W solar operation) +**Charger:** +Type: Huawei R4850G2 +**BMS:** +Type: JK-BD6A20S8P +Software V.: V10.XY +Serial No: 2032812241 +**Battary cells:** +Type: EVE LF90 (3,2V 90AH, Nominal) +Datasheet No.: LF90-73103 +Cut off Voltage: 3.65V/2.5V +Std. charge/Discharge: 1.0C + +**Controller:** ESPRESSIF ESP32-WROOM-32U (with ext. Antenna) +**CAN Driver:** +Driver IC: SN65HVD230 +**Serial Driver:** +Driver IC: Max485 CSA (2 pcs. for BMS and Inverter) +**Display:** +Driver: SSD1306 +Description: 4 Pin 0.96 Zoll OLED IIC Display Modul 128x64; +I2C Addr.: 0x3C +**Temperature Sensors:** +1-Wire +Type: DS18B20 waterproof + +## External connectors: + +**USB upper: ** +Pin 2 (RXD/D-) Output A Max 485 USB Driver for inverter, Inverter Input A+ +Pin 3 (TXD/D+) Output B Max 485 USB Driver for inverter, Inverter Input B- + +**USB Lower:** +Pin 2 (RXD/D-) CAN L +Pin 3 (TXD/D+) CAN H + +**RJ45:** +Pin 1 (Pair 3) Output A Max 485 USB Driver for BMS, BMS Input A+ +Pin 2 (Pair 3) Output B Max 485 USB Driver for BMS, BMS Input B- Pinleiste 6 Pol - Pin1 GPIO26 Temp Sensor - Pin2 Ground - Pin3 +3V3 - Pin4 NC - Pin5 NC - Pin6 NC - - -Pinning Controller -GPIO Function Application Driver -GPIO00 Boot Push Burron 1 - -GPIO01 -GPIO02 -GPIO03 -GPIO04 CAN RX Charger SN65HVD230 -GPIO05 CAN TX Charger SN65HVD230 -GPIO06 -GPIO07 -GPIO08 -GPIO09 -GPIO10 -GPIO11 -GPIO12 LED Blue, Charging -GPIO13 LED Green, Discharging -GPIO14 LED Yellow, Standby -GPIO15 LED Red, ERROR -GPIO16 U2RXD Inverter Max485 CSA -GPIO17 U2TxD Inverter Max485 CSA -GPIO18 RS485_EN Chip enable, Inverter Max485 CSA -GPIO19 -GPIO21 I2C SDA1 Display SSD1306 Address: 0x3C -GPIO22 I2C SLC1 Display SSD1306 Address: 0x3C -GPIO23 -GPIO25 -GPIO26 DAT Temp. Sensors DS18B20; inc. 4K7 pull up -GPIO27 -GPIO32 RS485 RxD BMS Max485 CSA -GPIO33 RS485 TxD BMS Max485 CSA -GPIO34 RS485_EN BMS Max485 CSA -GPIO35 Dig_input Push Button 3 -GPIO36 Dig_ input Push Button 2 -GPIO39 LED auxiliary - - - - - - - -Function: CalculatePower.cpp\int CalculatePower(int ActGridPower, int ActBatPower, int PowResCharger, int MaxPowCharger, int PowResInv, int MaxPowerInv) - -Positive ActGridPower means, we import power, so we should discharge the battery with the inverter. -Negative ActGridPower means, we export power, so we can charge the battery. - -Same logic applies to the battery: -Positive ActBatPower means, we dischcharge the battery. -Negative ActBatPower means, we charge the battery. - -Cases: -1) we already charge the battery and still have sufficient solar-power (ActGridPower is negative / less than PowerResCharger) - -if ActBatPower is negative - and if ActGridPower is less than PowerResCharger - than decrease ActBatPower normally (0.3x) - -2) we charge the battery but do not have sufficient solar power any more (ActGridPower is positive / bigger than PowResCharger). We have to reduce the charging power fast. - -if ActBatPower is negative - and if ActGridPower is more than PowerResCharger - than increase ActBatPower fast (0.5x) - - -3) we discharge the battery and we export energy means, we have to reduce fast the inverter power (ActGridPower is negative/ less than PowResInv) - -if ActBatPower is positive - and if ActGridPower is negative - than reduce ActBatPower fast (0.5x) - - -4) we discharge the battery and we import energy means, we can increase the inverter power (ActGridPower is positive, higher than PowResInv) - -if ActBatPower is positive - and if ActGridPower is positive - than increase ActBatPower normally (0.3x) - -Finally we have to limit the output power, not to exceed the capabilities of the system. -(-MaXPowerCharger) < ActBatPower < MaxPowerInv - - - -Information: - -Power Equation for the whole house: ActGridPower + ActBatPower + SolProd = Used Power +Pin1 GPIO26 Temp Sensor +Pin2 Ground +Pin3 +3V3 +Pin4 NC +Pin5 NC +Pin6 NC + +## Pinning Controller + +| GPIO | Function | Application | Driver | +| :----- | :-------- | :-------------------- | :------------------------ | +| GPIO00 | Boot | Push Burron 1 | | +| GPIO01 | | | | +| GPIO02 | | | | +| GPIO03 | | | | +| GPIO04 | CAN RX | Charger | SN65HVD230 | +| GPIO05 | CAN TX | Charger | SN65HVD230 | +| GPIO06 | | | | +| GPIO07 | | | | +| GPIO08 | | | | +| GPIO09 | | | | +| GPIO10 | | | | +| GPIO11 | | | | +| GPIO12 | LED | Blue, Charging | | +| GPIO13 | LED | Green, Discharging | | +| GPIO14 | LED | Yellow, Standby | | +| GPIO15 | LED | Red, ERROR | | +| GPIO16 | U2RXD | Inverter | Max485 CSA | +| GPIO17 | U2TxD | Inverter | Max485 CSA | +| GPIO18 | RS485_EN | Chip enable, Inverter | Max485 CSA | +| GPIO19 | | | | +| GPIO21 | I2C SDA1 | Display SSD1306 | Address: 0x3C | +| GPIO22 | I2C SLC1 | Display SSD1306 | Address: 0x3C | +| GPIO23 | | | | +| GPIO25 | | | | +| GPIO26 | DAT | Temp. Sensors | DS18B20; inc. 4K7 pull up | +| GPIO27 | | | | +| GPIO32 | RS485 RxD | BMS | Max485 CSA | +| GPIO33 | RS485 TxD | BMS | Max485 CSA | +| GPIO34 | RS485_EN | BMS | Max485 CSA | +| GPIO35 | Dig_input | Push Button 3 | | +| GPIO36 | Dig_input | Push Button 2 | | +| GPIO39 | LED | auxiliary | | + +# Information: + +Power Equation for the whole house: ActGridPower + ActBatPower + SolProd = Used Power From f3ad522b0425ad532cd007f115f9c74873de5b41 Mon Sep 17 00:00:00 2001 From: gropi75 Date: Sun, 12 Mar 2023 20:28:57 +0100 Subject: [PATCH 2/4] Update readme --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 1198c96..f0e9560 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ # ESP32_R4850g2 - -![GitHub stars](https://img.shields.io/github/stars/gropi75/ESP32_r4850g2) -![GitHub forks](https://img.shields.io/github/forks/gropi75/ESP32_r4850g2) -![GitHub watchers](https://img.shields.io/github/watchers/gropi75/ESP32_r4850g2) +![GitHub Repo stars](https://img.shields.io/github/stars/gropi75/ESP32_r4850g2?style=plastic) +![GitHub watchers](https://img.shields.io/github/watchers/gropi75/ESP32_r4850g2?style=plastic) +![GitHub forks](https://img.shields.io/github/forks/gropi75/ESP32_r4850g2?style=plastic) +![Release](https://img.shields.io/github/v/release/gropi75/ESP32_r4850g2?include_prereleases) ESP32 project to control the Huawei R4850G2 Power Supply and a Soyosource GNT1200 inverter for a solar powered LIFEPO4 48V battery pack From e87e391478c6d46ae19a429884fbe9ea8c6a53a7 Mon Sep 17 00:00:00 2001 From: gropi75 Date: Sun, 12 Mar 2023 20:57:25 +0100 Subject: [PATCH 3/4] Updated readme --- README.md | 74 ++++++++++++++++++++++++++++++++----------------------- 1 file changed, 43 insertions(+), 31 deletions(-) diff --git a/README.md b/README.md index f0e9560..2e992be 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ ESP32 project to control the Huawei R4850G2 Power Supply and a Soyosource GNT120 [TOC] # Main features: -- control of inverter to minimize power usage of the grid (over RS485) +- control of inverter to minimize power usage out of the grid (over RS485) - control of charger to maximize own usage of solar power (over CAN-bus) - adjustable power thresholds - optional manual control of charging power @@ -22,54 +22,66 @@ ESP32 project to control the Huawei R4850G2 Power Supply and a Soyosource GNT120 ## Hardware components: -**Inverter:** -Type: GNT 1200LIM 48 -MAX: Const. Power: 800W (1200W solar operation) -**Charger:** -Type: Huawei R4850G2 -**BMS:** -Type: JK-BD6A20S8P -Software V.: V10.XY -Serial No: 2032812241 -**Battary cells:** -Type: EVE LF90 (3,2V 90AH, Nominal) -Datasheet No.: LF90-73103 -Cut off Voltage: 3.65V/2.5V -Std. charge/Discharge: 1.0C - -**Controller:** ESPRESSIF ESP32-WROOM-32U (with ext. Antenna) -**CAN Driver:** -Driver IC: SN65HVD230 -**Serial Driver:** -Driver IC: Max485 CSA (2 pcs. for BMS and Inverter) -**Display:** -Driver: SSD1306 -Description: 4 Pin 0.96 Zoll OLED IIC Display Modul 128x64; -I2C Addr.: 0x3C -**Temperature Sensors:** -1-Wire -Type: DS18B20 waterproof +- **Inverter:** + - Type: GNT 1200LIM 48 + - MAX: Const. Power: 800W (1200W solar operation) +- **Charger:** + - Type: Huawei R4850G2 +- **BMS:** + - Type: JK-BD6A20S8P + - Software V.: V10.XY + - Serial No: 2032812241 +- **Battary cells:** + - Type: EVE LF90 (3,2V 90AH, Nominal) + - Datasheet No.: LF90-73103 + - Cut off Voltage: 3.65V/2.5V + - Std. charge/Discharge: 1.0C + +- **Controller:** + - ESPRESSIF ESP32-WROOM-32U (with ext. Antenna) +- **CAN interface:** + - Driver IC: SN65HVD230 +- **RS485 Serial interface:** + - Driver IC: Max485 CSA (2 pcs. for BMS and Inverter) +- **0.96 inch OLED IIC 128x64 Display:** + - Driver: SSD1306 + - I2C Addr.: 0x3C +- **Temperature Sensors:** + - 1-Wire + - Type: DS18B20 waterproof ## External connectors: -**USB upper: ** +**USB upper:** + Pin 2 (RXD/D-) Output A Max 485 USB Driver for inverter, Inverter Input A+ + Pin 3 (TXD/D+) Output B Max 485 USB Driver for inverter, Inverter Input B- **USB Lower:** + Pin 2 (RXD/D-) CAN L + Pin 3 (TXD/D+) CAN H **RJ45:** + Pin 1 (Pair 3) Output A Max 485 USB Driver for BMS, BMS Input A+ + Pin 2 (Pair 3) Output B Max 485 USB Driver for BMS, BMS Input B- -Pinleiste 6 Pol +**6 pin connector:** + Pin1 GPIO26 Temp Sensor + Pin2 Ground + Pin3 +3V3 + Pin4 NC + Pin5 NC + Pin6 NC ## Pinning Controller @@ -111,4 +123,4 @@ Pin6 NC # Information: -Power Equation for the whole house: ActGridPower + ActBatPower + SolProd = Used Power +Power Equation for the whole house: $\ ActGridPower + ActBatPower + SolProd = Used Power$ From d73ad05d383ab8a9a0ecf80a67f4f0ba2fb47280 Mon Sep 17 00:00:00 2001 From: gropi75 Date: Sun, 19 Mar 2023 21:54:21 +0100 Subject: [PATCH 4/4] Updated sunrise functions; dynamic load calculatio --- .gitignore | 10 + .pio/build/esp32dev/tmpahxafcje.tmp | 1 - README.md | 11 +- lib/PowerFunctions.h | 7 + lib/secrets_dummy.h | 22 ++ lib/sunrise.h | 34 ++- src/PowerFunctions.cpp | 41 +++ src/main.cpp | 107 +++++++- src/sunrise.cpp | 374 +++++++++++++++------------- 9 files changed, 427 insertions(+), 180 deletions(-) delete mode 100644 .pio/build/esp32dev/tmpahxafcje.tmp create mode 100644 lib/secrets_dummy.h diff --git a/.gitignore b/.gitignore index aca85c3..8c7aeaf 100644 --- a/.gitignore +++ b/.gitignore @@ -376,3 +376,13 @@ src/main.cpp .pio/libdeps/esp32dev/ArduinoJson/logo.svg .pio/libdeps/esp32dev/ArduinoJson/idf_component.yml .pio/libdeps/esp32dev/ArduinoJson/LICENSE.txt +.pio/build/esp32dev/tmpahxafcje.tmp +.pio/build/esp32dev/tmpahxafcje.tmp +.pio/build/esp32dev/tmpao0pn_tn.tmp +.pio/build/esp32dev/tmpezdmcyso.tmp +.pio/build/esp32dev/tmpj2jtsnn0.tmp +.pio/build/esp32dev/tmpn8d7uo8a.tmp +.pio/build/esp32dev/tmpot58lxer.tmp +.pio/build/esp32dev/tmpq6hmdh87.tmp +.pio/build/esp32dev/tmpwft6of8y.tmp +.pio/build/esp32dev/tmpahxafcje.tmp diff --git a/.pio/build/esp32dev/tmpahxafcje.tmp b/.pio/build/esp32dev/tmpahxafcje.tmp deleted file mode 100644 index f06427a..0000000 --- a/.pio/build/esp32dev/tmpahxafcje.tmp +++ /dev/null @@ -1 +0,0 @@ --o .pio/build/esp32dev/src/main.cpp.o -c -Wno-frame-address -std=gnu++11 -fexceptions -fno-rtti -Os -mlongcalls -ffunction-sections -fdata-sections -Wno-error=unused-function -Wno-error=unused-variable -Wno-error=deprecated-declarations -Wno-unused-parameter -Wno-sign-compare -ggdb -freorder-blocks -Wwrite-strings -fstack-protector -fstrict-volatile-bitfields -Wno-error=unused-but-set-variable -fno-jump-tables -fno-tree-switch-conversion -MMD -DPLATFORMIO=60106 -DARDUINO_NodeMCU_32S -DHAVE_CONFIG_H -DMBEDTLS_CONFIG_FILE=\"mbedtls/esp_config.h\" -DUNITY_INCLUDE_CONFIG_H -DWITH_POSIX -D_GNU_SOURCE -DIDF_VER=\"v4.4.3\" -DESP_PLATFORM -D_POSIX_READER_WRITER_LOCKS -DARDUINO_ARCH_ESP32 -DESP32 -DF_CPU=240000000L -DARDUINO=10812 -DARDUINO_VARIANT=\"nodemcu-32s\" -DARDUINO_BOARD=\"NodeMCU-32S\" -DARDUINO_PARTITION_default -Isrc -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/libraries/HTTPClient/src -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/libraries/WiFiClientSecure/src -I.pio/libdeps/esp32dev/NTPClient "-I.pio/libdeps/esp32dev/Adafruit SSD1306" "-I.pio/libdeps/esp32dev/Adafruit GFX Library" "-I.pio/libdeps/esp32dev/Adafruit BusIO" -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/libraries/Wire/src -I.pio/libdeps/esp32dev/PubSubClient/src -I.pio/libdeps/esp32dev/CAN/src -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/libraries/SPI/src -I.pio/libdeps/esp32dev/ESPUI/src -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/libraries/LittleFS/src -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/libraries/ArduinoOTA/src -I.pio/libdeps/esp32dev/ArduinoJson@src-a1164c4c0cec8d7db9eadf9d19ad17c1/src -I.pio/libdeps/esp32dev/WiFiManager -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/libraries/WebServer/src -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/libraries/Update/src -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/libraries/ESPmDNS/src -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/libraries/DNSServer/src "-I.pio/libdeps/esp32dev/ESP Async WebServer/src" -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/libraries/WiFi/src -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/libraries/FS/src -I.pio/libdeps/esp32dev/AsyncTCP@src-2154f270fe2afd37e50c673663dbc05d/src -Ilib -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/newlib/platform_include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/freertos/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/freertos/include/esp_additions/freertos -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/freertos/port/xtensa/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/freertos/include/esp_additions -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp_hw_support/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp_hw_support/include/soc -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp_hw_support/include/soc/esp32 -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp_hw_support/port/esp32 -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp_hw_support/port/esp32/private_include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/heap/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/log/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/lwip/include/apps -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/lwip/include/apps/sntp -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/lwip/lwip/src/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/lwip/port/esp32/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/lwip/port/esp32/include/arch -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/soc/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/soc/esp32 -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/soc/esp32/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/hal/esp32/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/hal/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/hal/platform_port/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp_rom/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp_rom/include/esp32 -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp_rom/esp32 -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp_common/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp_system/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp_system/port/soc -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp_system/port/public_compat -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp32/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/xtensa/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/xtensa/esp32/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/driver/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/driver/esp32/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp_pm/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp_ringbuf/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/efuse/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/efuse/esp32/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/vfs/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp_wifi/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp_event/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp_netif/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp_eth/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/tcpip_adapter/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp_phy/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp_phy/esp32/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp_ipc/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/app_trace/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp_timer/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/mbedtls/port/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/mbedtls/mbedtls/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/mbedtls/esp_crt_bundle/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/app_update/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/spi_flash/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/bootloader_support/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/nvs_flash/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/pthread/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp_gdbstub/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp_gdbstub/xtensa -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp_gdbstub/esp32 -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/espcoredump/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/espcoredump/include/port/xtensa -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/wpa_supplicant/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/wpa_supplicant/port/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/wpa_supplicant/esp_supplicant/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/ieee802154/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/console -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/asio/asio/asio/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/asio/port/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/bt/common/osi/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/bt/include/esp32/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/bt/common/api/include/api -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/bt/common/btc/profile/esp/blufi/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/bt/common/btc/profile/esp/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/bt/host/bluedroid/api/include/api -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/bt/esp_ble_mesh/mesh_common/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/bt/esp_ble_mesh/mesh_common/tinycrypt/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/bt/esp_ble_mesh/mesh_core -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/bt/esp_ble_mesh/mesh_core/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/bt/esp_ble_mesh/mesh_core/storage -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/bt/esp_ble_mesh/btc/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/bt/esp_ble_mesh/mesh_models/common/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/bt/esp_ble_mesh/mesh_models/client/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/bt/esp_ble_mesh/mesh_models/server/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/bt/esp_ble_mesh/api/core/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/bt/esp_ble_mesh/api/models/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/bt/esp_ble_mesh/api -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/cbor/port/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/unity/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/unity/unity/src -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/cmock/CMock/src -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/coap/port/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/coap/libcoap/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/nghttp/port/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/nghttp/nghttp2/lib/includes -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp-tls -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp-tls/esp-tls-crypto -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp_adc_cal/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp_hid/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/tcp_transport/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp_http_client/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp_http_server/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp_https_ota/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp_https_server/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp_lcd/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp_lcd/interface -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/protobuf-c/protobuf-c -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/protocomm/include/common -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/protocomm/include/security -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/protocomm/include/transports -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/mdns/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp_local_ctrl/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/sdmmc/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp_serial_slave_link/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp_websocket_client/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/expat/expat/expat/lib -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/expat/port/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/wear_levelling/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/fatfs/diskio -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/fatfs/vfs -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/fatfs/src -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/freemodbus/common/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/idf_test/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/idf_test/include/esp32 -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/jsmn/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/json/cJSON -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/libsodium/libsodium/src/libsodium/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/libsodium/port_include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/mqtt/esp-mqtt/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/openssl/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/perfmon/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/spiffs/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/ulp/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/wifi_provisioning/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/rmaker_common/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/json_parser/upstream/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/json_parser/upstream -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/json_generator/upstream -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp_schedule/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp_rainmaker/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/gpio_button/button/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/qrcode/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/ws2812_led -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp_diagnostics/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/rtc_store/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp_insights/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp-dsp/modules/dotprod/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp-dsp/modules/support/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp-dsp/modules/windows/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp-dsp/modules/windows/hann/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp-dsp/modules/windows/blackman/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp-dsp/modules/windows/blackman_harris/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp-dsp/modules/windows/blackman_nuttall/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp-dsp/modules/windows/nuttall/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp-dsp/modules/windows/flat_top/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp-dsp/modules/iir/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp-dsp/modules/fir/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp-dsp/modules/math/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp-dsp/modules/math/add/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp-dsp/modules/math/sub/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp-dsp/modules/math/mul/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp-dsp/modules/math/addc/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp-dsp/modules/math/mulc/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp-dsp/modules/math/sqrt/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp-dsp/modules/matrix/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp-dsp/modules/fft/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp-dsp/modules/dct/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp-dsp/modules/conv/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp-dsp/modules/common/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp-dsp/modules/kalman/ekf/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp-dsp/modules/kalman/ekf_imu13states/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp_littlefs/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp-dl/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp-dl/include/tool -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp-dl/include/typedef -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp-dl/include/image -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp-dl/include/math -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp-dl/include/nn -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp-dl/include/layer -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp-dl/include/detect -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp-dl/include/model_zoo -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp-sr/src/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp-sr/esp-tts/esp_tts_chinese/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp-sr/include/esp32 -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp32-camera/driver/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp32-camera/conversions/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/fb_gfx/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/dio_qspi/include -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/cores/esp32 -IC:/Users/uli/.platformio/packages/framework-arduinoespressif32/variants/nodemcu-32s src/main.cpp diff --git a/README.md b/README.md index 2e992be..29a30ec 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,12 @@ -# ESP32_R4850g2 +# Solar Energy Manager for ESP32 (SEM.32) ![GitHub Repo stars](https://img.shields.io/github/stars/gropi75/ESP32_r4850g2?style=plastic) ![GitHub watchers](https://img.shields.io/github/watchers/gropi75/ESP32_r4850g2?style=plastic) ![GitHub forks](https://img.shields.io/github/forks/gropi75/ESP32_r4850g2?style=plastic) ![Release](https://img.shields.io/github/v/release/gropi75/ESP32_r4850g2?include_prereleases) -ESP32 project to control the Huawei R4850G2 Power Supply and a Soyosource GNT1200 inverter for a solar powered LIFEPO4 48V battery pack +SEM.32 (Solar Energy Manager 32) based on ESP32 controller, Soyosource Inverter, Huawei r4850g2 power supply, JK-BMS and 48V battery. It helps You to maximize the usage of self generated solar power. + -[TOC] # Main features: - control of inverter to minimize power usage out of the grid (over RS485) @@ -31,11 +31,14 @@ ESP32 project to control the Huawei R4850G2 Power Supply and a Soyosource GNT120 - Type: JK-BD6A20S8P - Software V.: V10.XY - Serial No: 2032812241 -- **Battary cells:** +- **Battery cells:** - Type: EVE LF90 (3,2V 90AH, Nominal) - Datasheet No.: LF90-73103 - Cut off Voltage: 3.65V/2.5V - Std. charge/Discharge: 1.0C +- **Power Meter:** + - Type: Tasmota based smart meter from [Hitchi](https://www.photovoltaikforum.com/thread/173032-lesekopf-bei-heise-getestet/) + - **Controller:** - ESPRESSIF ESP32-WROOM-32U (with ext. Antenna) diff --git a/lib/PowerFunctions.h b/lib/PowerFunctions.h index 78444a9..9e1b939 100644 --- a/lib/PowerFunctions.h +++ b/lib/PowerFunctions.h @@ -3,3 +3,10 @@ int CalculatePower(int ActGridPower, int ActBatPower, int PowResCharger, int Max // Get actual power from the central power meter. int getActualPower(char ip[40], char cmd[40], char resp[20], char resp_power[20]); + +// calculate max inverter load to have a balanced discharge of the battery over the whole night +int CalculateBalancedDischargePower(int capacity, float voltage, int actualSOC, int targetSOC, float sunset, float sunrise); + +// get solar prognosis +float getSolarPrognosis(char token[40], char id[4], char today[9], char tomorrow[9]); + diff --git a/lib/secrets_dummy.h b/lib/secrets_dummy.h new file mode 100644 index 0000000..8300a2b --- /dev/null +++ b/lib/secrets_dummy.h @@ -0,0 +1,22 @@ +// rename this file to secrets.h + +const char g_WIFI_SSID[] = "SSID"; +const char g_WIFI_Passphrase[] = "password"; + +char mqtt_server[40] = "192.168.188.80"; +char mqtt_port[6] = "1883"; +char current_clamp_ip[40] = "192.168.188.127"; +char current_clamp_cmd[40] = "/cm?cmnd=status+10"; +char sensor_resp[20] = "SML"; // or "MT175" +char sensor_resp_power[20] = "DJ_TPWRCURR"; // or "P" +bool g_EnableMQTT = true; + +char solarprognose_token[40] = "token"; // token to get prognosis from http://www.solarprognose.de +char solarprognose_id[4] = "999"; + +// +float lagmorning=0; // time in decimal hours between real sunset and start of PV +float lagevening=0; // time in decimal hours between end of PV power production and real sunset + +float laenge = 9.1234; // Postition of PV +float breite = 48.9999; // Position of PV \ No newline at end of file diff --git a/lib/sunrise.h b/lib/sunrise.h index cbfcdce..1cb2e4e 100644 --- a/lib/sunrise.h +++ b/lib/sunrise.h @@ -1,4 +1,15 @@ +#ifndef sunrise_H +#define sunrise_H +struct TimeStruct { + float sunrise_today; // sunrise today + float sunset_today; // sunset today + float sunrise_tomorrow; // sunrise tomorrow + int day_of_week; // shows which day is today, Monday.... Sunday + char* date_today; // date of today with format yyyymmdd (20230312) + char* date_tomorrow; // date for tomorro with format yyyymmdd (20230312) +}; +void TimeData(struct TimeStruct *s,float lagmorning, float lagevening, float laenge, float breite); // Function to setup the time client void setuptimeClient (); @@ -14,5 +25,26 @@ void setuptimeClient (); // This function figures out wethere PV can produce power or not // flag pvstartflag is true at daytime when pv can procuce power and false when PV can not produce power -bool setPVstartflag(float lagmorning, float lagevening); +bool setPVstartflag(float lagmorning, float lagevening, float laenge, float breite); +// current time in decimal hours +float factualtimeinhours(); + +// add on Issue in Github Provide time information #16 +//float sunrisetoday(); // sunrise of current day in decimal hours including lag +//float sunsettoday(); // sunset of current Day including lag +//float sunrisetomorow(); // sunrise today of next day including lag +//float actualtimeinhours(); // current time in decimal hours +//int dayofweek(); //current day of week as integer 1 monday ... 7 sunday +//char date_today(); // current datedate of today with format yyyymmdd (20230312) +//char date_tomorow();// date of tomorow with format yyyymmdd (20230312) + +//float fstartpv(float lagmorning, float lagevening, float laenge, float breite); // time when PV starts producing= sunrise + lagmorning +//float fstoppv(float lagmorning, float lagevening,float laenge, float breite); // time when PV stopps producing= sunset - lagevening +//float fstartpvtomorow(float lagmorning, float lagevening,float laenge, float breite); // Time when PV starts producing next day= sunrise + lagmorning + +//int fweekday(); //function returns the current week day as a char +//char* fdate_today(); // current date of today with format yyyymmdd (20230312) +//char* fdate_tomorow(); // date of tomorow with format yyyymmdd (20230312) + +#endif //sunrise_H \ No newline at end of file diff --git a/src/PowerFunctions.cpp b/src/PowerFunctions.cpp index 59a14d3..7957ed3 100644 --- a/src/PowerFunctions.cpp +++ b/src/PowerFunctions.cpp @@ -5,6 +5,9 @@ WiFiClient current_clamp_client; // or WiFiClientSecure for HTTPS; to connect to current sensor HTTPClient http; // to connect to current sensor +WiFiClient solarprognose_client; // to connect to Solarprognose.de +HTTPClient http_solar; + // Positive ActPower means, we import power, so we need the inverter // Negative ActPower means, we export power, so we can charge the batter // Calculate the set power both for charger and inverter. @@ -72,4 +75,42 @@ int getActualPower(char ip[40], char cmd[40], char resp[20], char resp_power[20] actPower = StatusSNS_SML[String(resp_power)]; // -2546 } return actPower; +} + +// calculate max inverter load to have a balanced discharge of the battery over the whole night +int CalculateBalancedDischargePower(int capacity, float voltage, int actualSOC, int targetSOC, float sunset, float sunrise) +{ + // shall we use https://github.com/buelowp/sunset + return (int)(capacity * voltage * 0.01 * (actualSOC - targetSOC) / (sunrise - sunset + 24)); +} + +// get solar prognosis +// http://www.solarprognose.de/web/solarprediction/api/v1?access-token=454jelfd&item=inverter&id=2&type=daily +float getSolarPrognosis(char token[40], char id[4], char today[9], char tomorrow[9]) +{ + float prognosis_today, prognosis_tomorrow; + char solarprognose_adress[83] = "http://www.solarprognose.de/web/solarprediction/api/v1?_format=json&access-token="; + http_solar.begin(solarprognose_client, solarprognose_adress + String(token) + "&item=location&id=" + String(id) + "&type=daily"); + int httpCode = http_solar.GET(); // send the request + if (httpCode > 0) + { + String payload = http_solar.getString(); // Get the request response payload + StaticJsonDocument<768> doc; + Serial.println(payload); + DeserializationError error = deserializeJson(doc, payload); + + if (error) + { + Serial.print("deserializeJson() failed: "); + Serial.println(error.c_str()); + return 0; + } + prognosis_today = doc["data"][String(today)]; // 9.322 + prognosis_tomorrow = doc["data"][String(tomorrow)]; // 20.653 + Serial.println(String(today)); + Serial.println(String(prognosis_today)); + Serial.println(String(tomorrow)); + Serial.println(String(prognosis_tomorrow)); + } + return prognosis_tomorrow; } \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index a791087..9c60639 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -79,6 +79,7 @@ FS *filesystem = &LittleFS; #include "PowerFunctions.h" #include "jkbms.h" #include "secrets.h" +#include "sunrise.h" TaskHandle_t TaskCan; int packetSize; @@ -118,15 +119,28 @@ namespace Main int PowerReserveInv = 15; int MaxPowerCharger = 2000; int MaxPowerInv = 100; + int DynPowerInv; bool g_EnableCharge = true; + float solar_prognosis; + int target_SOC; + + char date_today[9] = "20230319"; + char date_tomorrow[9] = "20230320"; + int date_dayofweek_today = 8; unsigned long g_Time500 = 0; unsigned long g_Time1000 = 0; unsigned long g_Time5000 = 0; + unsigned long g_Time30Min = 0; char temp_char[10]; // for temporary storage of strings values char mqtt_topic[60]; + // Time information + TimeStruct myTime; // create a TimeStruct instance to hold the returned data + float time_now; + bool is_day; // true: is day, false: is night + // BMS values as structure JK_BMS_Data BMS; JK_BMS_RS485_Data receivedRawData; @@ -134,7 +148,7 @@ namespace Main // byte receivedBytes_main[320]; uint16_t gui_PowerReserveCharger, gui_PowerReserveInv, gui_MaxPowerCharger, gui_MaxPowerInv; - uint16_t gui_ActualSetPower, gui_ActualSetPowerCharger, gui_ActualSetPowerInv; + uint16_t gui_ActualSetPower, gui_ActualSetPowerCharger, gui_ActualSetPowerInv, gui_DynPowerInv; uint16_t gui_SetMaxPowerInv, gui_SetMaxPowerCharger, gui_setMQTTIP, gui_setMQTTport, gui_testMQTT, gui_enableMQTT, gui_enableChange, gui_savesettings; uint16_t gui_GridPower, gui_ChargerVoltage, gui_ChargerCurrent, gui_ChargerPower; uint16_t gui_ChargerACVoltage, gui_ChargerACCurrent, gui_ChargerACPower, gui_ChargerACfreq; @@ -144,11 +158,12 @@ namespace Main uint16_t guiVoltageCell10, guiVoltageCell11, guiVoltageCell12, guiVoltageCell13, guiVoltageCell14, guiVoltageCell15; uint16_t guiCapacity, guiSysWorkingTime, guiTotCapacity, guiChargeCurrent, guiLog; uint16_t guiSOC, guiBattVoltage, guiBattStatus, guiCellDelta, guiAvgCellVoltage, guiCellCount; + uint16_t gui_today_sunrise, gui_today_sunset, gui_tomorrow_sunrise, gui_prediction; uint16_t guiMOST, guiT1, guiT2; uint16_t gui_resetsettings, gui_resetESP; - uint16_t gui_enableManControl, gui_ManualSetPower, g_ManualSetPowerCharger; - uint16_t gui_SetPowerReserveCharger, gui_SetPowerReserveInverter, gui_BatPower; - bool g_enableManualControl; + uint16_t gui_enableManControl, gui_ManualSetPower, g_ManualSetPowerCharger, gui_enabledynamicload; + uint16_t gui_SetPowerReserveCharger, gui_SetPowerReserveInverter, gui_BatPower, gui_PVprognosis; + bool g_enableManualControl, g_enableDynamicload = false; bool wm_resetsetting = false; // flag for saving data inside WifiManager @@ -332,9 +347,17 @@ namespace Main ESPUI.addControl(ControlType::Separator, "(Dis-)Charge Settings", "", ControlColor::None, TabBatteryInfo); gui_MaxPowerCharger = ESPUI.addControl(ControlType::Label, "Max Power Charger [W]", "0", ControlColor::Emerald, TabBatteryInfo); gui_MaxPowerInv = ESPUI.addControl(ControlType::Label, "Max Power Inverter[W]", "0", ControlColor::Emerald, TabBatteryInfo); + gui_DynPowerInv = ESPUI.addControl(ControlType::Label, "Dynamic Power Inverter[W]", "0", ControlColor::Emerald, TabBatteryInfo); gui_PowerReserveCharger = ESPUI.addControl(ControlType::Label, "Power Reserve Charger [W]", "0", ControlColor::Emerald, TabBatteryInfo); gui_PowerReserveInv = ESPUI.addControl(ControlType::Label, "Power Reserve Inverter [W]", "0", ControlColor::Emerald, TabBatteryInfo); + ESPUI.addControl(ControlType::Separator, "Solar info", "", ControlColor::None, TabBatteryInfo); + gui_prediction = ESPUI.addControl(ControlType::Label, "Power prediction tomorrow [W]", "0", ControlColor::Emerald, TabBatteryInfo); + gui_today_sunrise = ESPUI.addControl(ControlType::Label, "Sunrise today", "0", ControlColor::Emerald, TabBatteryInfo); + gui_today_sunset = ESPUI.addControl(ControlType::Label, "Sunset today", "0", ControlColor::Emerald, TabBatteryInfo); + gui_tomorrow_sunrise = ESPUI.addControl(ControlType::Label, "Sunrise tomorrow", "0", ControlColor::Emerald, TabBatteryInfo); + + // Settings tab gui_enableChange = ESPUI.addControl(ControlType::Switcher, "Edit", "", ControlColor::Alizarin, TabSettings, generalCallback); gui_savesettings = ESPUI.addControl(Button, "Save settings", "push", Alizarin, TabSettings, generalCallback); @@ -356,6 +379,7 @@ namespace Main gui_ManualSetPower = ESPUI.addControl(Slider, "Set charging power manually", "0", Alizarin, TabSettings, generalCallback); ESPUI.addControl(Min, "", "0", None, gui_ManualSetPower); ESPUI.addControl(Max, "", "4000", None, gui_ManualSetPower); + gui_enabledynamicload = ESPUI.addControl(ControlType::Switcher, "Enable dynamic load", "", ControlColor::Alizarin, TabSettings, generalCallback); ESPUI.addControl(ControlType::Separator, "Network settings", "", ControlColor::None, TabSettings); gui_setMQTTIP = ESPUI.addControl(Text, "MQTT Server:", mqtt_server, Alizarin, TabSettings, generalCallback); @@ -382,6 +406,7 @@ namespace Main ESPUI.setEnabled(gui_resetsettings, false); ESPUI.setEnabled(gui_SetPowerReserveCharger, false); ESPUI.setEnabled(gui_SetPowerReserveInverter, false); + ESPUI.setEnabled(gui_enabledynamicload, g_enableDynamicload); } // update ESPUI @@ -392,6 +417,7 @@ namespace Main ESPUI.updateLabel(gui_ActualSetPowerInv, String(ActualSetPowerInv) + "W"); ESPUI.updateLabel(gui_MaxPowerCharger, String(MaxPowerCharger) + "W"); ESPUI.updateLabel(gui_MaxPowerInv, String(MaxPowerInv) + "W"); + ESPUI.updateLabel(gui_DynPowerInv, String(DynPowerInv) + "W"); ESPUI.updateLabel(gui_PowerReserveCharger, String(PowerReserveCharger) + "W"); ESPUI.updateLabel(gui_PowerReserveInv, String(PowerReserveInv) + "W"); ESPUI.updateLabel(gui_GridPower, String(ActualPower) + "W"); @@ -404,7 +430,6 @@ namespace Main ESPUI.updateLabel(gui_ChargerACfreq, String(Huawei::g_PSU.input_freq) + "Hz"); ESPUI.updateLabel(gui_ChargerACPower, String(Huawei::g_PSU.input_power) + "W"); - // update the BMS values also only every 5 sec ESPUI.updateLabel(guiVoltageCell0, String(BMS.cellVoltage[0], 3) + "V"); @@ -434,6 +459,12 @@ namespace Main ESPUI.updateLabel(guiT1, String(BMS.Battery_T1, 0) + "°C"); ESPUI.updateLabel(guiT2, String(BMS.Battery_T2, 0) + "°C"); ESPUI.updateLabel(gui_BatPower, String(BMS.Battery_Power, 0) + "W"); + ESPUI.updateLabel(gui_prediction, String(solar_prognosis, 0) + "kW"); + ESPUI.updateLabel(gui_today_sunrise, String(myTime.sunrise_today, 2)); + ESPUI.updateLabel(gui_today_sunset, String(myTime.sunset_today, 2)); + ESPUI.updateLabel(gui_tomorrow_sunrise, String(myTime.sunrise_tomorrow, 2)); + + ESPUI.updateLabel(guiCapacity, String(BMS.Nominal_Capacity) + "Ah"); ESPUI.updateLabel(guiSysWorkingTime, String(BMS.days) + " days " + String(BMS.hr) + ":" + String(BMS.mi)); @@ -469,6 +500,7 @@ namespace Main json["PowerReserveInv"] = PowerReserveInv; json["MaxPowerCharger"] = MaxPowerCharger; json["MaxPowerInv"] = MaxPowerInv; + json["g_enableDynamicload"] = g_enableDynamicload; File configFile = LittleFS.open("/config.json", "w"); if (!configFile) @@ -547,6 +579,7 @@ namespace Main MaxPowerInv = json["MaxPowerInv"]; g_EnableMQTT = json["g_EnableMQTT"]; wm_resetsetting = json["wm_resetsetting"]; + g_enableDynamicload = json["g_enableDynamicload"]; } else { @@ -697,6 +730,9 @@ namespace Main JKBMS_init_RS485(JKBMS_RS485_PORT_RX, JKBMS_RS485_PORT_TX, JKBMS_RS485_PORT_EN); Serial.println("JK-BMS RS485 setup done"); + // initialize NTP connection + setuptimeClient(); + // initialize MQTT, however only connect, if it is enabled PSclient.setServer(mqtt_server, atoi(mqtt_port)); PSclient.setCallback(callback); @@ -764,7 +800,7 @@ namespace Main // ActualCurrent = info.output_current; // calculate desired power - ActualSetPower = CalculatePower(ActualPower, ActualSetPower, PowerReserveCharger, MaxPowerCharger, PowerReserveInv, MaxPowerInv); + ActualSetPower = CalculatePower(ActualPower, ActualSetPower, PowerReserveCharger, MaxPowerCharger, PowerReserveInv, DynPowerInv); // decide, whether the charger or inverter shall be activated @@ -901,6 +937,52 @@ namespace Main } g_Time5000 = millis(); } + + + +#ifdef test_debug + if ((millis() - g_Time30Min) > 10000) // every 10 seconds in case of debugging +#elif + if ((millis() - g_Time30Min) > 18000000) // 18000000 ms = 30 Minutes +#endif + + + { + TimeData(&myTime, lagmorning, lagevening, laenge, breite); // call the TimeData function with the parameters and the pointer to the TimeStruct instance + + // execute the following only once a day + if (date_dayofweek_today != myTime.day_of_week) + { + // !!! shall be executed only few times a day, due to API limitations. So time functions has to be implemented at first + solar_prognosis = getSolarPrognosis(solarprognose_token, solarprognose_id, myTime.date_today, myTime.date_tomorrow); + date_dayofweek_today = myTime.day_of_week; + } + + if (is_day != setPVstartflag(lagmorning, lagevening, laenge, breite)) + { + is_day = !(is_day); + if (!is_day) // execute at sunset + { + if (g_enableDynamicload) + { + + if (solar_prognosis < 4.6) + { + target_SOC = int( 100 * (4.6 - solar_prognosis) / (4.6)); + } + else + target_SOC = 0; + DynPowerInv = CalculateBalancedDischargePower(BMS.Nominal_Capacity, BMS.Battery_Voltage, BMS.SOC, target_SOC, myTime.sunset_today, myTime.sunrise_tomorrow); + } + else + { + DynPowerInv = MaxPowerInv; + } + } + } + + g_Time30Min = millis(); + } } // Most UI elements are assigned this generic callback which prints some @@ -951,6 +1033,17 @@ namespace Main PSclient.disconnect(); } } + if (sender->id == gui_enabledynamicload) + { + if (type == S_ACTIVE) + { + g_enableDynamicload = true; + } + if (type == S_INACTIVE) + { + g_enableDynamicload = false; + } + } if (sender->id == gui_testMQTT) { if (type == B_DOWN) @@ -1019,6 +1112,7 @@ namespace Main ESPUI.setEnabled(gui_resetsettings, true); ESPUI.setEnabled(gui_SetPowerReserveCharger, true); ESPUI.setEnabled(gui_SetPowerReserveInverter, true); + ESPUI.setEnabled(gui_enabledynamicload, true); } if (type == S_INACTIVE) { @@ -1035,6 +1129,7 @@ namespace Main ESPUI.setEnabled(gui_resetsettings, false); ESPUI.setEnabled(gui_SetPowerReserveCharger, false); ESPUI.setEnabled(gui_SetPowerReserveInverter, false); + ESPUI.setEnabled(gui_enabledynamicload, false); } } } diff --git a/src/sunrise.cpp b/src/sunrise.cpp index 422724c..375f4ac 100644 --- a/src/sunrise.cpp +++ b/src/sunrise.cpp @@ -1,66 +1,76 @@ - - +// Aufgaben 16.03.2023: in lauffähiges programm bringen, ohne display mit wifi connection. +// testen im Main alle daten ausgeben +// korrektur sunrise tomorow benötigt auch epochtime+1 Tag!! +// https://randomnerdtutorials.com/esp8266-nodemcu-date-time-ntp-client-server-arduino/ #include #include +#include "sunrise.h" - -#define PI 3.1415926536 -int dayofyear=0; +// #define PI 3.1415926536 +int dayofyear = 0; +int dayofyearplusone = 0; +float currenttime; // this is the time in decimal hours i.e. 8.5 +float startpv, stoppv, startpvtomorow; // time in decimal hours when PV starts, stopps +int vdayofweek; // day of week +int currentDay; // Define NTP Client to get time WiFiUDP ntpUDP; NTPClient timeClient(ntpUDP, "pool.ntp.org"); -//Week Days -String weekDays[7]={"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}; - -//Month names -String months[12]={"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"}; +// Week Days +String weekDays[7] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}; +// Month names +String months[12] = {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"}; //________________________________________________________________________________________calculate sunrise and sunset // die folgenden Formeln wurden der Seite http://lexikon.astronomie.info/zeitgleichung/ entnommen - // subfunction to compute Sonnendeklination -float sonnendeklination(int T) { - // Deklination der Sonne in Radians - // Formula 2008 by Arnold(at)Barmettler.com, fit to 20 years of average declinations (2008-2017) - return 0.409526325277017*sin(0.0169060504029192*(T-80.0856919827619)); +float sonnendeklination(int T) +{ + // Deklination der Sonne in Radians + // Formula 2008 by Arnold(at)Barmettler.com, fit to 20 years of average declinations (2008-2017) + return 0.409526325277017 * sin(0.0169060504029192 * (T - 80.0856919827619)); } // subfunction to compute Zeitdifferenz // Dauer des halben Tagbogens in Stunden: Zeit von Sonnenaufgang (Hoehe h) bis zum hoechsten Stand im Sueden -float zeitdifferenz(float Deklination, float B) { - - return 12.0*acos((sin(-(50.0/60.0)*PI/180.0) - sin(B)*sin(Deklination)) / (cos(B)*cos(Deklination)))/PI; +float zeitdifferenz(float Deklination, float B) +{ + + return 12.0 * acos((sin(-(50.0 / 60.0) * PI / 180.0) - sin(B) * sin(Deklination)) / (cos(B) * cos(Deklination))) / PI; } // subfunction to compute Zeitgleichung -float zeitgleichung(int T) { - return -0.170869921174742*sin(0.0336997028793971 * T + 0.465419984181394) - 0.129890681040717*sin(0.0178674832556871*T - 0.167936777524864); +float zeitgleichung(int T) +{ + return -0.170869921174742 * sin(0.0336997028793971 * T + 0.465419984181394) - 0.129890681040717 * sin(0.0178674832556871 * T - 0.167936777524864); } // subfunction to compute sunrise -float aufgang(int T, float B) { - float DK = sonnendeklination(T); - return 12 - zeitdifferenz(DK, B) - zeitgleichung(T); +float aufgang(int T, float B) +{ + float DK = sonnendeklination(T); + return 12 - zeitdifferenz(DK, B) - zeitgleichung(T); } // subfunction to compute sunset -float untergang(int T, float B) { - float DK = sonnendeklination(T); - return 12 + zeitdifferenz(DK, B) - zeitgleichung(T); +float untergang(int T, float B) +{ + float DK = sonnendeklination(T); + return 12 + zeitdifferenz(DK, B) - zeitgleichung(T); } -// subfunction to compute it all   +// subfunction to compute it all /*void initsunset(int T) { float Laenge = 10.98; float Breite = 48.25; int Zone = 2; // Unterschied zu UTC-Zeit ( = 2 in der Sommerzeit, 1 in der Winterzeit ) float B = Breite*PI/180.0; // geogr. Breite in Radians - + // Berechnung von Sonnenauf- und -Untergang float Aufgang = aufgang(T, B); // Sonnenaufgang bei 0 Grad Laenge float Untergang = untergang(T, B); // Sonnenuntergang bei 0 Grad Laenge @@ -71,29 +81,31 @@ float untergang(int T, float B) { Serial.print(" Aufgang: ");Serial.print(Aufgang);Serial.print(" Untergang: ");Serial.println(Untergang); } */ -float computeAufgang(int T, float Laenge, float Breite) { - - int Zone = 1; // Unterschied zu UTC-Zeit ( = 2 in der Sommerzeit, 1 in der Winterzeit ) - float B = Breite*PI/180.0; // geogr. Breite in Radians - - // Berechnung von Sonnenaufgang - float Aufgang = aufgang(T, B); // Sonnenaufgang bei 0 Grad Laenge +float computeAufgang(int T, float Laenge, float Breite) +{ - Aufgang = Aufgang - Laenge /15.0 + Zone; // Sonnenaufgang bei gesuchter Laenge und Zeitzone in Stunden - return Aufgang; + int Zone = 1; // Unterschied zu UTC-Zeit ( = 2 in der Sommerzeit, 1 in der Winterzeit ) + float B = Breite * PI / 180.0; // geogr. Breite in Radians + + // Berechnung von Sonnenaufgang + float Aufgang = aufgang(T, B); // Sonnenaufgang bei 0 Grad Laenge + + Aufgang = Aufgang - Laenge / 15.0 + Zone; // Sonnenaufgang bei gesuchter Laenge und Zeitzone in Stunden + return Aufgang; } -float computeUntergang(int T, float Laenge, float Breite) { - - int Zone = 1; // Unterschied zu UTC-Zeit ( = 2 in der Sommerzeit, 1 in der Winterzeit ) - float B = Breite*PI/180.0; // geogr. Breite in Radians - - // Berechnung von Sonnenuntergang +float computeUntergang(int T, float Laenge, float Breite) +{ - float Untergang = untergang(T, B); // Sonnenuntergang bei 0 Grad Laenge + int Zone = 1; // Unterschied zu UTC-Zeit ( = 2 in der Sommerzeit, 1 in der Winterzeit ) + float B = Breite * PI / 180.0; // geogr. Breite in Radians - Untergang = Untergang - Laenge /15.0 + Zone; // Sonnenuntergang bei gesuchter Laenge und Zeitzone in Stunden - return Untergang; + // Berechnung von Sonnenuntergang + + float Untergang = untergang(T, B); // Sonnenuntergang bei 0 Grad Laenge + + Untergang = Untergang - Laenge / 15.0 + Zone; // Sonnenuntergang bei gesuchter Laenge und Zeitzone in Stunden + return Untergang; } //___________________________________________________________end calculate sunrise and sunset @@ -101,152 +113,178 @@ float computeUntergang(int T, float Laenge, float Breite) { //_____________________________________________________________Calculate Day of year /************************************************* Program to calculate day of year from the date - * + * * Enter date (MM/DD/YYYY): 12/30/2006 * Day of year: 364 - * + * ************************************************/ -int caldayofyear(int day,int mon,int year) +int caldayofyear(int day, int mon, int year) { - int days_in_feb = 28; - int doy; // day of year + int days_in_feb = 28; + int doy; // day of year - doy = day; // check for leap year - if( (year % 4 == 0 && year % 100 != 0 ) || (year % 400 == 0) ) + if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) { days_in_feb = 29; } - switch(mon) + switch (mon) { - case 2: - doy += 31; - break; - case 3: - doy += 31+days_in_feb; - break; - case 4: - doy += 31+days_in_feb+31; - break; - case 5: - doy += 31+days_in_feb+31+30; - break; - case 6: - doy += 31+days_in_feb+31+30+31; - break; - case 7: - doy += 31+days_in_feb+31+30+31+30; - break; - case 8: - doy += 31+days_in_feb+31+30+31+30+31; - break; - case 9: - doy += 31+days_in_feb+31+30+31+30+31+31; - break; - case 10: - doy += 31+days_in_feb+31+30+31+30+31+31+30; - break; - case 11: - doy += 31+days_in_feb+31+30+31+30+31+31+30+31; - break; - case 12: - doy += 31+days_in_feb+31+30+31+30+31+31+30+31+30; - break; + case 2: + doy += 31; + break; + case 3: + doy += 31 + days_in_feb; + break; + case 4: + doy += 31 + days_in_feb + 31; + break; + case 5: + doy += 31 + days_in_feb + 31 + 30; + break; + case 6: + doy += 31 + days_in_feb + 31 + 30 + 31; + break; + case 7: + doy += 31 + days_in_feb + 31 + 30 + 31 + 30; + break; + case 8: + doy += 31 + days_in_feb + 31 + 30 + 31 + 30 + 31; + break; + case 9: + doy += 31 + days_in_feb + 31 + 30 + 31 + 30 + 31 + 31; + break; + case 10: + doy += 31 + days_in_feb + 31 + 30 + 31 + 30 + 31 + 31 + 30; + break; + case 11: + doy += 31 + days_in_feb + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31; + break; + case 12: + doy += 31 + days_in_feb + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30; + break; } - - - return doy; // return day of year + return doy; // return day of year } //_________________________________________________________________End calculate day of year - //____________________________________________________________________SetPV flag -// this function calculates start and end of the PV production -// based on sunrise and sunset and a lag factor -bool setPVstartflag(float lagmorning, float lagevening) +// this function calculates start and end of the PV production +// based on sunrise and sunset and a lag factor +bool setPVstartflag(float lagmorning, float lagevening, float laenge, float breite) { -bool pvstartflag=false; -float startpv, stoppv; -float laenge = 9.0658; // Postition of PV -float breite = 48.7990; // Position of PV -float currenttime; // this is the time in decimal hours i.e. 8.5 - - -timeClient.update(); - time_t epochTime = timeClient.getEpochTime(); - float currentHour = timeClient.getHours();// get current hour - float currentMinute = timeClient.getMinutes(); // get current menutes - struct tm *ptm = gmtime ((time_t *)&epochTime); - int monthDay = ptm->tm_mday;// get current day of the month - int currentMonth = ptm->tm_mon+1;//get current month - int currentYear = ptm->tm_year+1900; // get current year - -dayofyear=caldayofyear(monthDay,currentMonth,currentYear);// calculate current day of the year - - startpv=computeAufgang(dayofyear, laenge, breite) + lagmorning; // statring time of pv - stoppv=computeUntergang(dayofyear,laenge,breite)-lagevening; // stop time of PV - -currenttime=currentHour + (currentMinute/60); // calculate current ime in decimal hours - -// figure out wethere pv can produce power or not -// flag pvstartflag is true at daytime when pv can procuce power -if (currenttime>=startpv & currenttime<=stoppv){ - pvstartflag=true; -}else pvstartflag= false; - -//__________________________-Test ausgabe - -Serial.print ("Sonnenaufgang: "); -Serial.println(computeAufgang(dayofyear, laenge, breite)); -Serial.print("Sonnenuntergang: "); -Serial.println(computeUntergang(dayofyear,laenge,breite)); - - -Serial.print("Day of the year: "); -Serial.println (dayofyear); - -Serial.print("Current minute: "); -Serial.println (currentMinute); - - -Serial.print("Current time decimal: "); -Serial.println (currenttime); - -Serial.print("start PV: "); -Serial.println (startpv); - -Serial.print("stoppv PV: "); -Serial.println (stoppv); - -Serial.print("pvstartflag: "); -Serial.println (pvstartflag); - -String currentDate = String(currentYear) + "-" + String(currentMonth) + "-" + String(monthDay); - Serial.print("Current date: "); - Serial.println(currentDate); + bool pvstartflag = false; + timeClient.update(); + time_t epochTime = timeClient.getEpochTime(); + float currentHour = timeClient.getHours(); // get current hour + float currentMinute = timeClient.getMinutes(); // get current menutes + currentDay = timeClient.getDay(); // get current Day 0 Sunday + long day; + struct tm *ptm = gmtime((time_t *)&epochTime); + int monthDay = ptm->tm_mday; // get current day of the month + int currentMonth = ptm->tm_mon + 1; // get current month + int currentYear = ptm->tm_year + 1900; // get current year + + dayofyear = caldayofyear(monthDay, currentMonth, currentYear); // calculate current day of the year + startpv = computeAufgang(dayofyear, laenge, breite) + lagmorning; // statring time of pv + stoppv = computeUntergang(dayofyear, laenge, breite) - lagevening; // stop time of PV + currenttime = currentHour + (currentMinute / 60); // calculate current time in decimal hours + + // figure out wethere pv can produce power or not + // flag pvstartflag is true at daytime when pv can procuce power + if (currenttime >= startpv & currenttime <= stoppv) + { + pvstartflag = true; + } + else + pvstartflag = false; -return pvstartflag; // return pv start produce flag + return pvstartflag; // return pv start produce flag } - -//____________________________________________________________________end day of year - - //________________________________________________START NTP Client // Initialize a NTPClient to get time to calculate sunrise and sunset -void setuptimeClient (){ - // Set offset time in seconds to adjust for your timezone, for example: - // GMT +1 = 3600 - // GMT +8 = 28800 - // GMT -1 = -3600 - // GMT 0 = 0 - timeClient.begin(); - timeClient.setTimeOffset(3600); - +void setuptimeClient() +{ + // Set offset time in seconds to adjust for your timezone, for example: + // GMT +1 = 3600 + // GMT +8 = 28800 + // GMT -1 = -3600 + // GMT 0 = 0 + timeClient.update(); + delay(200); + timeClient.begin(); + delay(200); + timeClient.setTimeOffset(3600); +} +//________________________________________________END NTP client + +float factualtimeinhours() +{ // current time in decimal hours + float currenthour; + timeClient.update(); + // time_t epochTime = timeClient.getEpochTime(); + float currentHour = timeClient.getHours(); // get current hour + float currentMinute = timeClient.getMinutes(); // get current menutes + currenthour = currentHour + (currentMinute / 60); // calculate current time in decimal hours + return currenthour; +} + +void TimeData(struct TimeStruct *s, float lagmorning, float lagevening, float laenge, float breite) +{ + char TempCharMonth[3]; + char TempCharDay[3]; + timeClient.update(); + delay(100); + time_t epochTime = timeClient.getEpochTime(); + time_t epochTimetomorow = timeClient.getEpochTime() + 86400; + + struct tm *ptm = gmtime((time_t *)&epochTime); + int monthDay = ptm->tm_mday; // get current day of the month + int currentMonth = ptm->tm_mon + 1; // get current month + int currentYear = ptm->tm_year + 1900; // get current year + dayofyear = caldayofyear(monthDay, currentMonth, currentYear); // calculate current day of the year + startpv = computeAufgang(dayofyear, laenge, breite) + lagmorning; // statring time of pv + s->sunrise_today = startpv; + // date today + sprintf(TempCharMonth, "%02d", currentMonth); + sprintf(TempCharDay, "%02d", monthDay); + String currentDate = String(currentYear) + TempCharMonth + TempCharDay; + + char *charArray = (char *)malloc((currentDate.length() + 1) * sizeof(char)); + strcpy(charArray, currentDate.c_str()); + s->date_today = charArray; + + // Sunset today with lag + stoppv = computeUntergang(dayofyear, laenge, breite) - lagevening; // stop time of PV + s->sunset_today = stoppv; + + // sunrise tomorow with lag + // time_t epochTimetomorow = timeClient.getEpochTime()+86400;// epoch time 1 day later + struct tm *ptmt = gmtime((time_t *)&epochTimetomorow); + int monthDaytomorow = ptmt->tm_mday; // get current day of the month + int currentMonthtomorow = ptmt->tm_mon + 1; // get current month + int currentYeartomorow = ptmt->tm_year + 1900; // get current year + dayofyearplusone = caldayofyear(monthDaytomorow, currentMonthtomorow, currentYeartomorow); // calculate current day of the year +1 day + startpvtomorow = startpv = computeAufgang(dayofyearplusone, laenge, breite) + lagmorning; // statring time of pv next day + s->sunrise_tomorrow = startpvtomorow; + + // Date tomorow + // time_t epochTime = timeClient.getEpochTime()+86400; + + sprintf(TempCharMonth, "%02d", currentMonthtomorow); + sprintf(TempCharDay, "%02d", monthDaytomorow); + + String currentDatetomorow = String(currentYeartomorow) + TempCharMonth + TempCharDay; + char *charArraytomorow = (char *)malloc((currentDatetomorow.length() + 1) * sizeof(char)); + strcpy(charArraytomorow, currentDatetomorow.c_str()); + s->date_tomorrow = charArraytomorow; + + // day of week as int + s->day_of_week = timeClient.getDay(); } -//________________________________________________END NTP client \ No newline at end of file