Analog sampling accuracy

I've noticed that if I connect a potentiometer across 5V - GND to analog input 0 (or any other), and tell the arduino to output the value of the potentiometer, then scale using map() to within a range of 0-255, i get variation of +/-1 unit - the device will not settle on one number for one position. Is this a limitation of the arduino hardware or is it a poor potentiometer?

I haven't monitored the output of the device at unmapped (0-1023) scale... but I imagine it'd be 4x +/-1 variation. The code structure is basically: read analog 0 scale to within 255 output using DMXSimple library to digital pin 3.

Any ideas?

Any A/D can only output to + / - 1 digit, think about it.

What I mean is, in my serial console I get: (for example) 144 144 144 144 144 143 144 144 144

Variations of +/- one in the last digit will always be an issue (even after scaling down) and irrespective of accuracy/precision/quality of the analog to digital hardware you use.

To overcome this issue you can consider measuring deltas (difference between absolute unscaled readings). Then you can scale the deltas rather than the absolute readings. How you go about doing this will depend on your application.

Just wondering.. why will this variation always be an issue? Presumably the input voltage is constant and should be measured as a constant also... ? This seems like an odd behaviour for the measure of a supposedly stable input... I don't disagree with you (BenF), but if you could explain why this is the case, I'd be very grateful. :)

The last digit in the raw reading reperesents less than 5mV, any minor change in supplyvoltage, ripple, temperature etc. will have a small influence on the ADC reading.

To deal with it consider taking a number of readings and calculate the average.

The problem is that the wiper on your pot may be positioned very close between two readings (144, 143 in your example). The difference between the two readings may be so small that even the most accurate ADC ever made will not be able to distinguish one from the other.

If you had a way of knowing for a fact that the analog pot wiper was positioned exactly half way between two readings - the last digit (after scaling) would be more reliable. If you experiment with your current setup you will probably find a wiper position that is more stable and less likely to fluctuate between two readings.

Depending on your application, you may choose to read deltas and increment/decrement an absolute position based on the difference between to readings mapped/scaled to your requirements.

The hardware alternative could be a rotary encoder.

I tend to take an average of 10 or 20 readings - that helps keep the analog looking good.

Look at the "for" example, but don't forget to flush the varible by setting to zero as the first step of the "for" section.

    pot_value =0;  // clears the value of pot_value so it adds cleanly each time
    for (int i = 0; i > 5; i = i + x)  //sets up to read the input pin 5 times and adds i.e. 2+2+2+2+2 =10
     pot_value=  pot_value+analogRead(pot_pin);  //reads the value 5 times and adds
      pot_value = pot_value / 5; // divides by 5 to get the average of 5 reads.

This helps get rid of those "half way" readings that cause the final decimal to change.

Trying to remember for sure what I learned last night from this group - do I remember correct? (I'm at work this morning and working from memory).

Ken H.

You will see this effect on ALL forms of sensors. Every transistor is unique, when you get right down to the atoms. A reading that is somewhere near the transition of the least significant digit(s) will fluctuate between values. Even the act of reading the sensor has an effect on the next reading.

Microphone? The "noise" or "hiss" that you can never 100% get rid of.

Digital camera? This is the "noise" or "grain" you see in the image, if you magnify the image. Even analog film has a similar effect, where each crystal of photosensitive material is unique.

The best you can do, if you really don't want so many little fluctuations, is to get the average of the last several readings. This is called "smoothing," and it just masks the behavior a little.