![]() |
rasProject_01 / weSweetHome
R. 146 2026-09-26
process control / RasPi software by weinert-automation
|
Common types and values for buffer battery handling. More...
#include "basicTyCo.h"Macros | |
| #define | BAT_BAL_STRT_PWM |
| Start value for ballast loading (LiFePo4). | |
| #define | BAT_KEEP_PWM |
| Battery keep alive PWM setting (LiFePo4). | |
| #define | BAT_LDBAL_STR_PWM |
| PWM start value for ballast loading. | |
| #define | BAT_LDBAL_TIM |
| Maximum time for battery loading as ballast. | |
| #define | BAT_LDMX_PWM |
| Battery maximum load PWM setting (LiFePo4). | |
| #define | BAT_LOAD_PWM |
| Value for permanent loading. | |
| #define | BAT_LOD_END_MAX_POW |
| Battery controlled load end phase maximum power. | |
| #define | BAT_LOD_END_MIN_POW |
| Battery controlled load end phase minimum power. | |
| #define | BAT_LOD_NRM_MAX_POW |
| Battery controlled load maximum power. | |
| #define | BAT_LOD_NRM_MIN_POW |
| Battery controlled load maximum power. | |
| #define | BAT_NOLD_PWM |
| Battery no load no keep setting (LiFePo4). | |
| #define | BAT_SOC_UP_LIM_LOAD |
| Upper SoC (state of charge float) limit to stop loading. | |
| #define | BAT_TNUM |
| Battery type number. | |
| #define | BAT_TYPE |
| Battery type. | |
| #define | BATkeepInhByCmd |
| Inhibit battery keep loading after battery Off command. | |
| #define | BATkeepInhContLoad |
| Inhibit battery keep loading after controlled loading. | |
| #define | BATkeepInhUnload |
| Inhibit battery keep loading after unloading. | |
| #define | BATmaxUNLODtime |
| Upper time limit to stop discharging (LiFePo4). | |
| #define | BATSOC_LO_LINT_UNLD |
| SoC (state of charge integer) limit to start unload. | |
| #define | BATSOC_LO_STP_UNLD |
| Lower SoC (state of charge integer) limit to stop discharging. | |
| #define | BATVOLT_LO_LIM_UNLD |
| Voltage limit to start unload. | |
| #define | BATVOLT_LO_STP_UNLD |
| Lower voltage limit to stop discharging. | |
| #define | BATVOLT_UP_LIM_LOAD |
| Upper voltage limit to stop loading. | |
| #define | currSOC |
| The actual state of charge (SoC). | |
| #define | ESP_U_CORR |
| Correction factor for ESP battery voltmeter. | |
| #define | PDEL_MINP_UNL |
| Minimum power from public electricity supplier to start discharging. | |
| #define | PDEL_STOP_UNL |
| Minimum power from public electricity to stop discharging. | |
| #define | PINV_ON_CRIT |
| Minimum discharge power to consider discharge inverter on. | |
| #define | SOCinvalid |
| State of charge (SoC) is invalid. | |
| #define | SOCvalid |
| State of charge (SoC) is valid. | |
Functions | |
| unsigned int | unldAllowed () |
| Is battery unload allowed by battery state. | |
Variables | |
| uint16_t | hundredsV |
| The battery voltage in 0.01V units. | |
| uint16_t | tenPromSoC |
| The battery state of charge or SOC in 0.01% units. | |
Common types and values for buffer battery handling.
Revision history
In the smart home buffer batteries are used and managed since 2019.
Until August 2022, we had an array of parallel 12V (6 cell) lead acid batteries. The used batteries were donated to the project as becoming unfit for their former use in glider starting winches. Nominally, more than 200Ah should allow buffering 1 kWh. The usable capacity was far below, due to the batteries age and principal limits of lead acid accumulators as buffers.
Hence, all lead acid batteries were replaced by one 12,8V 100Ah ECO-WORTHY LiFePo4 accumulator. In consequence, all loading, keeping and unloading constants and procedures had to be changed. After good experiences with the type and reduction of prices, two more were added in February and November
From start of the project battery voltage is measured at the battery clamps by a special ESP 32 based MQTT device (see also files mqttHome.h and sweetHome2.c). It uses WLAN and has a 12V supply and just "lives" directly on the batteries. Besides an own fuse it needs no extra hardware.
The idle voltage accuracy was more than sufficient, but the battery's (and fuse holder's) clamp voltage has significant variations due to current (range > +/-30A). Additionally there are delays from current to voltage changes. Getting a reliable value for SoC (state of charge) by idle Ubat is hardly feasible as 1% delta SoC is about 20mV delta U.
The battery management and protection system, of course, monitors internally every cell voltage and "knows" voltages, SoC and more accurately. Additionally, it will switch off loading or unloading in cases of over-current, over-voltage and under-voltage. Fortunately, the battery last purchased publishes all relevant and accurate internal values as well as the state of the load and unload protection switches by Bluetooth.
In August 2026 we made an M5Stamp ESP32S3 get those values and deliver them to the same MQTT server in a compatible (payload) format. If available the "Bluetooth" voltage and SoC take precedence over the ADU voltage and the SoC(U) look-up.
| #define BAT_TNUM |
Battery type number.
The battery type as integer number corresponding to the text, see BAT_TYPE.
LiFePo4, 12.8V, has number 2 and LeadAcid, 12V, is type 1.
LeadAcid batteries were dumped as not fit for PV buffering. Hence, type 1 isn't implemented any more.
| #define PDEL_MINP_UNL |
Minimum power from public electricity supplier to start discharging.
If public power consumption is below this limit battery unloading shall not be started respectively inhibited. The current value is 300 W.
Rationale: Battery unload power is above 200 W and has no fine grained control. When exceeding the consumption unloading would be turned off. We won't use battery power to heat domestic hot water.
Used in: batUnloadStatChg
| #define PINV_ON_CRIT |
Minimum discharge power to consider discharge inverter on.
As we use one DC input of a solar inverter (and a step up converter) for discharging the AC power flow to may start with up to 10 minutes delay. The measured discharge power > PINV_ON_CRIT is used as criterion for having started.
The delay is a special German feature: When a sleeping inverter is woken up by seeing DC power it must make long AV voltage and frequency considerations according to VDE-AR-N 4105 or similar standards. When changing the same inverter's setting from Germany to Poland (e.g.) the AC power delivery would start immediately. Consider the electric energy gain at every sunrise or tearing of clouds.
The current value is 53W (could be up to 200W).
Used in: batUnloadStatChg
| #define PDEL_STOP_UNL |
Minimum power from public electricity to stop discharging.
We inhibit all power delivery to the public grid. Especially we do not discharge the batteries when not consuming all battery power. As we can't control discharge power and re-starting discharge takes long (thanks to VDE-AR-N 4105, a German "unique selling point") we allow very low negative power hardly / not fully measured by Ferraris counters biased to start on minimal positive values.
Used in: batUnloadStatChg
| #define ESP_U_CORR |
Correction factor for ESP battery voltmeter.
Due to tolerances the value delivered via MQTT is a bit too low. This factor is a good average correction and may be put into the ESP voltmeter code some day.
On the other hand changing this factor on Pi C Eclipse ... environment is loads more easy and less (hardware) error prone than handling an ESP.
| #define BAT_TYPE |
Battery type.
The battery type as text, like LiFePo4 or LeadAcid.
As C's macro handling is too stupid to compare strings we have a co-responding integer type number BAT_TNUM 2.
| #define BATmaxUNLODtime |
Upper time limit to stop discharging (LiFePo4).
The normal discharge end condition in the unload SFC would be state of charge (SoC BATSOC_LO_STP_UNLD) battery or voltage (BATVOLT_LO_STP_UNLD). And there is this time limit of currently 10h.
With lead acid accumulators, it was much lower. Currently we have 3 * 100 aH * 12V LiFePo4 batteries. For currently 300 W discharging from 90 to 10% (SoC) 9h. 10h should be quite save if other end criteria fail.
Via Bluetooth one of the batteries gives precise SoC values an other experiments show the behaviour of the three parallel batteries being the same. Additionally all have a battery management and protection system with switches to turn off over and under charging. Hence, this end time feature
| #define BATkeepInhUnload |
Inhibit battery keep loading after unloading.
Start battery keeping immediately after unloading would most probably be unnecessary charging as we are on the discharge curve. As we have ample reserve we may consider the base load 10..20W as mildly unloading. The current value is 3 hours.
Hint: The "inhibit keep timer" starts battery keeping (startBatteryKeep) when running out.
| #define BATkeepInhContLoad |
Inhibit battery keep loading after controlled loading.
The current value is 30 minutes.
Used in: batCntLodStatChg
| #define BATkeepInhByCmd |
Inhibit battery keep loading after battery Off command.
The current value is 10 minutes from now. If the inhibit timer is running already its end time will eventually be prolonged but not shortened.
Used in: stopBatteryOps
| #define BATVOLT_LO_LIM_UNLD |
Voltage limit to start unload.
This is the minimal voltage to allow starting an unload sequence.
Current value 13.120 V.
Used in: batUnloadStatChg and before starting unload in timers befRiseTimChg, sunsetTimChg and duskTimChg
| #define BATSOC_LO_LINT_UNLD |
SoC (state of charge integer) limit to start unload.
This is the minimal SoC to allow starting an unload sequence.
Current value 34%.
Used in: batUnloadStatChg and before starting unload in timers befRiseTimChg, sunsetTimChg and duskTimChg
| #define BATSOC_LO_STP_UNLD |
Lower SoC (state of charge integer) limit to stop discharging.
This is the minimal SoC to stop a running unload (SFC) for providing buffer capacity needed.
This is a critical value. Choosing a value too high reduces the usable buffer capacity (the battery's purpose in life). A value too low endangers the battery respectively if needed a minimal DC power reserve.
To allow for permanent loads without being forced to load within the next 24 hours we intend to stop in the range 30..20%.
The current value is 33%.
Note: 30% seemed too low after consecutive dark days. To avoid loading from public grid higher values seem indicated, best conditionally. Conditions may be past sunshine, weather forecast (no reliable dervice free of charge) or just time of the year.
For the Web interface and this limit ::valFilVal.by[11] is used as unsigned integer in the range of 0..100%; it is set to 120 (>100) to indicate that no valid ("young") value is available. In the case of invalid SoC only the voltage and its limits BATVOLT_LO_STP_UNLD and :: BATVOLT_LO_LIM_UNLD are used.
Used in: batCntBalStatChg batUnloadStatChg
| #define SOCvalid |
State of charge (SoC) is valid.
| #define currSOC |
The actual state of charge (SoC).
| #define BATVOLT_LO_STP_UNLD |
Lower voltage limit to stop discharging.
This is the minimal voltage, measured under 5..10% cap unload, to stop a running unload sequence for providing buffer capacity needed.
This is a critical value. Choosing a value too high reduces the usable buffer capacity (the battery's purpose in life). A value too low endangers the battery.
To allow for permanent loads without being forced to load within the next 24 hours we intend to stop in the range 30..20%.
The current value is 12.00V under discharging load which then quickly recovers to our aim 12.31V (~10% on "book's" idle curve).
Used in: batCntBalStatChg batUnloadStatChg
| #define BAT_LDBAL_TIM |
Maximum time for battery loading as ballast.
This time limit is the last resort to stop overloading as ballast for surplus power. The current value is 13 hours.
This feature is not necessary as the LiPoFe batteries protect themselves against over charging and the current loading module max. voltage of 14.75V (+ 0.4V for the Schottky diodes 15.15V) is within the limits.
Used in: batCntBalStatChg
| #define BAT_LDBAL_STR_PWM |
PWM start value for ballast loading.
The current value is 135 (pwm = 13.88V) to have a quick start.
Used in: batCntBalStatChg
| #define BAT_NOLD_PWM |
Battery no load no keep setting (LiFePo4).
This is the PWM setting for neither charging nor keeping. Until August 2024 it was 0 for the array of old lead acid starter batteries.
"LiFePO4 battery cells have a maximum discharge depth of 98% to 100%. This is longer than any other battery technology currently in the market. This means that you can safely discharge these batteries to their full capacity. However, most manufacturers recommend still using a 80% depth of discharge for these batteries to prolong their lifespan. Even if you occasionally use 100% of the battery capacity, the battery will not get harmed." cited from [https://ecotreelithium.co.uk/news/lifepo4-battery-depth-of-discharge/]
For neither keeping or loading we permanently back the battery with 12.5V (+0.4V on no current) to keep about 10%. The relation between BATVOLT_LO_STP_UNLD and BAT_NOLD_PWM shall not lead to start keeping immediately after unloading. Current value 37.
Used in: switchBatToStepUp changeBatLoadPWM
| #define BATVOLT_UP_LIM_LOAD |
Upper voltage limit to stop loading.
The battery loading SFCs would stop when this voltage is reached.
Full loading would require 14.6 V and for safety reasons one should be more below, perhaps. 14.88V is over-charge protection and 14.4V is the cell equalising start voltage. On the other hand EcoWorth's LiFePo4 12V 100Ah has a built in battery management system (BSM), which would cut of at over-voltage.
| #define BAT_SOC_UP_LIM_LOAD |
Upper SoC (state of charge float) limit to stop loading.
The battery loading SFCs would stop when state of charge (SoC) by Bluetooth for one of the batteries is valid and if this upper limit reached. For the Web interface ::valFilVal.by[11] (or currSOC) is used as unsigned integer in the range of 0..100; it is set to 120% (>100) to indicate that no valid (not too old) value is available.
| #define BAT_KEEP_PWM |
Battery keep alive PWM setting (LiFePo4).
This is the PWM setting for the battery load module for permanently keeping the battery at live by preventing self discharge and by feeding the (low) permanent loads. The value is 45.
| #define BAT_LDMX_PWM |
Battery maximum load PWM setting (LiFePo4).
N.b.: The value 14.6V is the value for full loading. Without load current the voltage will rise by the 0.4V drop of the (parallel) Schottky diodes. Hence monitoring BATVOLT_UP_LIM_LOAD and/or BAT_SOC_UP_LIM_LOAD is essential.
Current value 235 (= 14.6V).
| #define BAT_BAL_STRT_PWM |
Start value for ballast loading (LiFePo4).
The value is 81 (= 13.37V).
| #define BAT_LOAD_PWM |
Value for permanent loading.
The value is 48.
| #define BAT_LOD_NRM_MAX_POW |
Battery controlled load maximum power.
For controlled (resp. ordered unconditional) battery charging this value is the maximum power. If higher the output of the charging module will be reduced.
This condition can be checked when an actual charging power measurement is available. As water heating and battery charging use the same power meter heating would spoil the value; see batLoadPowValid.
The current value is 144.4 W.
| #define BAT_LOD_NRM_MIN_POW |
Battery controlled load maximum power.
For controlled (resp. ordered unconditional) battery charging this value is the minimum power; see BAT_LOD_NRM_MAX_POW.
The current value is 84.4 W.
| #define BAT_LOD_END_MAX_POW |
Battery controlled load end phase maximum power.
When the end criteria for controlled load are reached a low charging power end or keep fresh phase is entered.
Note: This feature is inherited from the quite complex handling of lead acid accumulator and may be removed.
The current value is 68.4 W.
| #define BAT_LOD_END_MIN_POW |
Battery controlled load end phase minimum power.
The current value is 31.4 W.
| unsigned int unldAllowed | ( | ) |
Is battery unload allowed by battery state.
If state of charge or battery voltage prohibit discharging 0 (FALSE) will be returned.
|
extern |
The battery voltage in 0.01V units.
This is just an integer value consistent to the last valid battery voltage measurement valFilVal.batVolt. Contrary to valFilVal.batVolt which is set to -0.9 to indicate invalidity after 2.4s without new (MQTT) measurements, this integer value will be kept "forever".
It is preset with 1289 (12.89 V) to avoid "battery low" status before the first valid MQTT measurement / message.
Receiving a good MQTT message from the battery voltmeter will set valFilVal.batVolt, batVoltValid and this value.
Use
to format as "12.89" without trailing zero.
|
extern |
The battery state of charge or SOC in 0.01% units.
This the state of charge of (one of the) ECOworthy batteries in units of 0.01% or 10 per mille as published by Bluetooth. A value of 2468 would mean a SoC of 24.68% and for a 100Ah battery also a charge of 24.68Wh.
If no Bluetooth data of (at least) one of the three batteries connected in parallel are available the SoC will be looked up by SoC(U) table.
Use
to format as "24.68" without trailing zero.