Go Down

Topic: Hi guys need some help with SwitchDebounce and StateChangedetection (Read 590 times) previous topic - next topic

ash901226

is you all know in the arduino IDE there are some example of programming which also include

debounce:
Code: [Select]

const int buttonPin = 2;
const int ledPin =  13;


int ledState = HIGH;
int buttonState;     
int lastButtonState = LOW; 

long lastDebounceTime = 0;
long debounceDelay = 50;

void setup() {
  pinMode(buttonPin, INPUT);
  pinMode(ledPin, OUTPUT);
}

void loop() { 
  int reading = digitalRead(buttonPin);
  if (reading != lastButtonState) {
    // reset the debouncing timer
    lastDebounceTime = millis();
  }
 
  if ((millis() - lastDebounceTime) > debounceDelay) {
    buttonState = reading;
  }
  digitalWrite(ledPin, buttonState);
  lastButtonState = reading;
}


and State Change Detection
Code: [Select]

const int  buttonPin = 2;
const int ledPin = 13;     

int buttonPushCounter = 0;
int buttonState = 0;       
int lastButtonState = 0;   

void setup() {
  pinMode(buttonPin, INPUT);
  pinMode(ledPin, OUTPUT);
  Serial.begin(9600);
}

void loop() {
  buttonState = digitalRead(buttonPin);
  if (buttonState != lastButtonState) {
    if (buttonState == HIGH) {
      buttonPushCounter++;
      Serial.println("on");
      Serial.print("number of button pushes:  ");
      Serial.println(buttonPushCounter, DEC);
    }
    else {
      Serial.println("off");
    }
  }
  lastButtonState = buttonState;
  if (buttonPushCounter % 4 == 0) {
    digitalWrite(ledPin, HIGH);
  } else {
   digitalWrite(ledPin, LOW);
  }
}


I was trying to merge both the program together and i came out with this
Code: [Select]

uint8_t Switch =2;
uint8_t Led =13;

boolean LastSwitchState=HIGH;
boolean LedState=LOW;
unsigned long LastDebounceTime;

void setup()
{
  pinMode(Switch,INPUT);
  digitalWrite(Switch,HIGH);
  pinMode(Led,OUTPUT);
}

void loop()
{
  boolean SwitchState=digitalRead(Switch);
  if (SwitchState != LastSwitchState)
  {
    LastDebounceTime=millis();
  }
  if (millis()-LastDebounceTime>=10UL)
  {
    if (digitalRead(Switch) ==LOW)
    {
      LedState = !LedState;
    }
  }
  digitalWrite(Led,LedState);
  LastSwitchState = SwitchState;
}


What happen with my code was, the led will light up at random as though the switch have not been debounce man i was frustrated. i tried thinking it over and over still cant see whats the problem i tried changing the variable and the position of each line in the hope of it make sense.

the i remembered one tutorial that i saw long ago, it work perfectly but i try to change it to suit my need.Haha my need is not to use delay and thats it
heres the link to the tutorial in ladyada site http://www.ladyada.net/learn/arduino/lesson5.html

and if you scroll down or you try to read all the tutorial.( Its a good tutorial btw) you will find this in challenge part 2. and the best thing is that the site make a white back ground and turn the writing white so its kinda invisible unless you try to highlight the white box.

heres the code that i am refering to
Code: [Select]

int switchPin = 2;         
int led1Pin = 12;
int led2Pin = 11;
int led3Pin = 10;
int led4Pin = 9;
int led5Pin = 8;

int val;                     
int val2;                   
int buttonState;         

int lightMode = 0;         

void setup() {
  pinMode(switchPin, INPUT); 

  pinMode(led1Pin, OUTPUT);
  pinMode(led2Pin, OUTPUT);
  pinMode(led3Pin, OUTPUT);
  pinMode(led4Pin, OUTPUT);
  pinMode(led5Pin, OUTPUT);
 
  Serial.begin(9600);
  buttonState = digitalRead(switchPin);
}

void loop(){
  val = digitalRead(switchPin);     
  delay(10);                         
  val2 = digitalRead(switchPin);     
  if (val == val2) {                 
    if (val != buttonState) {         
      if (val == LOW) {               
        if (lightMode == 0) {         
          lightMode = 1;               

          digitalWrite(led1Pin, HIGH);
          digitalWrite(led2Pin, HIGH);
          digitalWrite(led3Pin, HIGH);     // blink on!
          digitalWrite(led4Pin, HIGH);
          digitalWrite(led5Pin, HIGH);

          delay(100);

          digitalWrite(led1Pin, LOW);
          digitalWrite(led2Pin, LOW);
          digitalWrite(led3Pin, LOW);     // blink off!
          digitalWrite(led4Pin, LOW);
          digitalWrite(led5Pin, LOW);

          delay(100);

        } else {
          lightMode = 0;               // turn light off!
         }
      }
    }
    buttonState = val;
  }
}


and heres how i think it should be when i try to convert it without using delay() and use millis() instead
Code: [Select]

/*Declaring Pin Location*/
uint8_t Switch = 2;
uint8_t Led    =13;

/* Declaring Fix Variable*/
unsigned long DebounceTime=5;

/* Declaring Variable*/
boolean SwitchState1 = HIGH;
boolean SwitchState2 = HIGH;
boolean LastSwitchState = HIGH;
unsigned long LastDebounce =0;
boolean LedState=LOW;

/* Only run Once during Startup*/
void setup()
{
  pinMode(Switch,INPUT);
  digitalWrite(Switch,HIGH);
  pinMode(Led,OUTPUT);
  LastSwitchState = digitalRead(Switch);
}

/*Run Continuoustly*/
void loop()
{
  SwitchState1=digitalRead(Switch);
  if (SwitchState1 != LastSwitchState)
  {
    LastDebounce=millis();
  }
  if ((millis() - LastDebounce) >= DebounceTime)
  {
    SwitchState2= digitalRead(Switch);
  }
  if (SwitchState1 == SwitchState2)
  {
    if (SwitchState2!= LastSwitchState)
    {
      if ( SwitchState2 == LOW)
      {
        LedState = !LedState;
      }
      LastSwitchState = SwitchState2;
    }
  }
  digitalWrite(Led,LedState);
}


Still the outcome is kinda the same. I have also try to change a couple of variable and how my placement of variable and code.

so after this long post of maybe what i could call failure to merge and to debug, I surrender and ask the big guns on why my code didn't work in term of debouncing and state change detecting in both account. Any hints and help is much appreciated and i bow my head in defeat in this simple task that i cant seem to wrap my head around.
edited: I have to delete all the comment so that I can fit all the code and all.

PaulS

Code: [Select]
  boolean SwitchState=digitalRead(Switch);
digitalRead() doesn't return a boolean.

In your code, you are reading the pin state and, if it is not the same as some stored state, recording a time. Then, you determine if the difference between now and that event is greater than some small amount. If it is, and if the transition was to pressed, you toggle the led state variable.

You never clear the transition time, so next time around, the difference will be even greater. So, the pin will toggle again.

Arrch

Code: [Select]

 if (millis()-LastDebounceTime>=10UL)
 {
   if (digitalRead(Switch) ==LOW)
   {
     LedState = !LedState;
   }
 }


Keep in mind that first if statement won't just run once. Once the switch has been LOW for more than 10 ms, it will run over and over again, toggling the LED state each iteration.

You need separate "reading" and "state" variables, both current and last for each. The when the reading is stable, that is, it hasn't changed for the specified debounce time, you update the state variable:

Code: [Select]
int currentReading = digitalRead(switchPin);
if (currentReading != lastReading)
 lastDebounceTime = millis();

if (millis() - lastDebounceTime > debounceInterval)
 currentState = currentReading;


You can then check for a signal edge by using the state variables:

Code: [Select]
if (currentState != lastState)
{
 // A debounced signal edge has occured!
}


And of course, you need to update your "last" variables at the end of each loop():

Code: [Select]
lastReading = currentReading;
lastState = currentState;


In this example, currentState, lastState and lastReading all need to persist through the loop() iterations, so they should be static/global.

johncc

Hi ash,

It is useful and important for you to go through the exercise of understanding very well the nature of the loop and state variables representing lastUNDebouncedSwitchState, currentUNDebouncedSwitchState, lastDEbouncedSwitchState, currentDEbouncedSwitchState, lastLedState, currentLedState ...

But after you have eventually learned it well, it is then useful to show you the value of an Object Oriented library :
Code: [Select]

#include <Bounce.h>
...
int ledValue = LOW;
Bounce button = Bounce( BUTTON, 120 );  // 120 msec bounce filter

void loop() {

  button.update();  // do all that state machine crap

  // if you want
  // the led to be on while the button is pressed and
  // the led to be off while the button is released  :
  digitalWrite( LED, ! button.read() );  // note button is active low (between pinX and Ground)

  // OR if you want
  // the led to toggle each time you *press* the button:
  //if (button.fallingEdge()) digitalWrite( LED, ledValue = !ledValue);

  // OR if you want
  // the led to toggle each time you *release* the button
  //if (button.risingEdge()) digitalWrite( LED, ledValue = !ledValue);

}


Cheers,
John

HazardsMind

You actually almost had it, just a few errors that are preventing it from working correctly though. Go back to the two main sketchs and see exactly what both do. You were very close.
My GitHub:
https://github.com/AndrewMascolo?tab=repositories

LarryD

Later on, you may want to look at: http://playground.arduino.cc//Code/Bounce
The way you have it in your schematic isn't the same as how you have it wired up!

ash901226

@PaulS:
I thought that since the nature of digitalRead() return value is between HIGH and LOW, I could use boolean.
now i know better.

@Arrch:

Code: [Select]

  if (millis()-LastDebounceTime>=10UL)
  {
    if (digitalRead(Switch) ==LOW)
    {
      LedState = !LedState;
    }
  }


Keep in mind that first if statement won't just run once. Once the switch has been LOW for more than 10 ms, it will run over and over again, toggling the LED state each iteration.


yes when you say about it, i realize that my understanding towards the program is totally false.

ash901226

Guys I got this to work, and interestingly the first time around it work only that i have press the switch twice to make it work.

Code: [Select]

uint8_t Switch = 2;
uint8_t Led =13;

boolean LedState =LOW;
int SwitchState =0;
int SwitchDebounce;
int LastSwitchState=HIGH;
int LastSwitchDebounce=LOW;

unsigned long LastDebounceTime = 0;
unsigned long DebounceDelay = 50;

void setup()
{
  pinMode(Switch,INPUT);
  digitalWrite(Switch,HIGH);
  pinMode(Led,OUTPUT);
}

void loop()
{
  int CurrentSwitch = digitalRead(Switch);
  if (CurrentSwitch != LastSwitchDebounce)
  {
    LastDebounceTime = millis();
  }
  if ((millis() - LastDebounceTime) > DebounceDelay)
  {
    SwitchDebounce = CurrentSwitch;
    SwitchState = digitalRead(Switch);
    if (SwitchState != LastSwitchState)
    {
      if (SwitchState == LOW)
      {
        LedState = !LedState;
      }
    }
    LastSwitchState=SwitchState;
  }
  digitalWrite(Led,LedState);
  LastSwitchDebounce = CurrentSwitch;
}

Hope you guys could give me some other pointer that i could use to make it more efficient?

i Saw some of the reply saying i could use a library. yes i have Debounce and Bounce library but by using the library i fail to understand how it work only that i know that it work. nothing more then some educational purpose.


HazardsMind

#8
Jan 22, 2013, 10:13 pm Last Edit: Jan 22, 2013, 10:20 pm by HazardsMind Reason: 1
Quote
I was trying to merge both the program together and i came out with this

Hint: Instead of "if (digitalRead(Switch) == LOW)" where you read the button again, why not use the same button state from the first press.

(byte or int, not boolean) SwitchState = digitalRead(Switch);

"if (SwitchState == LOW)"

Also ">=10UL" is usually just "> 50"
My GitHub:
https://github.com/AndrewMascolo?tab=repositories

Arrch

Code: [Select]

    SwitchDebounce = CurrentSwitch;


This is the only time SwitchDebounce is ever used, what exactly are you using it for?

Go Up