Skip to content

Commit

Permalink
Merge pull request #17 from gropi75/BalancedLoad
Browse files Browse the repository at this point in the history
Balanced load
  • Loading branch information
gropi75 authored Mar 19, 2023
2 parents 84ff0b9 + d73ad05 commit 02ead7a
Show file tree
Hide file tree
Showing 9 changed files with 545 additions and 319 deletions.
10 changes: 10 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -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
1 change: 0 additions & 1 deletion .pio/build/esp32dev/tmpahxafcje.tmp

This file was deleted.

268 changes: 125 additions & 143 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,147 +1,129 @@
# 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
# 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)

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-
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.

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
# Main features:
- 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
- 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
- **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)
- **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:**

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-

**6 pin connector:**

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$
7 changes: 7 additions & 0 deletions lib/PowerFunctions.h
Original file line number Diff line number Diff line change
Expand Up @@ -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]);

22 changes: 22 additions & 0 deletions lib/secrets_dummy.h
Original file line number Diff line number Diff line change
@@ -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
34 changes: 33 additions & 1 deletion lib/sunrise.h
Original file line number Diff line number Diff line change
@@ -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 ();
Expand All @@ -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
Loading

0 comments on commit 02ead7a

Please sign in to comment.