Hello community,
oversampling has been brought to my attention quite recently, and it sounded like black magic. So I decided to implement it for myself, since the one library I found regarding oversampling, did not satisfy me.

I have implemented oversampling as per AVR121. The implementation (and an example) may be found in the github repository.

My test results are looking pretty good, they may also be found in the repository.

I was wondering if anyone would is motivated to peer review my code, and the README. Just to make sure I really understood what I am doing - as mentioned the results look promising.

So thanks in advance,

Nice work! Reading your readme file it seems like you've got it down!

I wrote functions very similar to your readDecimated() and setPrescaler() functions and they worked well based on my testing. One thing I did was use a switch statement in the setPrescaler() function to avoid silly mistakes like trying to set the prescaler to 100 or something other than the allowed values between 16 and 128. Also, I wrote a simple function to measure and display the actual sample rate of the ADC each time the device was started.

A few things I learned when playing with oversampling:

  1. As you mention in the readme, the signal value should not change during the oversampling period so this technique is best used with relatively slow changing variables like pressure and temperature; and in my case I was measuring the voltage and current output of a generator.

  2. As the number of samples increases the maximum ADC sample rate becomes important. On the Arduino Uno (Atmel 328) I was using, I was able to get about 17kS/s from the built in ADC, using a clock divider of 64. This limited me to 15 bits of resolution. As you mention in your code, on the Atmel 328 in the Arduino Uno, the clock divider is adjustable from 128(default) to 16. Lower dividers give a higher sampling rate but at the expense of accuracy. In my case, more than 15 bits meant the oversampling time was too slow for my signal and increasing the sampling rate by reducing the clock divider below 64 unacceptably decreased accuracy.

  3. Another thing I found was that the voltage reference is important in making this technique successful. When I used the default voltage reference which was rock solid at about 4.997V, the oversampling didn't work. There was just crisp transitions from bit to bit as the signal changed. The Atmel app note also says you need 1-2LSB of noise in the signal for oversampling to work and that's why. When I changed the voltage reference to the internal 1.1V reference (measured at 1.079V) there was enough noise in the voltage reference to successfully oversample and increase resolution to at least 15 bits in my case.

  4. One key thing not to forget is calibration. Increasing resolution without calibrating to increase accuracy isn't going give the desired result. Calibrating includes measuring your ADC voltage reference and addressing offset and gain errors. I tried the technique in Atmel App Note 120 but couldn't get it to go far enough. In addition I created a correlation between some known accurate values and the output of my ADC and built that math into the code to correct the ADC reading. The result was less than 0.4% error from about 2% error based on the App note 120 technique alone. My application was a DC power meter reading voltage from 0-10V and current from 0-10A and calculating the power and energy output.

Thank you for taking the time to register and respond. Very much appreciated.

Sanity checking the prescaler is a very good idea. Although I am masking the byte accordingly, so nothing "bad" should happen.

  1. I'll borrow your examples and add them to the README, if it's OK with you?

  2. Interesting. I will try to compare different resolution settings. Also I received my "real" 12 Bit ADC today, so I am able to run comparable measurements. Hope to get it done this weekend.

  3. Again - very interesting. So you introduce noise via reference voltage? I thought the noise of the signal to be measured is of importance. I got some adjustable shunt diodes with tight tolerances to play around with external reference voltage to see how it compares.

  4. I read the paper about calibration, but did not try it out yet. You convinced me to do it.

Also I would like to know, since you were measuring 0-10V with 1.1V internal reference you had a voltage divider, with a ratio of 1:10 I'd assume? I was wondering how and if the voltage divider would affect the accuracy, eg.: resistance change due to temperature.

Again, thank you very much for responding.