Pages: [1] 2   Go Down
Author Topic: debouncing + interrupt ?  (Read 823 times)
0 Members and 1 Guest are viewing this topic.
Philippines
Offline Offline
Newbie
*
Karma: 0
Posts: 8
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi, im quite new to arduino, and im having a bit of a problem in implementing a debounced interrupt.
So i have 4 leds, which are programmed to light based on a pattern i coded into an array. I have to "pause" the pattern using the pushbutton. However, when i release the button, the result is not always what i expect it to be. Like it jumps to the next pattern, or resets the cycle.

Do you guys have any suggestions for this? I have my attached my code so you can comment on it. Thanks. smiley

Code:

const int buttonPin = 2;     
int led = 13;
int led0 = 12;
int led1 = 11;
int led2 = 10;
//               0,1,2,3,4,5,6,7,8,9,10
int ledArr [] = {0,0,0,0,1,1,1,1,1,1,1};
int ledArr0[] = {0,0,0,1,0,0,0,1,1,1,1};
int ledArr1[] = {0,0,1,0,0,0,1,0,0,1,1};
int ledArr2[] = {0,1,0,0,0,1,0,0,1,0,1};

volatile int  i;
int j = 0;
volatile int buttonState = 0;             
int lastButtonState = LOW;   


long lastDebounceTime = 0; 
long debounceDelay = 40;   


void setup() {
  Serial.begin(9600);
  pinMode(buttonPin, INPUT);
  pinMode(led, OUTPUT);
  pinMode(led0, OUTPUT);
  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
  digitalWrite(buttonPin, LOW);
  attachInterrupt(0, doNothing, RISING);

}

void loop() {
  ledPattern();
 
 
}


void debounceThis(){
  int reading = digitalRead(buttonPin);
  if (reading != lastButtonState) {
   
    lastDebounceTime = millis();
  }
 
  if ((millis() - lastDebounceTime) > debounceDelay) {   
    buttonState = reading;
  }
  lastButtonState = reading;

}

void ledPattern(){
    for (i = 0; i < 11; i++){
      debounceThis();
      if(buttonState == 0){
      delay(400);
      digitalWrite(led2, ledArr[i]);
      digitalWrite(led1, ledArr0[i]);
      digitalWrite(led0, ledArr1[i]);
      digitalWrite(led, ledArr2[i]);
         
      Serial.println(i); 
     }
  }
 
 
}

void doNothing(){
 buttonState != buttonState;
 Serial.print("i during ISR: ");
 Serial.println(i);
 
 
}


* EXER2.ino (1.41 KB - downloaded 4 times.)
« Last Edit: February 24, 2013, 04:11:16 am by ajdimaano » Logged

East Anglia (UK)
Offline Offline
Faraday Member
**
Karma: 90
Posts: 3512
May all of your blinks be without delay()
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Serial.print in an ISR ?

NO !
Logged

Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

Philippines
Offline Offline
Newbie
*
Karma: 0
Posts: 8
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I'm really sorry for that. I was trying to see at what part of the array it was when i push the button, so there. I'm completely new at this.  smiley
Logged

Offline Offline
Edison Member
*
Karma: 57
Posts: 2078
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

This is a simple debounce, using millis(), http://arduino.cc/en/Tutorial/Debounce
Logged

Seattle, WA USA
Online Online
Brattain Member
*****
Karma: 551
Posts: 46213
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Why are the arrays ledArr, ledArr0, etc. int, when they only hold 0 or 1. Perhaps you could make them long and waste twice as much space.
Logged

Philippines
Offline Offline
Newbie
*
Karma: 0
Posts: 8
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
This is a simple debounce, using millis(), http://arduino.cc/en/Tutorial/Debounce

That's the one I used for this..

Quote
Why are the arrays ledArr, ledArr0, etc. int, when they only hold 0 or 1. Perhaps you could make them long and waste twice as much space.

I don't know what you meant by that, but is there a way  I could make it more efficient? What I would like to do with it is to pause the pattern when i hold the button, and resume to where it left before it responded to the interrupt. Thanks. smiley
Logged

Seattle, WA USA
Online Online
Brattain Member
*****
Karma: 551
Posts: 46213
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

You should always use the smallest size variable that can hold the data that you need to hold. All your values are either 0 or 1. If you look at the reference page, you can see a list of types. Look at each one, and see what range of values that type can hold. Then, determine if there are smaller types that can hold the value, or not. If so, use the smaller type. The types that can hold integer values are byte, int, long, and long long. Which ones can hold the values that you have? What are the sizes? Which is the smallest? Which is, therefore, the most appropriate?
Logged

Philippines
Offline Offline
Newbie
*
Karma: 0
Posts: 8
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I will keep that in mind sir. Thank you. smiley

Do you have any suggestions for my problem? smiley
I'm still at it, but unfortunately, I can't figure this one out. Is the problem with the array? Should I find another way to code the pattern?
Logged

Seattle, WA USA
Online Online
Brattain Member
*****
Karma: 551
Posts: 46213
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

You are polling the switch, to determine if it is bouncing. Why do you also need an interrupt? The interrupt is NOT being debounced.

Why is the interrupt service routine called doNothing()? If it really did nothing, there would be no point in calling it.
Logged

Philippines
Offline Offline
Newbie
*
Karma: 0
Posts: 8
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Okay, so i thought by interrupting the for loop, I would be able to pause it, because that's what I think interrupting does. Am I right? What I mean is, at whatever 'i' in the for loop is at, whenever I hold the button, it would pause incrementing, and instead do whatever is in the function called in the attachInterrupt(), and then resume at whatever value it left off. So.. you're saying that i do not need to debounce the button? I'm a bit confused.

I tried to compare the value of i during the loop and when I hold the button. As I pressed on it, the value would still increment by at least 2, and then stop. And when I release it, the LED pattern is not what it should be.  

Oh, and I named the function doNothing() because it really does nothing but to hold the state at which the LEDs are at when I hold the button. At least that's what I intend it to do. Yeah, I think I should rename that. Thanks again. smiley
« Last Edit: February 24, 2013, 03:09:31 pm by ajdimaano » Logged

Seattle, WA USA
Online Online
Brattain Member
*****
Karma: 551
Posts: 46213
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Okay, so i thought by interrupting the for loop, I would be able to pause it, because that's what I think interrupting does. Am I right?
No. You are in the middle of cooking dinner, stirring the gravy (that's a for loop). The phone rings (that's an interrupt). What do you do when you end the phone call? Have a beer and a cigar? No, you return to stirring the gravy (hoping it hasn't burned and lumped).
Logged

Philippines
Offline Offline
Newbie
*
Karma: 0
Posts: 8
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

So.. is there any way I could turn off the stove and turn it on again once i finish the call? smiley
Logged

Seattle, WA USA
Online Online
Brattain Member
*****
Karma: 551
Posts: 46213
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
So.. is there any way I could turn off the stove and turn it on again once i finish the call?
Of course, though that really is not necessary. Each pass through the loop in ledControl() you could listen for the phone to ring (the switch was pressed). If the phone is ringing, return (to loop()), turning off the stove (leds) as needed.

There really is no need for an interrupt in this program.
Logged

Philippines
Offline Offline
Newbie
*
Karma: 0
Posts: 8
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
There really is no need for an interrupt in this program.

Our professor requires it though. smiley-neutral

And in the next part of this exercise, I should be able to reverse the pattern (using a dip switch) and also pause it.

I think I should try a new approach for this. I'll post my code once I get it to work properly. smiley

Thanks for the answers!
Logged

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 452
Posts: 18694
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Our professor requires it though. smiley-neutral

Well, in that case ...  smiley

In the interrupt routine call micros or millis to see if enough time has elapsed since the last interrupt to amount to a debounce. If not, ignore it.

eg.

Code:
interrupted: note time
interrupted again: if less than (say) 10 mS has elapsed, ignore it (debounce)
interrupted again: more than 10 mS has elapsed, process it (and note time again)

Logged

Pages: [1] 2   Go Up
Jump to: