voltage divider making adc nonlinear - Page 1
Forum section: electronics / projects

author: cc83
author_rank: Contributor
timestamp: July 21, 2016, 04:58:41 am
content: I have a project I'm working on for a battery tester that has a 0-20 volt measurement range. I prototyped it out with a arduino but will be converting it to a AVR in C later. The problem I'm having is that my voltage readings are not linear. I have a resistive voltage divider that cuts the 20V max to 10V max, and then that goes into a potentiometer that cuts it in half again to 5V max and allows for trimming, the resulting signal goes to a op-amp buffer and then into the ADC. The voltage reference is provided by a maxim 5V reference chip on the aref. When I hook up the avr (arduino) directly to a source for testing, the ADC output is linear but when I test it through the input circuit the result is not linear. When I trim the input to be exactly 10.0 volts I get a reading error increase of 0.2 volts for every 2 or 3 volts of input. For example, at 10.0V input the reading (output to lcd after converting the ADC reading to a float) is 10.0V, but at 12.0V input the reading is 12.2V. At 15.0V input the reading is 15.3V. this also work in the inverse when decreasing the voltage below 10V. I suspect that there is perhaps some loading or other issue going on with the resistive divider, I have tried different resistor values and it doesn't seem to change anything. I'm trying to minimize the burden when I make the measurement. Any advice would be appreciated.

author: Vgkid
author_rank: Super Contributor
timestamp: July 21, 2016, 05:41:51 am
content: loading will definetly be an issue. Not sure on the adc that you are using, ut lets assume 100k input impedance, as apposed to a multimeters 10M+ impedance. Now the offset is definetly causing an interesting issue. Have you looked into the specs of your adc yet?I will run some sims, and see what I get.Is this similiar to how your circuit is wired? ignore the switch and the 100k resistor portion, that is for testing.

author: cc83
author_rank: Contributor
timestamp: July 21, 2016, 06:04:31 am
content: It's a ATMEGA 328P, the input impedance is listed as 100 MegOhm. The fact that the nonlinearity is on a s curve is interesting. I will try to graph it later today so you can see exactly what I'm talking about. I do have the op-amp buffer before the ADC input. And as I said if I just input directly to the ADC for testing I get a very linear measurement so it seems the problem is with the circuit that divides the voltage down to something the ADC can read.

author: promacjoe
author_rank: Regular Contributor
timestamp: July 21, 2016, 06:06:28 am
content: Your problem could be in your program, specifically the conversion, reference value for each step of the A/D converter. If this value is slightly off, It will give you an incorrect reading. I would look their first. especially since you said you were using a op amp buffer. If that is the case, the current drop should not be the problem. The op amp will give sufficient current for the Arduino and not affect the measured source.

author: Vgkid
author_rank: Super Contributor
timestamp: July 21, 2016, 06:51:07 am
content: Joe, might be onto something with a programming issue.

author: newbrain
author_rank: Super Contributor
timestamp: July 21, 2016, 07:29:40 am
content: Could you please post the schematic (with values and op-amp model) of the whole input stage, and, maybe, some pictures thereof?That might help us finding a problem either in the design or the implementation.If the readings are linear without the input circuitry, the chances of a SW problem are lowered (but still there).So, you might want to show the relevant code parts too.Edit: gremmer and spleling

author: mikerj
author_rank: Super Contributor
timestamp: July 21, 2016, 07:46:49 am
content: No one can help without a schematic, I'm amazed by the number of people that ask for help without one. What resistance values are you using for the divider and potentiometer? Which op-amp are you using? What are the supply rails to the op-amp?

author: cc83
author_rank: Contributor
timestamp: July 21, 2016, 07:52:21 pm
content: Sorry about the lack of schematic, I was at work so I couldn't post it. Here it is. As I said I tried a bunch of different values for the resistors.

author: KerryW
author_rank: Regular Contributor
timestamp: July 21, 2016, 08:05:33 pm
content: The LM358 is not a rail-rail output op-amp. It will get pretty close to ground (at low currents) but only up to 2-3V below the + rail (5V)

author: Vgkid
author_rank: Super Contributor
timestamp: July 21, 2016, 08:21:06 pm
content: I will go with what KerryW says, in addition to this.Hopefully your 220 Ohm resistors are at least 1W. Since ((12*12)/440)/2 = .164W

author: cc83
author_rank: Contributor
timestamp: July 21, 2016, 08:32:14 pm
content: I'm using 10k resistors but I have a lot of values from 220 all the way up to 10M . Also I don't really need it to hit the bottom rail. It only really has to go down to about 6.5 volts.

author: f5r5e5d
author_rank: Frequent Contributor
timestamp: July 21, 2016, 08:43:13 pm
content: there are details to check on the integrated ADC spec but you may have enough conversion accuracy without the op amp buffer if you can load the battery by 10 kOhms - then the divider could have ~2 KOhm Ztypically these ADC are switching C input - if not continuously converting then a C to gnd from your divider can even restore full conversion accuracy even if ADC input charging current x divider Zout is too much in continuous operationand you don't want to trim that way - pot too high value, shouldn't be "full authority" 0-100 % adjustment range - it should be a parallel path to not increase Z, should only be able to pull the ratio by the worst case R tolerancemost with uC, integrated ADC system will production calibrate and download the constants to eeprom for the sw to use to calc rather than twiddle a pot

author: KerryW
author_rank: Regular Contributor
timestamp: July 21, 2016, 08:46:13 pm
content: But the LM358 will only go UP to 2-3V, representing a sensor voltage of 8-12V. You need an op-amp that will get close to 5V out. Something like an MCP6002 will fit right in to the circuit and do the job.

author: C
author_rank: Super Contributor
timestamp: July 21, 2016, 09:07:24 pm
content: Think of what a ADC is.It's a ratio device and will work better if you use it as such.Your variable resistor is just changing the ratio to a ratio device.When you calibrate this you should be able to use any setting on the variable resistor.One point calibration is then some voltage on input to give you some high value in ADC(%) that then puts same voltage on display. This assumes that 0 volts is 0% on ADC.Two point calibration is using a high %(value) and a low %(value) to ADC calibrate. This results in a linear display change between these two %'s.Still need a good input when using the above.

author: georges80
author_rank: Frequent Contributor
timestamp: July 21, 2016, 09:15:21 pm
content: Over complicated.I've used a resistor divider (365K/48.7k) with a 0.1uF across the bottom 48.7k resistor into AVR tiny devices and that works just fine from 24 - 0V input range. AVR running at 3V and using the VCC as the reference (3V).For more accuracy I will do a one time calibration at say 12V. With a reasonable regulator you'll get sufficient 'reference' stability over 0 - 80C range.Works just fine without opamps and other 'stuff' which just adds more non-linearities and tempco issues.cheers,george.

author: acolomitchi
author_rank: Contributor
timestamp: July 22, 2016, 05:32:34 am
content: Quote from: Vgkid on July 21, 2016, 08:21:06 pmWhy the/2? The way I know, P=U2/R (unlike the energy stored in a capacitor)With a 220R value - (12*12)/(220+220)=0.32W - those resistor should feel warm-going-hot with a 1/4W resistor (even at a 10V, one is close to a 1/4W).Once out of the safe range, all bets are off in regards with the rated values of those resistors - can't even assume their resistance will vary proportionally with the temperature (this would require homogenous resistive film with a constant/equal width of the track, otherwise hotter points may develop and make the variation with the temperature quite nonlinear).

author: acolomitchi
author_rank: Contributor
timestamp: July 22, 2016, 07:19:52 am
content: Quote from: cc83 on July 21, 2016, 07:52:21 pmAh, I know. Highly probable the explanation lays with theoffset voltage and current bias.You are assuming the Vout=alpha*Vin.In reality, due to OpAmp's offset voltage and current, the Vout will have a Y intercept at non-zero coordinate.Somethinglikethis (exaggerated to make the things clearer), the red line being the actual Vout=f(V_in) and the blue one is the assumed Vout=f(V_in)LM158/358 spec- page 5.You can have a typical 2mV yAxis intercept due to the voltage offset (may be positive or negative).Additionally, it can be compounded with a voltage difference caused by the current bias - the inverting input has 0R in input, but the non-inverting input will feel "those two halves of the potentiometer in parallel". Assuming you are close to the mid of your pot, it'll be 500K||500k=250k which will "steal" from the input voltage due to the current bias - with a "typical value" for current bias of 45nA, over 250k resistor this give a "typical value" of around 11mV - to be subtracted from the actual non-inverting input voltage.Now, you've made a 1-point calibration based on the assumption that the axes intercept of Vout=f(Vin) is in origin. As such, your computed slope (blue line) will be smaller than the actual slope of the OpAmp, which will give you higher (than expected) measured values when your Vin is above the "calibration point" and lower when Vin is lower than the calibration point.The good news is that your relation should be linear (thus easily invertible by the software), except that you'll need a two point calibration to get both the slope and the y intercept.Or, you know, just simplify your design: put aside your OpAmp and make the connection straight into the ADC - CMOS, with an impedance in hundred MOhm range, is better prepared to do the job than a bipolar OpAmp.

author: newbrain
author_rank: Super Contributor
timestamp: July 22, 2016, 07:25:40 am
content: Quote from: acolomitchi on July 22, 2016, 05:32:34 amYes, 0.32W total dissipated power, but there are two of them.In other words, each resistor will have 6V across, so P=(6*6)/220=0.164W.So, yes 1/4W resistor s should be barley enough (but they'll get warm/hot).

author: acolomitchi
author_rank: Contributor
timestamp: July 22, 2016, 07:28:07 am
content: Quote from: newbrain on July 22, 2016, 07:25:40 amAh, yes, my bad.

author: C
author_rank: Super Contributor
timestamp: July 22, 2016, 08:18:53 am
content: Quote from: cc83 on July 21, 2016, 04:58:41 am

author: newbrain
author_rank: Super Contributor
timestamp: July 22, 2016, 11:49:26 am
content: Quote from: C on July 22, 2016, 08:18:53 amYes, at 20V it'll be ~1/2W, of course. Not that it makes much sense to use this value for the actual divider, as already stated in other posts.

author: Seekonk
author_rank: Super Contributor
timestamp: July 22, 2016, 01:56:14 pm
content: As said before the op amp serves no useful purpose. Even with a 1M pot it will likely work better if you feed it in directly with a .01uF cap to ground.

author: acolomitchi
author_rank: Contributor
timestamp: July 22, 2016, 02:17:42 pm
content: Quote from: Seekonk on July 22, 2016, 01:56:14 pmYes, it does. Learning is usefulMore precisely:a. learning how the limits of real opamps can screw your day (if you ignore them)b. learning to use minimum components and trim those not needed

author: StillTrying
author_rank: Super Contributor
timestamp: July 22, 2016, 02:46:04 pm
content: Driving one input of the LM358 from it's output and the other through a 1M pot will cause input bias current problems, - as well as all the others!It looks like the ADC's recommended driving impedance is anything <10K.

author: bson
author_rank: Unknown
timestamp: July 22, 2016, 05:32:16 pm
content: If it were me I'd put the pot in series with R2, not parallel. Your divider effectively has R2||Rpot with a wiper tap, which just seems unnecessarily complicated. Also, the input impedance on the op amp is so high you could use e.g. 20k or 50k resistors for R1, R2 and not have to worry about currents. Actually, get rid of R1,R2 and just use a 20k pot or something; the pot itself is already a divider.Also, add a hold on the reset: 1k to Vcc and a 0.1uF cap to ground. Then the reset button sits across the cap and discharges it when pressed. This gives you a hold on the order of 1ms and deglitch to boot, and a nice reset hold on power-on:

author: wraper
author_rank: Unknown
timestamp: July 23, 2016, 05:33:25 pm
content: Quote from: bson on July 22, 2016, 05:32:16 pmVery "smart suggestion" to put cap in parallel with button, inductive kickback is surely what should be implemented on reset pin.

author: Seekonk
author_rank: Super Contributor
timestamp: July 23, 2016, 06:41:37 pm
content: Since this discussion was initially about a UNO, that reset capacitor should be increased to several uF. A UNO will reset anytime the USB port is plugged in and stored data will be lost. Reset is externally pulled down by .1uF connected to that pin.

author: cc83
author_rank: Contributor
timestamp: July 27, 2016, 01:59:07 am
content: Thanks everyone for the suggestions. I retested and reconfigured and even with my original circuit the result was accurate and linear from input to MCU pin. So I looked at the software. Couldn't find anything there. So I set up a program to log in values on the ADC and the result... It's a ADC linearity issue. So I did some error adjustment in software and it's working well now. I am going to redesign the input a little for v2. This project was for someone that had some strange requirements and they kept changing so the design was not optimal for the end result. I'm hoping that when I design a standalone board without the arduino and shield I won't have as much ADC error.