1

I have a potentiometer connected to an ADC input of an Arduino Leonardo. The ADC resolution is 10-bit (0..1024), while I need just 7-bit (0..127).

I use a simple filter to reduce the noise and then a map to cut the unused bits:

#define ADC_CH                18
#define ADC_FILTER            0.90

uint16_t value;

uint16_t adc = analogRead(ADC_CH); value = (uint16_t) ((float) ADC_FILTER * adc + (1. - ADC_FILTER) * value);

I show value on an LCD. It's very stable, but it may happen that if the adc readings are in the nearby of two values, there is nothing that could prevent a change in the final value, even if the noise is of just few LSBs.

Is there a simple way to implement an hysteresis for each low-res value?

In this way the change between N and N+1 happens on a different ADC reading than between N and N-1, improving the noise rejection without increasing the filter delay (that would only increase the change interval).

Mark
  • 393
  • 2
  • 14

1 Answers1

4

When you reduce the resolution from 10 bits to 7 bits, every possible output corresponds to an interval of inputs. If you add some hysteresis, then those intervals should overlap. Below is a representation of the input intervals corresponding to outputs 0, 1,… 6, for an hysteresis width of 4:

input: 0    5   10   15   20   25   30   35   40   45   50   55   60
       └────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴
       ├─────0────┤
           ├───────1──────┤
                   ├───────2──────┤
                           ├───────3──────┤
                                   ├───────4──────┤
                                           ├───────5──────┤
                                                   ├───────6──────┤

To implement this in code, you have to remember the last output, and change it only if the input lies outside the interval assigned to this output. Here is an example implementation:

const int hysteresis = 4;  // tune to taste

/* Remove 3 bits of resolution while adding some hysteresis. */ int resample(int adc) { static int value; // last output if (adc < (value<<3) - hysteresis) { value = (adc + hysteresis) >> 3; } else if (adc >= ((value+1)<<3) + hysteresis) { value = (adc - hysteresis) >> 3; } return value; }

Note that a static local variable keeps its value between successive calls to the function.

Edgar Bonet
  • 45,094
  • 4
  • 42
  • 81