I need to take a reading using an ATmega328P of a gas sensor. The ATmega328p has a built in 10bit ADC giving only 1024 'steps'

The data sheets for my O2 sensor are: http://www.citytech.com/PDF-Datasheets/ao2.pdf http://www.quantika.ro/prospecte/ao2.pdf

It works by generating a voltage by chemical reaction to O2. It requires a load resistor of 10K to 'get it going'

The T90 or T99 is the time in seconds a sensor takes to reach n% of the correct reading.

I was wondering for the range 0-100% gas reading, the sensor gives 0-60mV.

What would be the best solution to give me a 0.01 resolution?

10000 steps would mean a 14bit ADC? Peferably I2C or SPI so something like the ADS1118? Do I need to use an OpAmp to amplify the signal first? Is there an instrumentation amplifier with a built in PGA that will suit this application?

I was able to put a 10k Resistor in parallel with the sensor, using an ADS1115 ADC I was able to read the value using i2c with my ATmega328p. The ADS1115 (had to remove link as reputation not good enough) was good but I found the PGA gain not enough for me.

If I use the powered version on this o2 sensor called a mox20 (had to remove link as reputation not good enough but google mox-20 oxygen sensor) as the output is much higher, I don't need so much amplification but this sensor is more expensive so I am looking for a circuit idea maybe using an op-amp and another ADC or ideally an ADC with a built in PGA with the gain I would require.

  • \$\begingroup\$ Welcome to EE.SE. What kind of sensor have you got? Is it a potentiostat type of sensor? Is the 0 to 60mV referenced to ground, or to some reference voltage above ground? \$\endgroup\$ Commented Aug 16, 2014 at 22:31
  • \$\begingroup\$ Would you give us the part number of the sensor? Have you any evidence that the error in its measurement is to at least "a 0.01 resolution"? \$\endgroup\$
    – gbulmer
    Commented Aug 16, 2014 at 23:06
  • \$\begingroup\$ The data sheet is citytech.com/PDF-Datasheets/ao2.pdf Thanks \$\endgroup\$
    – Andrew Eve
    Commented Aug 17, 2014 at 6:46
  • \$\begingroup\$ @AndrewEve That's a surprisingly short datasheet. It doesn't even map the function for each pin (at least, I don't see it). My feeling is that there should be more information. Is there a family datasheet? Is there an industry standard that's implied? Possibly, you need to implement this circuit (app note) to work with your sensor. But, that app note doesn't seem to link to particular sensor models or families. Interrogating the manufacturer may generate some insight. \$\endgroup\$ Commented Aug 17, 2014 at 7:52
  • \$\begingroup\$ I updated the original question with another possibly more informative datasheet quantika.ro/prospecte/ao2.pdf \$\endgroup\$
    – Andrew Eve
    Commented Aug 17, 2014 at 19:32

1 Answer 1


The signal should be amplified with a low noise 'instrumentation' amplifier to get it's full range signal up the match the range of the ADC, say 5V. Otherwise you are wasting ADC resolution. Someone else can answer the analogue, though I believe that has been answered on electronics.stackexchange already.

My reading of that sensor data sheet is the senor is very slooooooooooow compared to digital technology. It says it's response time for 'T90' < 5 seconds, and 'T99.5 < 40 seconds.

If you could explain exactly what those terms mean, I might be able to be more exact in my answer, but I'll give you the punchline anyway, because it appears to help.

There are purely software techniques for increasing the resolution of an ADC which work by taking multiple samples.

This is not simply taking multiple samples to do normal averaging to reduce error.

Instead, the technique extracts more information about the signal from many samples.

The technique is called "Oversampling and Decimation"

It can be made to work in a couple of ways, and this Atmel application note "AVR121: Enhancing ADC resolution by oversampling" explains how. It has a worked example, which looks very similar to your scenario.

A Mental model
It might be easier to think of the real sample having a tiny (less than 1-bit high) saw-tooth signal added. The saw-tooth must not be synchronised with sampling.

Draw a voltage vs time graph, volts up, time right.

Draw a steady, horizontal, real signal. Then draw horizontal lines to represent the measured digital value. The signal will be somewhere between two lines. Then draw a saw-tooth signal, 1 bit high, sitting on top of the horizontal real signal

When the steady signal is close to the next higher digital value, the saw-tooth crosses up above that value 1 higher.
When the steady signal is barely above its measured digital value, the saw-tooth hardly ever crosses up above that value 1 higher.
(I will try to find time to draw this, I can't find the picture by searching)

The maths:
When a real signal 'r' is measured it is rounded down to the nearest digital value by the ADC. Let's call that rounding down floor(), and let's say how many bits the ADC measures.

So, a signal r is measured by a 10-bit ADC as a number, call it 's', = floor(r, 10)

Let's call the amplitude of the saw-tooth at any instant t, we don't know what it is, except it is less than the voltage between any ADC value, and the next. For a 10-bit ADC measuring 0-5V, the maximum value of t is 5V/1023, or roughly 5mV.

Now let's think about a long stream of values from the ADC. Remember, it is measuring r with the saw-tooth voltage t added.

Then each time the ADC samples, the answer is the real signal r and the saw-tooth. s = floor(r+t, 10)

The saw-tooth will sometimes push s 1 bit higher than r alone would be measured because the saw-tooth happens to be big enough when added.

If the signal r is almost at the digital value r+1, then a lot of the samples with t added in will be measured as s = r+1. If the real-signal r is barely above r, then almost all will be at s = r

This is key: when r is very close to s+1 (but just under it), t pushes lots of ADC conversions high enough to measure as s+1 when r is far below s+1 (very close to s), t pushes very few ADC conversions high enough to measure as s+1, so most are still measured as s

So, if we add up a long sequence of ADC values, s, the ratio of s=r values to s=r+1 will give us more information. The ratio of s=r to s=r+1 tells us the value of r in that 1-bit, 5mV voltage range. The saw-tooth (not synchronised with sampling the signal) extracts that information.

The nice part is we don't need to count the ratio of s to s+1. We just add the sample values, and shift right (to get the correct number of bits). The number of +1's is added in, and that is the right ratio.

Now here is the sneaky part.

Random (Gaussian) noise acts in a very similar way to the saw-tooth signal. It gets added anyway, for free. We don't need to do anything except add a sequence of values. The only downside is noise takes more samples than a saw-tooth. In this case, I don't think it matters.

Summary: add enough samples then the low-res ADC acts like a higher resolution ADC.

How effective is this?

That document has a table, but let's pick a few, using a 10 bit ADC (e.g. an ATmega328P)

11 bits - 4X samples
12 bits - 16X samples
13 bits - 64X samples
14 bits - 256X samples

By adding 256 samples, a ATmega328P's 10bit ADC provides 14 bits of resolution.

An ordinary Arduino, samples at roughly 9.6kHz, and that sensor looks so slooooow, it shouldn't have changed much while sampling.

TI's application note "Oversampling Techniques using the TMS320C24x Family", AKA spra461.pdf has some useful diagrams and explanation of superimposing a triangle wave, which increases resolution with fewer over-samples that noise.

Side note: If you are confident with programming, consider getting an ST Micro Nuceleo. They are mbed's, so the software is instantly available from mbed's cloud. ST's Nucleo's cost about 8GBP. They have one or more 12bit ADC's built in. Most have 1M samples/second ADC's, and the STM32F302 and STM32F334 have 5M sample/second ADCs. The extra 2 bits mean they only need sample and add 16 values. So they could provide 14bit resolution at a higher sample rate than the raw ATmega328 could provide 10 bits. This isn't an advert for ST. Any MCU with a faster higher-resolution ADC will perform in a similar way.

That sensor specification seems to be so slow, that by using this purely software technique, the 10bit ADC on the ATmega328P will provide 14bit resolution. In fact, it could provide 15bit resolution by adding more samples.

  • \$\begingroup\$ Thank you for your extensive answer! I am sure the atmega328p only has a 10bit ADC atmel.com/Images/doc8161.pdf \$\endgroup\$
    – Andrew Eve
    Commented Aug 18, 2014 at 6:19
  • \$\begingroup\$ Andrew, you need to re-read gbulmer's answer. He's telling you that you can get 14Bit performance from the atmega328p's 10Bit ADC. All you have to do is apply some processing. You must sample at the highest rate your atmega can manage, then run the samples through a low pass filter and the decimate the results - take a look at the application note he referenced. It provides a very good description of the background for the technique, as well as a practical example. \$\endgroup\$
    – JRE
    Commented Aug 18, 2014 at 9:49
  • \$\begingroup\$ @AndrewEve - The point of my answer is, it is very likely that you can extract 14bits of resolution from that sensor's signal using only a 10bit ADC. 'Oversampling and decimation' is a software technique; it needs a program. \$\endgroup\$
    – gbulmer
    Commented Aug 18, 2014 at 11:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.