Input/Feed processing for battery remaining capacity


From my Solax inverter I can read the battery % remaining and also the power flowing to/from the battery. The battery % alone gives power available to approx 0.1kWh (~10kWh system), but it would be nice to get a bit more accuracy if possible.

I can turn the power to/from battery to a kWh figure using a ‘Power to kWh’ conversion, which gives a more precise figure for power in the battery, but that figure drifts over a few days due to power losses (you don’t get back quite as much as you put in).

What I’d like to do is combine the two - have a feed for ‘power left in battery’ - maybe in Wh so it can be more accurate. When the battery percentage changes (say from 22% to 23%), set the feed to the known value of battery remaining (2300Wh in this case). Then while the battery percent sits at 23%, use the ‘battery power (W) + Power to kWh’ to track the fine changes in battery level until the next change in percentage happens and corrects any drift.

Right now, I can’t see a way to do this in feed/input processing, and I’m wondering if there is something I am missing. If it’s not possible I can probably hack it together in my python data input script, but I was hoping to avoid that and keep the data input simple.

Any ideas?



You say you can read the battery % (also called the SOC - state of charge - how full the battery is) ?
Why not just store that?
You will never be able to calculate the SOC from the power going in/out of the battery.
There’s a thing called “Round Trip Efficiency”, this is the how efficient the inverter is at converting AC to DC, how efficient the battery is at storing the electricity and getting it out again, and how how efficient the inverter is at converting DC back to AC.
The problem is the RTE changes depending on the charge/discharge rate, temperature, how old the batteries are, etc. It could be as good as 95% (i.e you put 1000W in and get 950W back out), or as low as 80% (1000W in, 800W out).
If you know your battery is 10kWh, and it’s 60% SOC (60% full), then you have 10 * 0.6 = 6kWh left in the battery (subject to RTE).
Monitoring the input/output is nice, but it’s got very little to do with the SOC.


yes, currently I am using the SOC as it comes from the system, but it’s mildly annoying because the system runs from 10% to 100% charge - the bottom 10% is reserved and never used. That’s really good from a battery health point of view, but from a display point of view you really want to know how much battery is left to use - who cares about the 10% reserved bit… So, to do that I take the value from the system, subtract 10 and multiply by 1.11 to go into the feed. That gives me a value from 0 to 100, which is more human friendly, but at certain points it jumps (ie from 17 to 19) due to rounding after the multiplication by 1.11. Those sort of effects become even worse if you start thinking in terms of using the backup power setting, which can reserve a further % of the battery for use in power cuts…

So, being a bit of a perfectionist, I’m trying to work out an improved way to get the battery readout so it doesn’t jump. I do understand that the round trip is not 100% efficient due to both losses in the battery and losses in the charger/inverter processes, but honestly that doesn’t matter massively… If I can make a composite SOC readout that changes 17, 17.1, 17.2, 17.3, etc, it doesn’t matter nearly as much if it jumps from 18.8 to 19 as it does when the raw SOC goes from 17 to 19 - sure, it’s not 100% accurate, but it’s better.

Anyway, cheers for answering - I guess I’m going to be doing this the python way.


I do exactly the same formula, implemented with a virtual feed. This gives me a floating point result, exactly as you’re after. I’d expect that using an input process would work the same. I can’t understand why you’re getting rounding after the multiplication…


I have a Powervault battery and wanted to use the emoncms My Solar Battery app but needed a SOC percentage which I can’t get.

So I created a couple of feeds on the battery:

  1. How much power goes in?
  2. how much comes out? (The average of a few full to empty constant discharges)

I learned that for my 8kWh battery it will discharge about 7.2.
It uses about 50W when doing nothing.

My input processing is a bit horrendous and definitely has some redundant steps but summarises to something like this:

Reset to original.
If >=50, subtract 50.
If positive, multiply by 0.77 (because only about 77% of what goes in comes out).
Log to %age W & kWh feeds.
Reset to zero, add 13.889.
Multiply by %age kWh feed.
Log to SOC feed.

The %age kWh feed now contains the number you are after, in my case usually something between 0 and 7.2. I also have a usable SOC from which the My Solar App can derive remaining time left. It’s all much more accurate than the Powervault app!

The thing is, you need a few extra steps to do it right, because the battery doesn’t always use exactly 50W etc., so you have to stop the %age kWh feed from going below zero or over 7.2:

Reset to zero, add feed %age kWh.
If < 0, set to zero, log to %age kWh feed.
If > 7.2, set to 7.2, log to %age kWh feed.

Because I refuse to use GOTO, the above 3 statements take 13 steps.

I’m going to have to redo some of the numbers soon as we have 4kWh more batteries coming on Friday for installation next week!


I’m surprised that works for any length of time!

It’s surprisingly accurate!

1 Like

Hi folks, thanks for the suggestions!

I hadn’t done anything with virtual feeds so far in emoncms, so I will investigate those to see what I can gain that way. I think I probably just dismissed them as ‘complex stuff I didn’t seem to need’ when setting up the system, so good to have a reminder to revisit them.

I’m going to have to read through Christian’s response a few times to make sure I understand what is going on :slight_smile: It’s certainly the sort of thing I’m trying to build I think. When thinking about this I realised that if I add an input that is the difference between the current SOC% readout for the inverter and the previous one then I can have all sorts of ‘if <0’ or ‘if >0’ conditions in the processing, which might let me do what I want with most of the processing in emoncms rather than in python.

I did find a ‘remaining dischargeable capacity in Wh’ value on the modbus output of the inverter. Looked promising, but turns out that it goes up and down in steps of 116Wh, which is exactly 1% of system capacity :frowning:



I think you need to overcome the fear you have of 1% steps in the SOC.
If you can query the actual batteries (like I can with my PylonTechs) you’ll find they are all over the place, some higher, some lower. The SOC from the inverter is nice massaged/averaged figure for human consumption. There’s no point in giving it to you with 3 decimal places as it’s a mess of averages & guesswork. :man_shrugging:

When I said it was surprisingly accurate, several nights recently the My Solar App has given Battery Time Left values that means it will run out between midnight and 00:30 and on these occasions that has been what happened, within minutes of the battery giving up.

Unless your consumption is very, very flat, it’s all a bit academic and reasonable accuracy is enough.

LOL. I prefer to just ask the inverter for the SOC and get an answer without all the maths.
But excellent work on getting an accurate solution! :+1:

Thanks; I’d prefer to call an API too but Powervault say it’s not public and I can’t be bothered to reverse engineer it and keep up with changes.

1 Like

Hi folks,

sorry for taking so long to report back - I have been busy with some other things and not had time to investigate this properly until now.

With some tinkering I have managed to do all the processing I needed inside emoncms, as follows:

Inputs (both from inverter data)

  • DC Power flow from battery (+ve discharge) in W
  • Remaining power left in battery - integer readout measured in 0.1kWh


DC Power

  • Power to kWh → feed (‘frombat_dc_kwh’)

Remaining power left in battery

  • Log to feed ‘battpowerleft’
  • rate of change (logged to 'powerleft_rate)
  • if > -1 skip next
  • Absolute Value = 1
  • multiply by feed ‘frombat_dc_kwh’
  • if ZERO skip next
  • Log to feed ‘frombat_dc_kwh_ref’

New virtual feed ‘Battery Capacity Remaining’

  • source feed ‘battpowerleft’
  • multiply by 0.1
  • add source feed ‘frombat_dc_kwh_ref’
  • subtract source feed ‘frombat_dc_kwh’

Ok, how does it work?

The DC power from batter converted to kWh allows me to keep a fine track of power flow to/from the battery, but will tend to drift due to losses, etc.

Every time the remaining power left in battery value from the BMS changes (equally, the pecentage left would do here), the rate calculation is not the normal value of zero, instead it is -1 or +1 ( assuming no jumps of more than 1 unit).

If the rate calculation is negative, the combination of ‘if > -1 skip next’ and ‘abs value 1’ sets it to 1 - that means the value is then zero for no change and 1 for the battery power left just changed.

Multiply that by the latest ‘frombat_dc_kwh’ figure, means that the value being processed is either zero if the battery level has not changed, or the latest accumulated kwh value if it has changed. Then we only log to the ref feed if non-zero.

That way we have two feeds - frombat_dc_kwh which is the accumulated power flow to/from the battery, and ‘frombat_dc_kwh_ref’, which is the value of that feed when the battery power level last changed. The difference between the two is the power into (or out of) the battery since the battery power level last changed, so the virtual feed can combine the 3 values to give a more exact estimate of the power in the battery.

I would like to do the rate of change calculation without having to log to a feed, but I can’t see a way to do that (and I also can’t seem to use a memory feed for the rate).

I will also try to tinker with the virtual feed to see if I can limit the offset to between -0.1 and +0.1 kWh, but that’s just fine tuning.



1 Like

Just to follow up now I’ve had time to let this run for a bit…

Works well at generating reasonable values for battery capacity between the step points where the reported capacity changes. The light blue is the graph of the readout from the BMS and the yellow is my calculated remaining capacity.

The virtual feed calculates the correct instantaneous values, but doesn’t graph nicely - I think it is because the reference kwh value is only stored every few minutes and when the virtual feed is calculated it interpolates between the stored values, rather than taking the previous one. A real feed with the same calculation works fine as shown in the graph above (hope it shows up).

Next step - tweak my customized version of ‘MySolarBattery’ app to work using this data rather than battery %



1 Like