I want calculate a battery life from actual (or average consumption after 1minute) and actual SoC.
But not sure how to calculate with data from two sources which are not sync.
Thank you for any idea and help
This site is now in read-only archive mode. Please move all discussion, and create a new account at the new Victron Community site.
I do just that......
I take the current battery SOC and subtract the set minimum SOC and then divide that by the current power (discharging) to arrive at a time the battery is estimated to be flat.
Similarly, you can calculate an estimate for time fully charged.
There was a useful date/time formatter node to add to the pallet to calculate the times. (node-red-contrib-moment2)
Try pasting this to save you some work....
(You probably don't need global variables that I have used in some cases.)
[{"id":"441c6c1cce05ddce","type":"switch","z":"bf1e31f330e69c5c","name":"","property":"payload","propertyType":"msg","rules":[{"t":"lt","v":"-100","vt":"num"},{"t":"btwn","v":"-100","vt":"num","v2":"10","v2t":"num"},{"t":"gt","v":"10","vt":"num"}],"checkall":"true","repair":false,"outputs":3,"x":965,"y":960,"wires":[["d1d3b8bce39a0e3c"],["772d6aa399d12bdb"],["87a61f5ca9c470e2"]]},{"id":"60643f4bafcb4690","type":"change","z":"bf1e31f330e69c5c","name":"< -100 (Discharging)","rules":[{"t":"set","p":"flat-time-mins","pt":"flow","to":"$round(($globalContext('battery-SOC')-$globalContext('battery-min'))*40*60/$flowContext('battery-power'),0)*-1","tot":"jsonata"},{"t":"set","p":"payload","pt":"msg","to":"$millis()+($flowContext('flat-time-mins')*60*1000)","tot":"jsonata"},{"t":"set","p":"copy-to-display-directly--not-used","pt":"msg","to":"\"<font color=yellow>Battery flat around \"&$fromMillis($millis()+($flowContext('Time-estimate')*60*1000),' [h#1]:[m01] [P]', '+1000')","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":1330,"y":915,"wires":[["862d3e2030d077a9"]]},{"id":"fb9f4fc8b608b486","type":"change","z":"bf1e31f330e69c5c","name":"> 10 (Charging)","rules":[{"t":"set","p":"charge-time-mins","pt":"flow","to":"$round((100-$globalContext('battery-SOC'))*40*60/$flowContext('battery-power'),0)","tot":"jsonata"},{"t":"set","p":"payload","pt":"msg","to":"$millis()+($flowContext('charge-time-mins')*60*1000)","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":1310,"y":1005,"wires":[["23169a335dabda99"]]},{"id":"09c287effaba2b7e","type":"change","z":"bf1e31f330e69c5c","name":"-100 to 10 W (Idle)","rules":[{"t":"set","p":"payload","pt":"msg","to":"<font color=grey>=== Battery Idle ===","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":1320,"y":960,"wires":[["70a751144c40ec0c"]]},{"id":"f2bf967b830e18a7","type":"StatusUltimate","z":"bf1e31f330e69c5c","name":"Status","property":"payload","x":1145,"y":840,"wires":[["a8d7f1c490d6db89"]]},{"id":"a8d7f1c490d6db89","type":"change","z":"bf1e31f330e69c5c","name":"set flow.battery-power","rules":[{"t":"set","p":"battery-power","pt":"flow","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":1330,"y":840,"wires":[[]]},{"id":"d1d3b8bce39a0e3c","type":"StatusUltimate","z":"bf1e31f330e69c5c","name":"Status","property":"payload","x":1145,"y":915,"wires":[["60643f4bafcb4690"]]},{"id":"772d6aa399d12bdb","type":"StatusUltimate","z":"bf1e31f330e69c5c","name":"Status","property":"payload","x":1145,"y":960,"wires":[["09c287effaba2b7e"]]},{"id":"87a61f5ca9c470e2","type":"StatusUltimate","z":"bf1e31f330e69c5c","name":"Status","property":"payload","x":1145,"y":1005,"wires":[["fb9f4fc8b608b486"]]},{"id":"862d3e2030d077a9","type":"moment","z":"bf1e31f330e69c5c","name":"","topic":"","input":"","inputType":"msg","inTz":"Africa/Abidjan","adjAmount":0,"adjType":"days","adjDir":"add","format":"[<font color=yellow>Battery flat around ] h:mm a (ddd)","locale":"POSIX","output":"","outputType":"msg","outTz":"Australia/Melbourne","x":1600,"y":915,"wires":[["70a751144c40ec0c","5a6703fd90ea2abf"]]},{"id":"23169a335dabda99","type":"moment","z":"bf1e31f330e69c5c","name":"","topic":"","input":"","inputType":"msg","inTz":"Africa/Abidjan","adjAmount":0,"adjType":"days","adjDir":"add","format":"[<font color=green>Battery full around ] h:mm a (ddd)","locale":"POSIX","output":"","outputType":"msg","outTz":"Australia/Melbourne","x":1600,"y":1005,"wires":[["70a751144c40ec0c","19b1c41801612f0e"]]},{"id":"239ce9df032664ff","type":"smooth","z":"bf1e31f330e69c5c","name":"~ 15 sec average","property":"payload","action":"mean","count":"11","round":"0","mult":"single","reduce":true,"x":750,"y":840,"wires":[["441c6c1cce05ddce","f2bf967b830e18a7"]]},{"id":"72545a6ec8a2a8c5","type":"StatusUltimate","z":"bf1e31f330e69c5c","name":"Status","property":"payload","x":575,"y":840,"wires":[["239ce9df032664ff"]]},{"id":"ad02e7180b796eb7","type":"victron-input-battery","z":"bf1e31f330e69c5c","service":"com.victronenergy.battery.socketcan_can1","path":"/Soc","serviceObj":{"service":"com.victronenergy.battery.socketcan_can1","name":"BYD Premium LV battery","paths":[{"path":"/Dc/0/Voltage","type":"float","name":"Battery voltage (V)"},{"path":"/Dc/0/Current","type":"float","name":"Current (A)"},{"path":"/Soc","type":"float","name":"State of charge (%)"},{"path":"/Dc/0/Temperature","type":"float","name":"Battery temperature (C)"},{"path":"/Alarms/LowVoltage","type":"enum","name":"Low voltage alarm","enum":{"0":"No alarm","2":"Alarm"}},{"path":"/Alarms/HighVoltage","type":"enum","name":"High voltage alarm","enum":{"0":"No alarm","2":"Alarm"}},{"path":"/Alarms/LowTemperature","type":"enum","name":"Low battery temperature alarm","enum":{"0":"No alarm","2":"Alarm"}},{"path":"/Alarms/HighTemperature","type":"enum","name":"High battery temperature alarm","enum":{"0":"No alarm","2":"Alarm"}},{"path":"/Soh","type":"float","name":"State of health (%)"},{"path":"/Info/MaxChargeVoltage","type":"float","name":"CVL - Charge Voltage Limit (V)"},{"path":"/Info/MaxChargeCurrent","type":"float","name":"CCL - Charge Current Limit (A)"},{"path":"/Info/MaxDischargeCurrent","type":"float","name":"DCL - Discharge Current Limit (A)"},{"path":"/Alarms/CellImbalance","type":"enum","name":"Cell Imbalance alarm","enum":{"0":"No alarm","1":"Warning","2":"Alarm"}},{"path":"/Alarms/HighChargeCurrent","type":"enum","name":"High charge current alarm","enum":{"0":"No alarm","1":"Warning","2":"Alarm"}},{"path":"/Alarms/HighDischargeCurrent","type":"enum","name":"High discharge current alarm","enum":{"0":"No alarm","1":"Warning","2":"Alarm"}},{"path":"/Alarms/InternalFailure","type":"enum","name":"Internal error alarm","enum":{"0":"No alarm","1":"Warning","2":"Alarm"}},{"path":"/Alarms/HighChargeTemperature","type":"enum","name":"High charge temperature alarm","enum":{"0":"No alarm","1":"Warning","2":"Alarm"}},{"path":"/Alarms/LowChargeTemperature","type":"enum","name":"Low charge temperature alarm","enum":{"0":"No alarm","1":"Warning","2":"Alarm"}},{"path":"/Dc/0/Power","type":"float","name":"Battery power (W)"}]},"pathObj":{"path":"/Soc","type":"float","name":"State of charge (%)"},"name":"","x":170,"y":705,"wires":[["09dc839d87f22b25"]]},{"id":"09dc839d87f22b25","type":"rbe","z":"bf1e31f330e69c5c","name":"Block unless value changes","func":"rbe","gap":"","start":"","inout":"out","septopics":false,"property":"payload","topi":"topic","x":540,"y":705,"wires":[["0e5468367619f8e3"]]},{"id":"0e5468367619f8e3","type":"StatusUltimate","z":"bf1e31f330e69c5c","name":"Status","property":"payload","x":845,"y":705,"wires":[["b903bc215cbd7a69"]]},{"id":"b903bc215cbd7a69","type":"change","z":"bf1e31f330e69c5c","name":"set global.battery-SOC","rules":[{"t":"set","p":"battery-SOC","pt":"global","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":1060,"y":705,"wires":[["c4bad64373a5433f"]]},{"id":"c4bad64373a5433f","type":"change","z":"bf1e31f330e69c5c","name":"set topic: Battery SOC %","rules":[{"t":"set","p":"topic","pt":"msg","to":"Battery SOC %","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":1310,"y":705,"wires":[[]]},{"id":"0a90f2a7c0f5e204","type":"victron-input-battery","z":"bf1e31f330e69c5c","service":"com.victronenergy.battery.socketcan_can1","path":"/Dc/0/Power","serviceObj":{"service":"com.victronenergy.battery.socketcan_can1","name":"BYD Premium LV battery","paths":[{"path":"/Dc/0/Voltage","type":"float","name":"Battery voltage (V)"},{"path":"/Dc/0/Current","type":"float","name":"Current (A)"},{"path":"/Soc","type":"float","name":"State of charge (%)"},{"path":"/Dc/0/Temperature","type":"float","name":"Battery temperature (C)"},{"path":"/Alarms/LowVoltage","type":"enum","name":"Low voltage alarm","enum":{"0":"No alarm","2":"Alarm"}},{"path":"/Alarms/HighVoltage","type":"enum","name":"High voltage alarm","enum":{"0":"No alarm","2":"Alarm"}},{"path":"/Alarms/LowTemperature","type":"enum","name":"Low battery temperature alarm","enum":{"0":"No alarm","2":"Alarm"}},{"path":"/Alarms/HighTemperature","type":"enum","name":"High battery temperature alarm","enum":{"0":"No alarm","2":"Alarm"}},{"path":"/Soh","type":"float","name":"State of health (%)"},{"path":"/Info/MaxChargeVoltage","type":"float","name":"CVL - Charge Voltage Limit (V)"},{"path":"/Info/MaxChargeCurrent","type":"float","name":"CCL - Charge Current Limit (A)"},{"path":"/Info/MaxDischargeCurrent","type":"float","name":"DCL - Discharge Current Limit (A)"},{"path":"/Alarms/CellImbalance","type":"enum","name":"Cell Imbalance alarm","enum":{"0":"No alarm","1":"Warning","2":"Alarm"}},{"path":"/Alarms/HighChargeCurrent","type":"enum","name":"High charge current alarm","enum":{"0":"No alarm","1":"Warning","2":"Alarm"}},{"path":"/Alarms/HighDischargeCurrent","type":"enum","name":"High discharge current alarm","enum":{"0":"No alarm","1":"Warning","2":"Alarm"}},{"path":"/Alarms/InternalFailure","type":"enum","name":"Internal error alarm","enum":{"0":"No alarm","1":"Warning","2":"Alarm"}},{"path":"/Alarms/HighChargeTemperature","type":"enum","name":"High charge temperature alarm","enum":{"0":"No alarm","1":"Warning","2":"Alarm"}},{"path":"/Alarms/LowChargeTemperature","type":"enum","name":"Low charge temperature alarm","enum":{"0":"No alarm","1":"Warning","2":"Alarm"}},{"path":"/Dc/0/Power","type":"float","name":"Battery power (W)"}]},"pathObj":{"path":"/Dc/0/Power","type":"float","name":"Battery power (W)"},"name":"","x":170,"y":840,"wires":[["72545a6ec8a2a8c5"]]},{"id":"70a751144c40ec0c","type":"ui_text","z":"bf1e31f330e69c5c","group":"bba5452f.7c7ed","order":11,"width":7,"height":1,"name":"Time till flat or charged","label":"","format":"{ {msg.payload}}","layout":"row-center","x":1870,"y":960,"wires":[]},{"id":"5a6703fd90ea2abf","type":"StatusUltimate","z":"bf1e31f330e69c5c","name":"Status","property":"payload","x":1865,"y":915,"wires":[[]]},{"id":"19b1c41801612f0e","type":"StatusUltimate","z":"bf1e31f330e69c5c","name":"Status","property":"payload","x":1865,"y":1005,"wires":[[]]},{"id":"bba5452f.7c7ed","type":"ui_group","name":"Battery","tab":"263714fe.0cdaa4","order":5,"disp":false,"width":"15","collapse":false},{"id":"263714fe.0cdaa4","type":"ui_tab","name":"Solar Status","icon":"battery_charging_full","order":1,"disabled":false,"hidden":false}]
Great project, following with interest, happy to help with any testing ... thanks
Was exactly one of the first things I did for the liontron batteries that do not expose this values via can bus.
At first I set the soc as a global variable out of a
Venus System - Battery State of Charge (%)
Node with a function node with code:
global.set('soc', msg.payload) return msg;
Then I use as input the
Venus System - Battery Power (W)
Node and a function node with this inside:
soc=global.get('soc'); watts=msg.payload; capacity=51.2*(105+104+102+104); # Nominal Power of the Liontron Multiplied by the Ah sum of Capacity of the 4 Modules gives you the capacity in Watt Hours. remain=soc/100*capacity; rest=capacity-remain; if (watts !=0 ) { if (watts <0) { timetogo=remain/watts*-3600; left=remain; } else { timetogo=rest/watts*3600; left=rest; } } else { timetogo=864000; left=rest; } // Hours var Hours = ((timetogo)/3600); Hours = Math.floor(Hours); // Minutes var Minutes = (timetogo-(Hours*3600))/60; Minutes = Math.floor(Minutes); // Concatenate var Time = ('0' +Hours).slice(-2)+':'+('0' +Minutes).slice(-2); global.set('timetogo', timetogo); global.set('watts', watts); msg.payload=Time; msg.soc=soc; msg.watts=watts; msg.capacity=capacity; msg.remain=remain; msg.rest=rest; msg.timetogo=timetogo; msg.hours=Hours; msg.minutes=Minutes; msg.left=left; return msg;
As output you then have a msg object that has almost all necessary inside.
If you also want to subtract the set minimum soc to keep you can pick that also up by setting it as a global var and use it then by loading it into the function.
Hopefully that helps.
Kind regards,
Dierk
It's worth taking into account the efficiency of the inverter. I have a function that returns the 'assumed' efficiency based on the power. For my quattro 10k . At 1kW its maximum of 95% and then it linearly decays to 90% or less ( I forget the exact figures) at 8kW. Multiply the time to go by the calculated efficiency.
33 People are following this question.