ATMega328 ADC accuracy graph - Page 1
Forum section: electronics / general

author: Rick Law
author_rank: Super Contributor
timestamp: September 29, 2013, 07:45:54 pm
content: Like everyone else with the ATMega, I too am playing with the ADC on the ATMega to measure voltage as a learning exercise.This is some info I collected that some may found useful: The ATMega328 ADC voltage compared against UT61E.Here is the collection environment:- Since I found the USB's power qualitymakes a huge difference, I should point out this Arduino is powered via USB (@5.008V) connected to a laptop.- An Arduino UNO hosts the ATMega328. A large capacitor discharges and feed the voltage into a simple OpAmp voltage follower and a .1uF as decoupler cap at OpAmp output to the Arduino. No other circuit involved.- The UT61E reference reads at the point it enters the Arduino.- The Arduino does not average or anything fancy - wait 229ms, read analog ports, report back at 19200, and wait till the clock ticks again.- The conversion is the standard formula 5*adcCount/1023. As basic and native as it gets.- The data is collected via a Java program. The JAVA program readsboththe Arduino and the UT61E.- The Arduino reports data every 229ms - a prime number so the other little things I do (like key debounce) will not be evenly divided into it reporting cycle.- The Java program understands UT61E's overshoot and will skip a cycle when the UT61E just changed range.- A big source of error I discovered was the time delta between the UT61E's reading and the Arduino's reading. So the dV/dT is made as small as possible. Minimum 20 data point is collected per count (>10 seconds per ADC count since UT61E samples at about 1/2 seconds).- The Java program will wait for the next report if the one last read is too old. "How old is too old" is based on experience from the data collected thus far in the run. Total time delta Sum(time of UT61E's number - time of Arduino's number) for all records is under 700ms.- The error plotted is the average of AbsoluteValue(error percentage) of that ADC count. So, a +10% is not going to cancel out a -10%. Which ever ADC (A0-A3) reports the worst error is the one plotted.My comment:With a good USB power source, it does very well on the high ranges but too dependent on the quality of the USB power. At over 2.5 volt, you can count on better than 1%if USB power is very near but over 5V. I cannot get consistent results (when USB powered) between different machines or even different ports. My PCI powered USB/firewire card compared to the USB ports on the mother board has a 100mV USB voltage difference. The mother board USB power is also different than the USB power on my laptops. That little delta shows up in the results.At the low end, it is hopeless unless something is done about it. Averaging and other techniques, I have achieved better results in my learning exercise. I collected this native328 results as the base line to see if the results my learning exercise is better, and if so, how much better.Just thinking some may be interested in how well the native-ATMega328 ADC numbers look.

author: madires
author_rank: Super Contributor
timestamp: September 29, 2013, 08:39:55 pm
content: Nice graph! But I got some remarks :-) Using USB as power source might be not the best idea because Vcc is used as voltage reference by the ADC. A good voltage regulator should improve the results (no 78L05, but something like a MCP1702). And for voltages below the internal bandgap reference (around 1.1V, needs be measured) the bandgap reference could be used as voltage reference to increase the resolution by a factor of 5. Or an external voltage reference could be used. The conversion formula should be 5*adcCount/1024. I assume that the DMM averages several measurements. So the ATmega328 should do the same to keep the competition fair. Do we have to consider an isolated USB connection?

author: dannyf
author_rank: Super Contributor
timestamp: September 29, 2013, 09:20:03 pm
content: QuoteWow! You shouldn't have done that.The large error at low voltage, depending on how you power the opamp follower, could be due to the opamp.The AVRs don't have a particularly good adc but it shouldn't be worse than 8-bits (in accuracy).

author: dannyf
author_rank: Super Contributor
timestamp: September 29, 2013, 09:24:08 pm
content: QuoteThe Arduino's analog section is essentially incorrectly designed. It should have utilized some decoupling from Vdd, and you are better off with either the onboard Vref (fairly mediocre for a reference source) or external Vref (a TL431/TL431A would be far better).

author: sync
author_rank: Frequent Contributor
timestamp: September 29, 2013, 10:35:39 pm
content: Looking at the graph. Is this just an offset error?

author: Rick Law
author_rank: Super Contributor
timestamp: September 30, 2013, 12:29:13 am
content: Quote from: madires on September 29, 2013, 08:39:55 pmThis one is a "native" to set a baseline. I actually did exactly that with my "real one". During the prototype for the "real one" using a home-made arduino, I cut the USB power and externally power it, plus a 78L05 as external voltage reference. That took away most of the USB port dependencies. With my "real one" that I am doing for learning, I use a 7805 for power and use internal reference.Interestingly, a smaller error then show up that I did not expect: an upto +-3mV variation from presence/absence of TxRx signal.Since it is a logger, I made sure it is "calibrated" for the presence of Tx/Rx.

author: Rick Law
author_rank: Super Contributor
timestamp: September 30, 2013, 12:50:40 am
content: Quote from: dannyf on September 29, 2013, 09:20:03 pmI was getting some oscillation that a 0.1uF almost but not entirely eliminates for the range I was playing around with.Re: OpAmp inpact - good point! I path it through an OpAmp to emulate how I have been test my "real thing" - a volt logger that I am doing as a learning exercise. This one is what I did as a base-line. I probably should have eliminated the OpAmp.I'll say this - while I have always know that working in mV/uV is hard, but I was not giving it its due respect. This learning exercise is forcing me to "give a lot more respect" to working around mV range...If I do this for money, I'd loose my shirt for sure. The ADC works rather nice at higher range. I was able to develop some technique to get some good results. But it certainly is neither cheaper, nor more flexible, nor more convenient, nor more accurate (as compare to something like a 20 dollar DMM). But it does data logging, 4 channels but unfortunately all with common ground...

author: dannyf
author_rank: Super Contributor
timestamp: September 30, 2013, 01:06:26 am
content: QuoteYou should always be extreme cautious with capacitance on the output.QuoteQuality analog work is far more difficult, even for trained pros, than comparable digital work.If you reasonably good adc, follow the datasheet on the VAdd pin decoupling, and use the internal bandgap - you can correct that either off line or during run-time.

author: Rick Law
author_rank: Super Contributor
timestamp: September 30, 2013, 05:05:07 am
content: Quote from: Rick Law on September 30, 2013, 12:50:40 amRe: OpAmp inpact - good point! I path it through an OpAmp to emulate how I have been test my "real thing" - a volt logger that I am doing as a learning exercise. This one is what I did as a base-line. I probably should have eliminated the OpAmp.I must have been tired as hell. I got so many grammatical errors in the first post, and I totally forgot a point of fact when replying to your reply. Recalling that now, I can say the low end error has nothing to do with the OpAmp. The low end error were all ADC's errors (or the UT61E). It is not a case of UT61E measuring OpAmp in and the other measures opAmp out. Both are measuring OpAmp out at the same physical point.The rail for the discharge testing circuit is split -2V to 5V. The capacitor discharge from +5 to -0.2V and the OpAmp is wired to be able to output from +5V to pass 0.00 down to almost -0.2V.Since both the UT61E and the ATMega measure the OpAmp output at the same physical point, any deviation between their values are errors that has nothing to do with the OpAmp. With my discharge circuit, I also connect my Hantek 6022BE USB scope, so I know I have no significant oscillation. Given the close agreement between my 4 DMMs, I know the UT61E is the more accurate than the ATMega. So I can comfortably assume the low end errors are the ADC's own - except perhaps some noise picked up from AC at +-5mV as shown by the 6022BE. 5mV can affect the ADC by +-1 count. But that is the extreme end and the graph was half way to heaven way before ADC at 1 count.By the way. I set the negative volt to -0.2V (there about) rather than +-5V. I made a mistake one time and let it go past 0.0 too far negative and not even for long. With less than 1 minute of -5V, that ATMega328 is no longer on this earth as a functioning member of MCU society. RIP.

author: sync
author_rank: Frequent Contributor
timestamp: September 30, 2013, 10:04:46 am
content: Quote from: Rick Law on September 30, 2013, 05:05:07 amI think you see the ADC offset voltage (Vos) error here. Your graph looks like ((V+Vos)/V-1)*100% where Vos=0.0125V. See my attached graph. Simply add or subtract 0.0125V from your ATmega readings.QuoteUsing a series resistor at the analog input protects it. Use a value between 1k and 10k.

author: dannyf
author_rank: Super Contributor
timestamp: September 30, 2013, 10:29:52 am
content: QuoteAs the absolute level of measurements goes down, the relative magnitude of a given level of measurement errors goes up.Having said that, it should be more than a few LSBs off so something else is at play here.

author: sync
author_rank: Frequent Contributor
timestamp: September 30, 2013, 11:20:17 am
content: Quote from: dannyf on September 30, 2013, 10:29:52 amBut this looks really like a missing compensation for the offset.Quote12.5mV equals 2.5 LSB. The datasheet specs 2 LSB max.

author: nctnico
author_rank: Super Contributor
timestamp: September 30, 2013, 12:32:54 pm
content: If Vref of the ADC is available on an external pin it will help a lot to use a more precise reference like an LM4040 at 3V or 4.096V. A standard voltage regulator can also do the job but there is a wide variety in accuracy. Some can have an error up to 3% so check the datasheet. The best ones are about 1% accurate (like the LM1117). If you need more accuracy then you'd need to use a precision reference.

author: Rick Law
author_rank: Super Contributor
timestamp: September 30, 2013, 10:10:43 pm
content: Quote from: sync on September 30, 2013, 10:04:46 amWait, I am getting very confused now...Why should the OpAmp's vOffset be an issue? I stuck a few measuring devices at the OpAmp output. The OpAmp output -0.2volt to +5volt. It isnota case of comparing OpAmp in and OpAmp out.Both the Arduino and the UT61Emeasure at OpAmp output.From the measuring devices' perspective, they are all connected to the same physical point and they just see a voltage. They then compare the voltage to each other. So, the source of that voltage should not matter. The voltage could have come from battery, AC wall brick, capactor, opAmp, whatever, it should not matter at all. They all see a voltage at the same physical point and they compare the number against each other's readings.The only time I saw that made a difference is when there is some high frequency oscillation (5kHz'ish). The speed of the ADC's come into play. Otherwise, they are just all comparing what they read at that point.I would appreciate any clarification. I am confused.ThanksRick

author: Rick Law
author_rank: Super Contributor
timestamp: September 30, 2013, 10:18:11 pm
content: Quote from: nctnico on September 30, 2013, 12:32:54 pmThat (external vref) was the trick I used with my first prototype.But, the point of this one graph is a to set a baseline when nothing is done -- so as I can compare "nothing done" vs my other learning exercise that I do every I could reasonably do or want to do. So I left this one as native as possible -- except the OpAmp in the discharge circuit.That OpAmp in the discharge circuit is.....I am getting confused by some of the comments as to why it matters that Vin for both UT61e and ATMega is from an OpAmp. Hopefully, I will get some clarification from the commenters.

author: Rick Law
author_rank: Super Contributor
timestamp: September 30, 2013, 10:24:14 pm
content: Quote from: Rick Law on September 30, 2013, 10:10:43 pm

author: sync
author_rank: Frequent Contributor
timestamp: September 30, 2013, 10:42:10 pm
content: Quote from: Rick Law on September 30, 2013, 10:10:43 pmNot the op amp offset. The ADC offset. It has one too. Ideally an ADC output value of 0 is 0V. In reality it's not exactly 0V, e.g. 12.5mV. See attachment and section 23.6.3 of the ATmega 328 data sheet.If you don't compensate this offset error in software then your absolute error goes through the roof at the low end.

author: Rick Law
author_rank: Super Contributor
timestamp: September 30, 2013, 10:52:46 pm
content: Quote from: sync on September 30, 2013, 10:42:10 pmOh, I get it. I was confused and thinking the comments were referring to the Vos of the OpAmp feeding the voltage to the ADC/UT61E to compare.Compensation improvement was exactly why I made the graph. I want this baseline so I can compare the improvement (if any) from my adjustments against the "native" ATMega328.

author: pavlii
author_rank: Newbie
timestamp: October 28, 2013, 09:46:23 am
content: QuoteOh great.I was experimenting with the ATMEGA 328P ADC and the most precise current sensor available - the LTC6102.According to the LTC datasheet, it's input offset should be around 3 microvolts on the shunt resistor, but my tests shown something around 40 microvolts with 0.00025 ohm shunt resistor. I was curious what causes this discrepancy.I started to blame Linear Technology (they did not answered my email at all), but later I found, that transformed to the ADC input voltage offset it was something around 11,3 mV voltage offset in my calculations. I started to think about other possible causes of the behavior and started to suspect the AD controller and it's input offset. I found, there should be some offset in the datasheet, but I was not able to find any concrete value.But now, when I found this topic - the 12.5 mV value you published is very close to the 11.3mV value I measured, so this seems to be the cause! I'm going to test it today - shift the GND of the LTC6102 sensor by some diode up by 0.6Volts or so and connect the sensor to the ADC, if the zero offset of the sensor will decrease. I hope it will solve my problems

author: Rick Law
author_rank: Super Contributor
timestamp: October 28, 2013, 06:20:28 pm
content: Originally when I viewed these post, I distracted by thinking we were talking about Vos of my charging circuit. A newest response made in this thread made me review the earlier post...Quote from: sync on September 30, 2013, 10:04:46 amI should try that next time...Quote from: sync on September 30, 2013, 10:04:46 amWhen I first view my graph, I recognize that it looked like an inverse polynomial curve, so I did looked into it being a simple offset whereV(actual) = V(measured) +- constant.But I found that there is a distinct break point (see attached graph of V measured vs V-calculated in this reply)I made only one complete runs (adc=0 to 1023), but many partial runs. The partial runs consistently have this change from -deltaMV to +deltaMV at around the middle somewhere.However, these analysis were before I realize certain external impact (such as when the Air Conditioner came on, or the Washing machine, or the dish washer...). That baseline was done when a couple of months ago when it was hot, so AC was coming on every now and again. The ripples coming into my discharge circuit could knock it into oscillation for a while - I didn't know that then. I may do another round of measurement now that I am more experienced.

author: madires
author_rank: Super Contributor
timestamp: October 28, 2013, 06:39:13 pm
content: Quote from: sync on September 30, 2013, 10:42:10 pmThe compensation is very easy to do:- select Gnd as ADC input- measure voltage (= offset)- substract offset for all other measurements

author: sync
author_rank: Frequent Contributor
timestamp: October 28, 2013, 07:27:58 pm
content: Your results are good. The integral non-linearity is specified as 0.5 LSB. With your 5V reference voltage this would be 2.5mV (5V / 1024). You measured less than 1mV error.Quote from: Rick Law on October 28, 2013, 06:20:28 pmThat's nothing unusual for a ADC.

author: sync
author_rank: Frequent Contributor
timestamp: October 28, 2013, 07:33:28 pm
content: Quote from: madires on October 28, 2013, 06:39:13 pmUnfortunately this is not working here. The ADC output code can't go negative (below zero).

author: pavlii
author_rank: Newbie
timestamp: October 28, 2013, 07:34:00 pm
content: Quote from: madires on October 28, 2013, 06:39:13 pmThis will not work. My ADC reports result = 0 for any voltage below ~ 12mV. (ATMEGA328P)

author: madires
author_rank: Super Contributor
timestamp: October 28, 2013, 10:38:49 pm
content: Quote from: pavlii on October 28, 2013, 07:34:00 pmI see. Is it the same when using Vcc and the internal bandgap reference as reference for the ADC?

author: miceuz
author_rank: Frequent Contributor
timestamp: October 29, 2013, 07:03:09 am
content: Hi,Nice coinscidence, I was making ATmega ADC measurements of my own a couple of weeks ago. I've used AD5045 voltage reference and DAC8411 DAC for my test setup. This is the graph I got, light grey value is uncompensated error, dark grey is offset compensated error and red is offset and gain compensated error:As you can see, it's pretty nonlinear, but somewhat close to datasheet specs. On another run, I've added some noise to a DAC signal (5LSB peak to peak triangle wave) and oversampled the ATmega ADC input up to 14 bits:As you can see, quantization noise is gone, but the nonlinearity can be clearly seen. Note that LSBs on the second graph are 14 bit LSBs, so the nonlinearity we get is somewhat 0.8 LSB (on 10 bit scale) which is pretty close to datasheet specifications.Lessons learned - never use internal avr adc if you want to achieve any decent accuracy

author: rs20
author_rank: Super Contributor
timestamp: August 08, 2014, 08:06:30 am
content: Quote from: sync on October 28, 2013, 07:27:58 pmHas this been resolved? Inevitable quantization error is 0.5 LSB in any case, even a perfect, perfect ADC will be "wrong" by 0.5 LSB (2.5mV in this case) simply because if the input voltage is, say, 2.49mV, the ADChas tocommit to output = 0 LSB (0mV, 2.49mV error) or output = 1 LSB (5 mV, 2.51mV error). Getting an error of only 0.7mV is like, impossible for many values of analog input? How is the graphthatgood? I must be missing something, like results are being averaged or some 12-bit mode is being used or something.

author: Rick Law
author_rank: Super Contributor
timestamp: August 08, 2014, 04:21:27 pm
content: Quote from: rs20 on August 08, 2014, 08:06:30 amThere is no 12bit mode with the ATMEGA328 - 10 bit only. The sampling is averaged so it could filter out random fluctuation. Averaging may give the impression of higher resolution, but more digits in the math doesn't change the resolution of the ADC. I did however found that as it averages, (with luck) one could discern is LSB closer to X-1, X, or X+1 with a higher degree of confidence.Since you already expressed your dislike of "reading+-%error" format in another thread, you will not like this graph. Not your cup of tea.There really isn't anything to resolve from my perspective. I took some data, posted it in "Reading +- % Error" format, and think others may find it useful. One person's experience of one ATMEGA328 only. It is just another data point. Just like doing a tear down on a single DDM of a model line. With a sample size of one, it can't even begin to tell you how a "typical" DDM of that model would behave. Just another data point.Rick

author: Carrington
author_rank: Super Contributor
timestamp: August 08, 2014, 10:43:41 pm
content: @ miceuz:I used your code (k-thermocouple-lib) here:https://www.eevblog.com/forum/reviews/youyue-858d-some-reverse-engineering-custom-firmware/msg484155/#msg484155Thanks for sharing.Note: I have not corrected the ADC offset, and I use only the 328 internal reference.Yes, 10 bit only, with the following tool is easy to calculate ENOB (ENOB-PROGRAM-PACKAGE).http://www.maximintegrated.com/en/design/tools/calculators/hp50g/?=1Damn, I always have to edit and re-edit my posts, because I wrote something wrong.

author: rs20
author_rank: Super Contributor
timestamp: August 09, 2014, 06:34:01 am
content: Quote from: Rick Law on August 08, 2014, 04:21:27 pmThe fact that you were averaging does resolve this dilemma, sorry if you mentioned this earlier in the thread. Believe it or not, averaging many samplescanimprove noise below one LSB, and more importantly removes quantization noise as a fundamental obstacle. This is the basis of the "Hi-res" modes on many oscilloscopes that give better resolution than the native 8 bits of the ADC by heavily oversampling and averaging. It's a real gain, not mathematical smoke and mirrors. 1-bit delta-sigma ADCs are the ultimate example of this (loosely).Quote from: Rick Law on August 08, 2014, 04:21:27 pmI'm sorry about the other thread, I know I was going on about it a bit. However, in this thread I was just trying to understand how you were seemingly getting better results that physically possible (averaging explains it). BTW, the graph that I'm commenting on is the absolute one, without that division I "dislike" so much. The datasheet says 0.5 LSB of non-linearity, you're getting 0.2 LSB, other people should assume 0.5 LSB to be safe but it's good to see that your sample is behaving well within the datasheet limits. Few applications (basically, only ones that average or integrate, such as that current measuring one in the other thread) can even theoretically benefit from a non-linearity better than 0.5 LSB.Thanks!

author: Rick Law
author_rank: Super Contributor
timestamp: August 09, 2014, 05:45:15 pm
content: Quote from: rs20 on August 09, 2014, 06:34:01 amNo sweat. No harm done. We just increased understanding between us.I am not an EE guy. While I understood the (%FS+%Rd+n_digits) and realize it make perfect technology sense, and is the accurate way of saying exactly how-much and where potential errors are, but I found it hard to immediately visualize. After making this (%Rd+%error) graph to give me a visual, I thought others may find it useful.Rick