Introduction: Arduino + Push Switch + Debouncing + Interrupts

Since I've started using the Arduino I've loved it. Although I found one thing very complicating with the Arduino that I couldn't figure out why it was happening until today, literally today. What is it? It's connected a push button to an Arduino interrupt pin to make it change certain variables. 

The application that I am working on requires the use of 2 push buttons, each will link into an Arduino (as an interrupt) and control the current position of the motor. I have 6 positions that I want the motor in. 

I originally set up my circuit like so: 


hi


The problem with this setup was when the button was pressed the interrupt was being called multiple times and even toggling other buttons. Why was this happening? It is caused from a switch bouncing feedback. To fix this, you need to modify your circuit around this manner below: 


hi2


What this did was when the push button was on (=1) the pin was HIGH and only HIGH. It never bounces around like it used to. 

-----

The project that I was working on had the following schematic (created with PSpice Student 9.1). 


hi3


The pin configuration is as follows: 
  • PIN 2 - Push button 1 (increase motor position)
    • interrupt 0
  • PIN 3 - Push button 2 (decrease motor position)
    • interrupt 1
  • PIN 22 - LED 1 (position 1)
  • PIN 24 - LED 2 (position 2)
  • PIN 26 - LED 3 (position 3)
  • PIN 28 - LED 4 (position 4)
  • PIN 30 - LED 5 (position 5)
  • PIN 32 - LED 6 (position 6)

What this application is going to do is start off in position 1 then as you push button 1, the LED will change based on the new position. I call these positions gears. Here is the Arudino code... it's really straight forward. 






const int led6 = 32;
const int led5 = 30;
const int led4 = 28;
const int led3 = 26;
const int led2 = 24;
const int led1 = 22;
volatile unsigned int current_gear = 1;

volatile long long timeout = 3000; // 3 seconds
volatile long long last_change_time = 0;

void loop()
{
  switch(current_gear)
  {
    case 1:
      digitalWrite(led1,HIGH);
      digitalWrite(led2,LOW);
      digitalWrite(led3,LOW);
      digitalWrite(led4,LOW);
      digitalWrite(led5,LOW);
      digitalWrite(led6,LOW);
      break;
    case 2: 
      digitalWrite(led1,LOW);
      digitalWrite(led2,HIGH);
      digitalWrite(led3,LOW);
      digitalWrite(led4,LOW);
      digitalWrite(led5,LOW);
      digitalWrite(led6,LOW);
      break;
    case 3: 
      digitalWrite(led1,LOW);
      digitalWrite(led2,LOW);
      digitalWrite(led3,HIGH);
      digitalWrite(led4,LOW);
      digitalWrite(led5,LOW);
      digitalWrite(led6,LOW);
      break; 
    case 4: 
      digitalWrite(led1,LOW);
      digitalWrite(led2,LOW);
      digitalWrite(led3,LOW);
      digitalWrite(led4,HIGH);
      digitalWrite(led5,LOW);
      digitalWrite(led6,LOW);
      break;
    case 5: 
      digitalWrite(led1,LOW);
      digitalWrite(led2,LOW);
      digitalWrite(led3,LOW);
      digitalWrite(led4,LOW);
      digitalWrite(led5,HIGH);
      digitalWrite(led6,LOW);
      break;
    case 6: 
      digitalWrite(led1,LOW);
      digitalWrite(led2,LOW);
      digitalWrite(led3,LOW);
      digitalWrite(led4,LOW);
      digitalWrite(led5,LOW);
      digitalWrite(led6,HIGH);
      break;
  }
}
void setup()
{
  Serial.begin(9600);
  pinMode(led1,OUTPUT);
  pinMode(led2,OUTPUT);
  pinMode(led3,OUTPUT);
  pinMode(led4,OUTPUT);
  pinMode(led5,OUTPUT);
  pinMode(led6,OUTPUT);
  attachInterrupt(0,up,RISING); // digital pin 2 // up
  attachInterrupt(1,down,RISING); // digital pin 3 // down
}

void up()
{
  Serial.println("-------------GOING UP-------------");
  Serial.print("Current Time - ");
  Serial.println(millis());
  Serial.print("Last Change Time - ");
  Serial.println((long) last_change_time);
  int difference = millis()-last_change_time;
  Serial.print("Difference - ");
  Serial.println((long) difference);
  Serial.print("Within Threshold? - ");
  if(difference > timeout || last_change_time == 0)
  {
    Serial.println("YES");
  }
  else
  {
    Serial.println("NO");
  }
  Serial.print("Previous Gear = ");
  Serial.println(current_gear);
  if((current_gear > 0 && ((millis()-last_change_time)>timeout)) || last_change_time == 0)
  {
    if(current_gear <= 5 && current_gear != 6) 
    {
current_gear++;
last_change_time = millis();
}
}
Serial.print("New Gear = ");
Serial.println(current_gear);
delay(150);
}
void down()
{
Serial.println("-------------GOING DOWN-------------");
Serial.print("Current Time - ");
Serial.println(millis());
Serial.print("Last Change Time - ");
Serial.println((long) last_change_time);
int difference = millis()-last_change_time;
Serial.print("Difference - ");
Serial.println((long) difference);
Serial.print("Within Threshold? - ");
if(difference > timeout)
{
Serial.println("YES");
}
else
{
Serial.println("NO");
}
Serial.print("Previous Gear = ");
Serial.println(current_gear);
if(current_gear > 0 && ((millis()-last_change_time)>timeout))
{
int tempGear = current_gear - 1;
if(tempGear != 0)
{
current_gear--;
last_change_time = millis();
}
}
Serial.print("New Gear = ");
Serial.println(current_gear);
delay(150);




There you have it, a switch debouncer that will work in any case. This tutorial was customized specifically for the Arduino! Enjoy!!