Is there a way to get more stable voltage readings on a micro? - Page 1
Forum section: electronics / general

author: Red Squirrel
author_rank: Super Contributor
timestamp: May 17, 2019, 02:46:35 am
content: I use an arduino to monitor various things including battery voltage. I've always just used it as a ball park figure, and would go in the basement to check the real voltage. It would be nice if I could get it to actually be accurate though. The way my setup works right now is it takes the value from the arduino and times it by a multiplier that I determined by comparing to a volt meter and that's how I get the voltage. Problem is, I don't think ADCs are linear like that. When the voltage is at 13.5v the multiplier works and I get the right value, but as the voltage goes down, it no longer works, the reported voltage ends up being much lower than it really is. It also jumps around quite a bit.Is there any tricks to trying to get a more accurate reading? Capacitor or some kind of filter or something? I just have the 12v going to a voltage divider and then to the Arduino.

author: vk6zgo
author_rank: Super Contributor
timestamp: May 17, 2019, 04:18:23 am
content: Quote from: Red Squirrel on May 17, 2019, 02:46:35 amWhy not just determine the error, over a wide range, & program that into the micro, so it auto-corrects the final reading?(obviously your existing multiplier is too coarse to do the job).This wouldn't fix the jumping, however.

author: apblog
author_rank: Regular Contributor
timestamp: May 17, 2019, 04:40:50 am
content: you need both a multiplier and an offset in order to fix this properly.V = aM+bwhere V is the result and M is your measured voltage. You can find the coefficients a and b by math or by trial and error.A low pass filter would be helpful to steady the readings. You can implement the low pass filter in software very easily.I would do the low pass filter first. and then work on the multiplier and offset.here is a simple filter that works really well:new_avg = last_avg + ((new_avg - last_avg) / c);You don't need to store any old data points this way. Play with the value c to adjust how much smoothing you get.

author: Red Squirrel
author_rank: Super Contributor
timestamp: May 17, 2019, 04:52:04 am
content: Yeah was thinking about doing averaging suppose that's worth a shot.Never considered the offset, guess a good start is to see what the reading is when it's shorted to ground, I would assume 0, but guess it may not necessarily be 0, so I need to account for that offset.This thing is all hard wired so kinda a pain to even reprogram it with any code changes, but I'll work on figuring that out so I can do that. I might be able to do it from the automation server, think Arduino released some command line tools a while back so might be able to set that up.I eventually want to totally redo this system so it's more modular and easier to maintain/change.Also would I be better off using the AREF pin and supplying it with a smooth 5v? Right now it's not connected to anything. I wonder if the USB is maybe fluctuating slightly. I believe I need to change the code to switch to that mode as well, I'll need to check that further.For good measure I also put an electrolytic cap between the ground and +5v pin, though not sure if that will do much, as the Arduino probably already has filtering caps in it at the actual input. The 5v pin is more of an output, though the way it's connected it can kinda act as input.

author: mikerj
author_rank: Super Contributor
timestamp: May 17, 2019, 07:00:03 am
content: Quote from: Red Squirrel on May 17, 2019, 04:52:04 amFor low noise and best long term accuracy you should be connecting a well decoupled voltage reference to the AREF pin e.g. 2.5v. Also make sure the AVcc pin is well decoupled.A low pass filter should be used on the incoming signal to limit it's bandwidth. Averaging in the software helps but noise above half the sample frequency will be aliased, you need analog filtering to get rid of this. For something like voltage monitoring you typically only need a low bandwidth, (maybe 10Hz or so) unless you need to react very quickly to an out of specification voltage.

author: Red Squirrel
author_rank: Super Contributor
timestamp: May 17, 2019, 05:32:16 pm
content: Low pass filter would go at the ADC input right? That's something I'll have to experiment with, I imagine it would help. Might play with this with a separate arduino until I get it right then implement it.

author: mikerj
author_rank: Super Contributor
timestamp: May 17, 2019, 07:24:51 pm
content: Quote from: Red Squirrel on May 17, 2019, 05:32:16 pmYes, the less noise you put into the ADC the more stable the readings will be. This applies to both the ADC input and the voltage reference input.

author: rstofer
author_rank: Super Contributor
timestamp: May 18, 2019, 01:21:53 am
content: After you get everything as smooth as you can get it, calibrate it by applying a known voltage (measure with DMM) and noting the output. Keep these as x,y values - get several points, maybe a dozen.Then use Octave (free) polyfit() to generate a polynomial you can use to get a more accurate display of the input voltage.https://octave.sourceforge.io/octave/function/polyfit.htmlGet a reading, stuff it into the polynomial and get a result. I might stop at 2d degree, certainly no higher than 3rd degree. The more traditional y=mx+b is just a first degree polynomialhttps://octave.sourceforge.io/octave/function/polyfit.html

author: radiolistener
author_rank: Super Contributor
timestamp: May 18, 2019, 09:13:24 am
content: Most of ADC has pretty good linearity, so there is no need to use polynomial or spline correction for voltage measurement. I think topic starter's ADC gets correct measurement, but his multimeter measurement or schematic is incorrect.I think he measure voltage on some distance from circuit and didn't take into account voltage drop on wires (due to Ohm law). It can be checked easily, multimeter should be connected directly to ADC input pin.Also there is another possible issue with measurement, incorrect circuit on the ADC input.And the third possible issue is that ADC REF voltage drops below specification due to insufficient of power voltage, in such case there is no way to measure voltage correctly, you're need to fix your schematic to avoid that (use lower REF voltage).In order to make some conclusion, topic starter needs to check voltage directly on ADC input pins. Use long wire even for ground is not allowed for correct measurement, the multimeter probes should be applied directly to GND and ADC input pins of IC.Also, provide your schematic on ADC input.

author: Red Squirrel
author_rank: Super Contributor
timestamp: May 18, 2019, 06:39:27 pm
content: Thnks for the info, right now it's a very simple setup, no schematic involved, just arduino straight to battery. There is telco frame wire going to the negative and positive of the battery from the server rack where the arduino is. Nothing special in between. I will follow some of the tips on having multiple measurement points and also adding more filtering and going from there. Also come to think of it, should I omit the ground, since everything is ground referenced anyway?Is voltage drop something I really should worry about for simply measuring, I imagine it's not sinking enough current to matter, or is it? Suppose that could easily be solved by using thicker wire going to the voltage source.I do replan to eventually redo all of this anyway so I'll keep some of this stuff in mind.

author: Buriedcode
author_rank: Super Contributor
timestamp: May 18, 2019, 08:55:53 pm
content: I know you said you had no schematic, but if you're measuring 13.5V you clearly have some circuitry on the ADC - a resistor divider. As discussed, _generally_ a source impedance of at most 10k, or higher if you add a 10-100nF cap, and a half decent Vref will improve matters. So will slowing down the ADC clock, unless you require kSPS. As for jumping/erratic results, that'll be a noise issue both external (interference) and internal (all micro's ADCs are affected in some way). Running window averages are fine, but if you don't require a fast update rate, then /16 is more than good enough.I've noticed AVR ADCs to be somewhat less accurate than PIC ADC's but its not really an apples-to-apples comparison, since I used the PICs with an external Vref and run them fairly slow (Fosc/32), where-as most use the Arduinos ADC with the built-in functions, running at full pelt, with the internal Vref.Without an idea of your setup or the code you're using, its hard to say anything really

author: rstofer
author_rank: Super Contributor
timestamp: May 18, 2019, 10:11:37 pm
content: There's something else about measuring battery voltage that I skipped over: You really don't care about the voltage below, say, 10V because the battery is dead. I don't now the upper value of your charge voltage but let's say 15V. What you would really like to do is spread the 5V you do care about (10V..15V) over the range of your op amp and get rid of the range you don't care about.Section 4.5 of "Op Amps For Everyone" covers this nicely. They use 4 resistors and a single supply op amp to offset and rescale an input.https://web.mit.edu/6.101/www/reference/op_amps_everyone.pdfUsing this approach, you will definitely have to do at least a y=mx+b because 'b' will be 10V (the offset) and 'm' will be the scale 5V -> 3.3V?The good part about this is that you get resolution where you need it and not down below 10V where you really don't care.

author: radiolistener
author_rank: Super Contributor
timestamp: May 19, 2019, 12:12:27 am
content: Quote from: Red Squirrel on May 18, 2019, 06:39:27 pmNo. It may lead to incorrect measurement.

author: Red Squirrel
author_rank: Super Contributor
timestamp: May 19, 2019, 01:28:43 am
content: Quote from: rstofer on May 18, 2019, 10:11:37 pmOh interesting might be something worth checking for my next design. Right now I just have the divider setup for a 48v system (was planing on upgrading at some point) so I'm probably losing a lot of resolution covering the entire range. I don't recall what the values are but I had went with high enough, like 100k range. It's all tucked away in the server rack and wrapped in electrical tape so hard to get to without dismantling stuff. One of the reasons I want to redo this system, modularity or ease of maintenance was not exactly considered when I first set it up.