Debouncing a potentiometer

Potentiometers in my project send MIDI data, therefore I need 7-bit resolution. Here is how my current debouncing algorithm works:

First I’m setting the active input on 4051 multiplexers on which potentiometers are connected:

void setMuxOutput() {
  
    //reset the variable to 0 after its value reaches 8 using masking
    muxInput &= 7;
    
    //switch to next mux input
    PORTC = muxInput << 2;
 
}

After that I’m reading the pots:

void readPots() {
	
    //check analogue inputs from 2 4051 analogue multiplexers
    for (int i=0; i<NUMBER_OF_MUX; i++) {

            //calculate pot number
            uint8_t potNumber = (i*8) + muxInput;

            //read analogue value from mux
	    //we need 7-bit value for MIDI message
            int8_t tempValue = analogRead(analogueInputArray[i]) >> 3;

			//if new reading is stable send new MIDI message
			if (potValueStable(tempValue, lastAnalogueValue[potNumber], analogueValueTimer[potNumber]))	{
				//debugging
				Serial.print("Pot number: ");
				Serial.println(potNumber);
				Serial.print("Value: ");
				Serial.println(tempValue);
				Serial.print("Current time: ");
				Serial.println(millis());
				Serial.println();
			
			}

    }
      
      //increment mux input for next loop iteration
      muxInput++;
  
}

potValueStable is a function which returns true if pot value passes through a series of conditions:

potValueStable(int16_t currentValue, int16_t previousValue, uint32_t analogueValueTimer)	{
	
	//calculate difference between current and previous reading
	int16_t analogueDiff = currentValue - previousValue;
	if (analogueDiff < 0)	analogueDiff *= -1;
	
		/*	
			When value from pot hasn't changed for more than ANALOGUE_TIMEOUT_MAX value (time in ms), pot must 
			exceed FILTER_AMOUNT (2) value. If the value has changed during ANALOGUE_TIMEOUT_MAX, it must be
			different from previous reading (analogueDiff > 0). If any condition is true, analogueValue timer
			is updated. If there is some difference between the two readings and change occurred in less
			than ANALOGUE_TIMEOUT_MIN ignore the reading.
			
		*/

			if
			
			(
			
			(analogueDiff >= ANALOGUE_THRESHOLD) || 
			
			(
			
			(analogueDiff > 0) &&
			((millis() - analogueValueTimer) < ANALOGUE_TIMEOUT_MAX)
			&& ((millis() - analogueValueTimer) > ANALOGUE_TIMEOUT_MIN)
			
			)	
			
			)
			
			{
				
				//reset timer on each new value
				analogueValueTimer = millis();
                 
				//update previous pot value
				previousValue = currentValue;
				
				return true;		
			
			}
			
			return false;
	
}

ANALOGUE_TIMEOUT_MAX is set to 200ms and ANALOGUE_TIMEOUT_MIN is set to 5ms.

So, this is how the regular readings look like:

Pot number: 8
Value: 73
Current time: 115934

Pot number: 8
Value: 74
Current time: 115944

Pot number: 8
Value: 75
Current time: 115960

Pot number: 8
Value: 76
Current time: 115979

Now I waited a couple of seconds and then continued to move the pot:

Pot number: 8
Value: 78
Current time: 118244

Pot number: 8
Value: 79
Current time: 118280

Pot number: 8
Value: 80
Current time: 118349

So, if you get stable reading from pot and then you don’t move it for longer than ANALOGUE_TIMEOUT_MAX (200ms) the difference between last and current reading must be ANALOGUE_THRESHOLD, which is 2. All fine so far, but there is still a case when values start jumping and this is the part I’m struggling to solve (note that I moved the pot only first time, the rest of values were jumping without any touching of pot):

Pot number: 8
Value: 100
Current time: 190818

Pot number: 8
Value: 101
Current time: 190830

Pot number: 8
Value: 100
Current time: 190907

Pot number: 8
Value: 101
Current time: 190919

Pot number: 8
Value: 100
Current time: 190982

Pot number: 8
Value: 101
Current time: 190993

Pot number: 8
Value: 100
Current time: 191011

Time difference between those values is less than I defined with ANALOGUE_TIMEOUT_MAX and more than ANALOGUE_TIMEOUT_MIN, so they’re right in the range when it’s actually possible to move the pot at that speed. So, what are your suggestions for this problem? I would appreciate any advice.

What happens if you take a few readings and average them? 4 or 8 readings makes the averaging easier.

Is the impedance of the pot 10k or less?

I presume you know to allow a settling time when you change to reading a different pot.

...R

Robin2: What happens if you take a few readings and average them? 4 or 8 readings makes the averaging easier.

Is the impedance of the pot 10k or less?

I presume you know to allow a settling time when you change to reading a different pot.

...R

In between setMuxOutput and readPots functions is function which reads 4x5 button matrix and handles few LEDs, so I pressumed that time needed for that is enough to allow some settling of pins. The pots are 10k yes, linear. I haven't tried averaging the pots yet, I'll try.

kustom:
In between setMuxOutput and readPots functions is function which reads 4x5 button matrix and handles few LEDs, so I pressumed that time needed for that is enough to allow some settling of pins.

Wrong presumption. Time difference was less than 1 ms, so I added a new variable, uint32_t muxSettleTime, so now setMuxOutput looks like this:

void setMuxOutput() {
  
    if (!muxSettleTime)	{
	
	//reset the variable to 0 after its value reaches 8 using masking
    muxInput &= 7;
    
    //switch to next mux input
    PORTC = muxInput << 2;
	
	muxSettleTime = millis();
	
	}
 
}

And readPots() is also slighty modified:

void readPots() {
	
	if ((millis() - muxSettleTime) > 3)	{
		
	muxSettleTime = 0;


....


...


muxInput++;

}

Due to 3 ms delay between seting pins and reading the values, I also removed the following check from potValueStable function:

&& ((millis() - analogueValueTimer) > ANALOGUE_TIMEOUT_MIN)

So far, the values aren’t jumping but I’ll play around with pots for some more time and report back here.