Monitoring the current charge level of a battery is an essential element when camping and living self-sufficiently. Especially when using Lifepo4 batteries, where you only get very inaccurate results from the battery voltage, you need to use a better method.
Measuring voltage vs. current
1. Measure the voltage.
This method is very simple and therefore not very precise. The current state of the battery is calculated using the battery voltage. This is possible because it decreases with the charge level. This is still fairly accurate for an AGM/lead-gel battery, as you can speak of an almost linear decrease here, but it is hardly applicable to a LiFePO4 battery, as the voltage remains very stable and only drops sharply at the end.
2. Counting the current.
The capacity is given in ampere hours Ah or watt hours Wh. Let's take a 100Ah LiFePO4 battery as an example, it can deliver 100A for one hour or 1A for 100 hours. We now need the option to monitor the outgoing and incoming currents of the battery and count them over time. This function is already integrated in many (necessary) battery management systems for LiFePO4 batteries and we can find out the state of charge, often SOC (State of Charge). The various manufacturers provide apps or interfaces for this. In our VAN PI system, Daly/JBD - Xiaoxing/Liontron are currently supported via cable or Bluetooth. Another method of monitoring the current is a shunt. This is a calibrated "resistance" - or rather an area in the circuit - where we can calculate the current using the resulting voltage drop. Such shunts have a typical voltage drop of 75mV for a certain current such as 100A. This voltage drop is linear and we can therefore calculate and monitor the currents precisely.
Example invoice shunt
So we now know that a shunt is a calibrated low-ohm resistor in the circuit across which we measure the voltage drop in order to calculate the current.
For the calculation we use Ohm’s law: U=R*I
We have a consumer and our shunt in the circuit. Measurable voltages are now dropping across both. All we need to do now is measure the voltage drop across the shunt. Once we have this value, we can easily calculate the current by simply looking for I change .
I=U/R
and
R=U/I
so R=0.000375Ohm (0.075V/200A) for our 200A shunt.
This means we can calculate the current at any time as soon as we can measure the voltage drop.
Measuring the voltage drop
To measure the voltage drop of the shunt, we use an analog-digital converter with a resolution of 16 bits. The ADS1115 is integrated via the I2C bus and continuously measures the voltage drop.
If you are interested in more information and would like to build something yourself, you will find a very good explanation in this video.
https://www.youtube.com/watch?v=uGb_i9UPIg8
The most important thing to emphasise here is that the ADS can only measure very small voltages. This is why the shunt must be installed last, before the battery. This means that only a small voltage will drop there, as most of the voltage has already dropped across the consumers. If you place the shunt in the wrong place or use a cable that is too thin to the battery, the ADS will most likely be destroyed. Another problem is that we have a ground connection via the ADS. If you accidentally only connect the PLUS cable to the VanPI system and connect the shunt, there will be a ground connection via the ADS. It cannot handle that much current and will be destroyed. This is why it is always essential to disconnect and connect the ground cable at the same time as the plus cable.
In addition to the voltage from the voltage drop, we also need to measure the system voltage. This is done using a voltage divider.
Here you can find the wiring:
https://pekaway.de/docs/shunt/
Battery monitoring software
So far we only know the voltage drop and thus the current. What we now have to do is add these over time. This allows us to determine the current charge level of the battery. So we count how much current is being drawn from the battery and how much was loaded.
We need to query the ADS and perform the corresponding calculations relatively often and very quickly. This could be done directly in Node-Red, but it would not be optimal due to time-critical reasons, as Node-Red is still a ONE-THREAD application. However, since our RaspberryPi has 4 cores and Node-Red only uses one of them effectively, it would be nice if we could use the other 3 cores as well.
This is exactly what we did by running the actual shunt calculations in a Python script. This means we can constantly evaluate the shunt regardless of all requests and tasks in Node-Red. This only brings the challenge that we have to get the data back to Node-Red and we don't want to do this via the SD. Because we know that lots of write cycles are not good for the SD. That's why we have a small web server integrated into the Python script, via which Node-Red can get the data via HTTP query. The data then comes from the RAM and not from a file on the SD. The current battery charge level is written to the SD every 5 minutes, however, in order to have a starting point for monitoring the battery after a restart.
The starting point is also important to explain here. When setting up the battery in the web interface, you also have to enter an approximate charge level of the battery. This is because the shunt can only monitor the current that goes in and out, but cannot read the actual state of the battery. If the starting point is set incorrectly, the shunt can produce incorrect SOC values. Our Python script automatically detects a full battery after 15 minutes of charging voltage without charging current and sets the battery to full.
If you want to take a look at the script, you can find it here on the Raspberry:
~/pekaway/ads_py/ web1.py
Otherwise, as always, please feel free to post questions and requests in the comments.