debounce issue

hello!

Contextualization: Im using my arduino uno to drive my DS1307 based clock, which will show HH:MM:DD, DD/MM and temperature (twelve 7 segment displays).

what i am doing now: i want to use both interrupts to act as increase/decrease functions to set time, alarm, date, etc. im using two simple push buttons.

problem: since im multiplexing, i want to avoid as much as possible coding to increase multiplexing speed. i want to debounce the buttons via hardware.
i have tried:
simple pullup resistor -> no success.
simple pulldown resistor -> no sucess.
pullup and pulldown with capacitor side by side with button (1nF, 10nF, 100nF, 1uF, 10uF) -> no sucess
added a 7414 schmidt trigger -> half sucess.

see the video. when i press the button, the interrupt adds a number correctly to the counter, but when i release it, it stills add to the counter (which shows on the display).
Even with the simple software debouncing i have made, this seems to continue; sometimes the interrupt triggers insanely and the counter goes to like 70 or 80 in 1 button click (as in video).

*ignore thousands of transistors. i will change the 7-segments for bright LEDs after everything is okay.

any idea whay should i do to avoid this with minimum coding?

thanks!


codes im using.

int latchPin = 12;
int clockPin = 13;
int dataPin = 11;
int counter = 0;
int last_push = 0; //usado no debounce
int debounce_time = 100; //milisegundos para o debounce
--- multiplexing stuff ---


void setup() {
  attachInterrupt(0, counter_soma, RISING);
  attachInterrupt(1, counter_subtrai, RISING);
--- multiplexing stuff ---
}

void loop() {
 //this simply prints the number on the counter on a certain display on the board. no big deal. (with shift registers)
  digitalWrite(latchPin, LOW);
  shiftOut(dataPin, clockPin, MSBFIRST, segmento[counter]);
  shiftOut(dataPin, clockPin, MSBFIRST, numero[counter]);
  digitalWrite(latchPin, HIGH);
  }

that's the main block (still a lot of work to do)
now th einterrupts

void counter_soma(){
  if ((millis() - last_push) > debounce_time){
    last_push = millis();
   counter ++;
   Serial.println(counter);
  }
}

void counter_subtrai(){
  if ((millis() - last_push) > debounce_time){
    last_push = millis();
   counter --;
   Serial.println(counter);
  };
}

and now a simple pic of the buttons.

You have power supply issues!. The USB/voltage reg on the card can't supply that much current. So your arduino is browning out or being reset, hence the odd goings on. You need to add extra power for the displays.

Mark

void counter_soma(){
  if ((millis() - last_push) > debounce_time){
    last_push = millis();
   counter ++;
   Serial.println(counter);
  }
}

Don't do serial prints inside an ISR.

but when i release it, it stills add to the counter (which shows on the display).

It is probably bouncing on the way up, so you get more rising interrupts, and your debounce time is now up, so it registers again. You need to check for a state change.

yup! im just using it for debuging now. will remove them.
i will read the following thread. thanks =]

but i still dont know how the counter goes up insanely in a button press with a 150ms debounce time.

You have power supply issues!

im just turning on a 7-segment display at a time (since it is multiplexed), a 7414 and two 595 shift registers. does this consume a lot of current?
on the final stage i will make large displays with LEDs, then i will use an external power supply for them. the shift registers will control the transistors for higher current.

i will try to substitute the +5V power supply from arduino with a 7805 voltage regulator and a DC power supply i have here.

It seems to happen on the second set of LEDs. It doesn't just go up, I think holmes4 is right. Something electrically is going wrong. What do the serial prints say? (since you have put them there)

i still have to create the display control function, but for now they can show any value from 0 to 9 in any display.
the number on the display and the counter read on the serial are the same. the displays can't show any value >=10 and <0 (yet). in the video you can see the display blanking for a while because the counter is in a high value that the display can't show.

algo, i was reading 7414 datasheet and it says it sould work arround 5.5 - 7V, but i saw a lot of projects powering it by 5V.
ohh man, i really need an oscilloscope to see what's going on after the trigger.

Do counter and last push need to be volatile?

counter certainly should be.

i powered the arduino via a 9V 1A power supply (not USB) and the other components via a 7805 voltage regulator (i split the power supply jack in two and connect one of them directly in 7805, not thru Vin pin).

the same thing still happens, so, i think it's not power sypply issues.
i still don't know how the counter goes up. the only place where i ++ the counter is inside the interruption and i can only access it every 150ms. even when i set debounce_time of about 1 o 10s is still happens.

void counter_subtrai(){
  if ((millis() - last_push) > debounce_time){
    last_push = millis();
   counter --;
  };
}

do you think there's a possibility that the shiftOut is interfering in something?

yeah, i removed the shiftout and everything worked just fine (reading the counter number via serial).

so, is seems the shiftOut function is interfering with the interrupts, but why?
if im shifting out some information and i interrupt it, does it resumes the shifting process where it stopped or starts all over?

Why is there a semicolon at the end of this IF statement?

if ((millis() - last_push) > debounce_time){
last_push = millis();
counter --;
};

HazardsMind:
Why is there a semicolon at the end of this IF statement?

if ((millis() - last_push) > debounce_time){
last_push = millis();
counter --;
};

ah, im sorry. i think i put it there while ctrlC ctrlV the code (because i deleted the serial.println. i think i missed the semicolon)
but in the real code it isn't there =]

danilo_mello:
yeah, i removed the shiftout and everything worked just fine (reading the counter number via serial).

so, is seems the shiftOut function is interfering with the interrupts, but why?
if im shifting out some information and i interrupt it, does it resumes the shifting process where it stopped or starts all over?

I'm not 100% on this in the Arduino, though based on the description it seems likely, but usually something like the ShiftOut also uses interrupts, and depending on how it is written, it will run until completion, therefore other code cannot run. Also on a uC, while in an ISR, another ISR of equal or lower priority will not execute. This can cause some timing issues.

Best practice is to have something 'slow' like the shiftOut only happen elsewhere. You might also need to fiddle with your interrupt priorities. Atmel usually uses 3 levels.

mirith:
You might also need to fiddle with your interrupt priorities. Atmel usually uses 3 levels.

Oh? More detail please. How do you change interrupt priorities?

C2:
Do counter and last push need to be volatile?

Did you make "counter" volatile?

mirith:
I'm not 100% on this in the Arduino, though based on the description it seems likely, but usually something like the ShiftOut also uses interrupts, and depending on how it is written, it will run until completion, therefore other code cannot run. Also on a uC, while in an ISR, another ISR of equal or lower priority will not execute. This can cause some timing issues.

Best practice is to have something 'slow' like the shiftOut only happen elsewhere. You might also need to fiddle with your interrupt priorities. Atmel usually uses 3 levels.

on page 57 there's the interrupts priority and EXT 0 and 1 are the 2nd and 3rd priorities, just below RESET.
"RESET has the highest priority, and next is INT0 – the External Interrupt Request 0"
but it seems there's some dark way to change this.

i could disable both interrupts before shifting and activating them after, but with this i could miss the RISING/FALLING edge.


Did you make "counter" volatile?

no, i didn't. i will try with volatile.

okay, so, i added volatile on counter. no change on countr behavior was observed.

i also tried to detach the interrupts before shifting and then activating it after. the bouncing still occurs. maybe i could try to write my own shift out function, but this would increase loop time and mess up with multiplexing.

Interrupts are serviced in a priority order, as documented here:

 1  Reset 
 2  External Interrupt Request 0  (pin D2)          (INT0_vect)
 3  External Interrupt Request 1  (pin D3)          (INT1_vect)
 4  Pin Change Interrupt Request 0 (pins D8 to D13) (PCINT0_vect)
 5  Pin Change Interrupt Request 1 (pins A0 to A5)  (PCINT1_vect)
 6  Pin Change Interrupt Request 2 (pins D0 to D7)  (PCINT2_vect)
 7  Watchdog Time-out Interrupt                     (WDT_vect)
 8  Timer/Counter2 Compare Match A                  (TIMER2_COMPA_vect)
 9  Timer/Counter2 Compare Match B                  (TIMER2_COMPB_vect)
10  Timer/Counter2 Overflow                         (TIMER2_OVF_vect)
11  Timer/Counter1 Capture Event                    (TIMER1_CAPT_vect)
12  Timer/Counter1 Compare Match A                  (TIMER1_COMPA_vect)
13  Timer/Counter1 Compare Match B                  (TIMER1_COMPB_vect)
14  Timer/Counter1 Overflow                         (TIMER1_OVF_vect)
15  Timer/Counter0 Compare Match A                  (TIMER0_COMPA_vect)
16  Timer/Counter0 Compare Match B                  (TIMER0_COMPB_vect)
17  Timer/Counter0 Overflow                         (TIMER0_OVF_vect)
18  SPI Serial Transfer Complete                    (SPI_STC_vect)
19  USART Rx Complete                               (USART_RX_vect)
20  USART, Data Register Empty                      (USART_UDRE_vect)
21  USART, Tx Complete                              (USART_TX_vect)
22  ADC Conversion Complete                         (ADC_vect)
23  EEPROM Ready                                    (EE_READY_vect)
24  Analog Comparator                               (ANALOG_COMP_vect)
25  2-wire Serial Interface  (I2C)                  (TWI_vect)
26  Store Program Memory Ready                      (SPM_READY_vect)

However you don't change the order, nor are there "three priority levels".

im looking up on this topic here:

http://forum.arduino.cc/index.php/topic,46230.0.html
at the specific post
http://forum.arduino.cc/index.php?topic=46230.msg334805#msg334805
maybe i could use a new shiftout function.

he created a function

void shiftOutHP(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, byte val)

but im struggling on the part where he says

To compile it you need the pins_arduino.h and the cbi/turnOffOPWN definitions from wiring_digital.c:

i don't know what to do with the 2nd block of code he posted.
anyone could help? thanks!

I got as far as interrupts for push buttons. Now I can't get the word WHY? out of my head.

You don't need the speed/immediacy or the hassle. No one can possibly tap a button so fast that an even half-decent sketch couldn't read it dozens to 100's of times while taking care of a clock and display. Debounce takes that long.