I'm trying to do DC voltage sensing for a DIY UPS. I have a genric Arduino Pro Micro and over the last few weeks I have figured out that the onboard ADC combined with a cheap 5x voltage divider module won't give me the resolution I want (interesting voltage range is ~11-13V) also, I may not be able to have the Ardunio have a common ground with the DC power source it is sensing. So, I started looking at ADS1115 modules. At this point in the project, I want to use module PCBs and not individual components myself. I'm posting hear to get advice on my plan.
I'm planning to use an Arduino Pro Micro connected to a RPi. The Arduino will communicate with the RPi over USB as well as be powered by the USB connection. The Arduino will talk to the ADS1115 using I2C, and I'll have a 5x voltage divider module between the ADS1115 input and the DC voltage source. Voltage range will be 0-15V, but nearly all of the time between 11-14.5V. I need a voltage reading about once per second.
I was planning on using the differential mode of the ADS1115 chip because it's input ground (from the Arduino) may not be tied to the voltage source being measured. Is this correct?
I am going to set the gain to 1. So resolution is +/- 4.096V. Am I right that setting the gain as low as possible will give me more accurate measuements?
Before looking at this chip and writing code for the Arduino's onboard ADC, I went down the path of taking several measurements quickly and averaging (ex 10 measurements, each 1ms apart). It isn't clear to me if I need to do that with this external ADC or whether there is a combinations of settings that will effectively do this for me. This answer to this affects whether I choose one-shot or continuous mode, and what data rate I select, right? Any advice here is appreciated.
The ADS1115 inputs must be held at a voltage between ADS1115 GND and Vdd at all times, or the sensor will be instantly destroyed. There must be a shared ground with the voltage source.
So, a single ended measurement using a voltage divider is all you need.
For accurate results you must calibrate the voltage divider, unless you use high precision resistors (e.g. 0.1%).
The division ratio should be small enough that the maximum expected external voltage will be divided down to fit comfortably into the range selected, for example 4:1 will result in 14.5/4 = 3.625 < 4.096V.
If you are thinking of measuring battery voltage in an automotive environment, the ADS1115 is an extremely poor choice, because you must anticipate voltage reversals and transients as high as 125V.
The ADS1115 inputs must be held at a voltage between ADS1115 GND and Vdd at all times, or the sensor will be instantly destroyed.
Yup, I saw that but forgot to write it. VDD to GND will be 5V, with my 0-15V expected range, the 5x voltage divider will give 0-3V to the ADS1115.
There must be a shared ground with the voltage source.
Really? I thought in differential mode I could get the difference between A0 and A1 (as an example) on the ADS1115. I was thinking DC source + goes to A0 and DC source - goes to A1.
If you are thinking of measuring battery voltage in an automotive environment, the ADS1115 is an extremely poor choice, because you must anticipate voltage reversals and transients as high as 125V.
Thanks for the warning, but I'm not. They are SLA deep cycle batteries, but for a DIY UPS project I have running. They have a charger and an inverter hooked up. Charge voltage never higher than 14.5 and the inverter is not pulling a lot of load relative to the battery capacity so I don't have very much voltage sag due to load.
What I'm really looking for is a rough capacity remaining estimate from the SLA voltage. I know this is a problematic way to estimate capacity and I may go to a current shunt eventually, but I'm starting with voltage for now. My code is using a voltage chart from the manufacturer to map a given voltage back to an rough estimate of percent remaining.
That is a common beginner mistake and sometimes may appear to work because of the extremely high impedance of the inputs.
However the stray resistances to ground are not constant and won't result in reliable measurements. Don't even try.
The typical 10 bit Arduino ADC can be extended to 12 or 13 bits by oversampling and averaging. For example, collect 64 measurements, total them and divide by 16 to get a 12 bit result. Works quite well as long as there is some noise in the measurements.
But because of the extremely high impedance of the inputs, the stray resistances to ground are not constant and won't result in reliable measurements. Don't even try.
Oh man, so glad I posted here then. Thank you!
So follow up question:
So, if I power the RPi via good 5V regulator that is tapping of the battery to be measured, since the Arduino is powered via USB from the RPi, and the ADS1115 GND is connected to the Arduino's GND, that should work? The battery GND is tied to the ADS1115 GND in that case?
Just as a follow up, for others in case it is useful.
I ended up powering the Arduino using a buck regulator that has GND common with the battery bank that I'm trying to measure. Also using a 5x voltage divider board and single-ended measurements on the ADS1115 board I bought. The Arduino, ADS1115 board, and the battery being measured all share the same GND.
I'm using one-shot mode, 8 SPS, and 1x gain (+/- 4.096V), and communicating over i2c. I get enough accuracy for my needs. Each tick is 0.125mV. I need about 5mV of accuracy and I take the measurement at 1hz. In my testing with 1-50 samples at various SPS settings for the ADS1115, I had so little variation in results that I just decided to use one shot mode and call it every second. As expected I got more variation when using my cheap benchtop PSU as a stand-in for the battery bank, but even then, one shot mode gives me enough.
Your point about extending to 12-13bits by oversampling is really useful. I'll file that away and maybe do that next time. For this personal project, it was fun and useful for me to figure out how to wire up and use the external ADC.
In the theoretical "next" version of this project, I think I'm just going to use an all-in-one current voltage monitor (TI has a few) with an external shunt and keep track of amps. Using voltage as a proxy for remaining capacity isn't awesome (I knew this going in, just saying it out loud)