suggestions for Debounce on analog switches

I am trying to come up with a debounce for an analog switch. So far, the program I have written seems to agree with my logic about 66% of the time. I want to think that the other 33% the time it is taking false readings from a loose breadboard and bad connections. Also, on occasion, it will continue to spit out zeros until I input a solid reading. In any case, I would appreciate some advise to improve this.

const int  buttonPin = A0;   
int buttonstateCounter = 0;
int lastanalogvalue = 0;
int analogvalue = 0;
int difference;
long previousMillis = 0; 
long interval = 1000;

void setup() {
  // initialize the button pin as a input:
  pinMode(buttonPin, INPUT);
  Serial.begin(9600);
}


void loop() {     

  analogvalue = analogRead(buttonPin); // read the pushbutton input pin
  difference = abs(lastanalogvalue - analogvalue);
  if (difference > 5 ) { // button has either been pressed or released
  
      buttonstateCounter++;
      if (buttonstateCounter % 2 != 0)// button pressed, take value
     {
       unsigned long currentMillis = millis();
       if(currentMillis - previousMillis > interval) 
       {
         previousMillis = currentMillis;
         Serial.println (analogvalue); 
       }
     }         
  lastanalogvalue = analogvalue;  
  }
}

and here is serial monitor output (anything less the ~160 is some sort of error):

804 980 694 172 0 0 11 12 178 382 587 980 14 586 177 382

What do you mean by "analog switch"?

You really should think before creating your subject...

I agree, was posting the same thing, lol

Capture.PNG

Yes, sorry about that. I must clarify... I should have said that there are multiples switches connected to one analog pin through their own unique resistor. I am trying to use one analog pin to do different things. the rest of this program has already been posted multiple times on this forum so I didn't want people to get sick of seeing it. ("Oh, this guy again...") The increments between button values is approximately 150, though some are more than 200 because of the values of the resistors I had on hand.

In that case, it appears you are leaving the pin floating when no button is pressed. You should fix that with hardware, not software.

Truly sorry, I did not mean to be offensive :/ does that happen with the titles very often? only with newbies right

and I should have stated that the analog pin has a 10K ohm pull down resistor. boy I am on a roll...

seanz2003: and I should have stated that the analog pin has a 10K ohm pull down resistor.

You might want to draw up a schematic and post it. Again, the behavior you describe suggests the pin is floating.

A circuit diagram would be nice.

This is how I do my analogue switches:

All the resistors have the same (10K) value. I get:

All off - 1024
S1 on - 820
S2 on - 768
S3 on - 683
S4 on - 513
S5 on - 0

Combinations take the lowest value.

Then I average the results of my reading - depending on the program I am using that might just be do a number of reads and average them, or do a constant rolling average of the reads, using say 10 data points.

If you want to debounce it then simplest general algorithm is to wait until it has provided consistent values for some period. You will have to decide how long that is - for example 0.1 seconds might be appropriate.

To implement that you would do your resistance comparisons to convert the input analog value to one of the switch positions, presumably held as an enum.

Your debounce algorithm takes a raw switch position as an input and produces a debounced switch position as the output. It uses a state variable recording the input switch position at the last sample, and the time when the input switch position last changed, and the current debounced position.

Each time you read the analog value and convert it to a raw switch position, apply your debounce algorithm to it:

  • If the raw position is the same as the previous sample and the last change happened long enough ago, the debounced state changes to the new position.

  • If the current position is different to the previous position, record the new position and note the time when this change happened.

  • Record the raw position for next time.

  • Return the debounced position.

Note that the debounce algorithm treats the 'switch not pressed' state exactly the same as any other state - you have to take your hand off the switch long enough for your debounced state to change to 'not pressed' before you tell your application the switch has stopped being pressed.

You would put this debouncing code in front of the code discussed on your other thread which looks for changes in the debounced state.

How do i post an image? i see the button but how do i use it?

I'm not sure. I host the images on my own web server and just paste in the URL inside tags.

Reply to this thread. click "Additional Options..." And then "Attach"

ah it worked. I know this hardware set up works , i have used it with other examples without any issues with floating pins. for instance this code works very reliably:

const int sensorPin = A0;
const int ledPin = 9;
const int threshold1 = 50;   // an arbitrary threshold level that's in the range of the analog input
const int threshold2 = 200;
const int threshold3 = 400;
const int threshold4 = 540;
const int threshold5 = 640;
const int threshold6 = 740;
const int threshold7 = 900;
int sensorValue = 0;
const int sensorMin = 0;      // sensor minimum, discovered through experiment
const int sensorMax = 1023;

  void setup() {
  // turn on LED to signal the start of the calibration period:
    Serial.begin(9600); 
    pinMode(sensorPin, INPUT);
  }
  void loop() {
    sensorValue = analogRead(sensorPin);
    Serial.print(sensorValue);
    int range = map(sensorValue, sensorMin, sensorMax, 0, 9);
    delay(500);
    switch (range) {
      case 0:    // 
        Serial.println("0"); //0-102
        break;
      case 1:    // 54k ohm - 175
        Serial.println("r");
        break;
      case 2:    // 205-306
        Serial.println("0");
        break;
      case 3:    // 307-409 18.5k ohm 378
        Serial.println("c");
        break;
      case 4:    // 410-511
        break;
      case 5:    // 512-613 8.5k ohm 579
        Serial.println("e");
        break;
      case 6:    // 614-716 5.5k ohm 682
        Serial.println("s"); 
        break;
      case 7:    // 717-818 3k ohm 807
        Serial.println("f");
        break;
      case 8:    // 819-920 1.2k ohm 913
        Serial.println("ph adjust"); 
        break;
      case 9:    // 921-1023 0 ohm 
        Serial.println("auto");
        break;
        
    } 
    }

but nevertheless, it is a valid consideration. it could also be floating from bad connections.

PeterH, I appreciate your detailed explanation of debounce, but sadly my brain isn't processing it. could I trouble for a raw example of how the program might be set up, (If you have the time). I have tried adapting the arduino example but it returns two values for every press and I only want one. I would also like it to only return a value once the button has been pressed

I have just started writing a handy “Average” library.

At the moment it just deals with rolling averages. I have used it with this piece of analog button debounce code:

#include <Average.h>

#define SMOOTH 10

int history[SMOOTH];

int bvals[] = {1023,819,768,683,513,0};

int analogButton(int channel, int *vals, int nvals)
{
  int value;
  int lastValue = 0;
  int l;
  while(1)
  {
    value = rollingAverage(history,SMOOTH,analogRead(channel));
    if(value == lastValue)
    {
      for(l=0; l<nvals; l++)
      {
        if(value == vals[l])
        {
          return l;
        }
      }
    }
    lastValue = value;
  }
}

void setup()
{
  Serial.begin(9600);
}

void loop()
{
  int value;
  static int lastValue = 0;
  
  value = analogButton(0,bvals,6);
  while(lastValue == value)
  {
    value = analogButton(0,bvals,6);
  }
  lastValue = value;
  Serial.println(value);
}

You will need my Average library for this: http://hacking.majenko.co.uk/libs/average

very cool, thanks