0

I want to make debounce for two buttons. So turn on Red led or Green led knowing which button have pressed My program only works for 1 button.

I think that I need a array for two several buttons.

Could anyone help me to improve my code two buttons or more ?

int boton = 11;
int led = 13;

boolean estadoAnterior = LOW;
boolean estadoActual = LOW;
boolean ledOn = false;
int cont=0;
void setup()
{
  pinMode(boton, INPUT);
  pinMode(led, OUTPUT);
  Serial.begin(9600);
}

boolean rebote(boolean eAnterior)
{
  boolean eActual = digitalRead(boton);
  if (eAnterior != eActual)
  {
    delay(5);
    eActual = digitalRead(boton);
  }
  return eActual;
}

void loop()
{
  estadoActual = rebote(estadoAnterior);
  if (estadoAnterior == LOW && estadoActual == HIGH)
  {
    ledOn = !ledOn;
    cont++;
    Serial.println(cont);
  }
  estadoAnterior = estadoActual;

  digitalWrite(led, ledOn);

}
  • show what you have tried – Piglet Sep 29 '17 at 08:54
  • 1
    This is a design issue. With `delay()`, you actually suspend your program, and with only a single thread, there's no way to debounce two buttons using that approach. Sketched solution: Use some timers and state machines instead. –  Sep 29 '17 at 08:55
  • @FelixPalmen Arduino is a bare metal microcontroller, not a PC. Your comment makes no sense. – Lundin Sep 29 '17 at 08:58
  • @Lundin https://github.com/Zirias/shuttercontrol/blob/master/shutterctl_attiny84/buttons.c <- debounce using timers and state machines for an AVR chip -- it **does** make sense, you can do something similar with arduino. –  Sep 29 '17 at 09:00
  • @FelixPalmen No need to write 100 lines of trash to debounce a number of buttons. It is a very simple thing to do. Read all buttons, wait, then read them again. Preferably wait by using on-chip hardware timers. – Lundin Sep 29 '17 at 09:04
  • @Lundin this code does more than just debouncing, in case you didn't notice. It also uses hardware-timers through an abstraction layer. It's just an example what you **could** do. Reading all buttons at once and in the same interval won't be realiable. Also, "read and wait" bears the risk to miss a very short button press. –  Sep 29 '17 at 09:06
  • @FelixPalmen A proper MCU program will have a general-purpose timer driver with a HAL. Then you create a single timer for all buttons, which triggers at certain intervals. When it does, you have a callback function. Either you just read the buttons again, or compare the previous read with the new, or you store the results in a rolling median3 filter (overly careful way to dodge EMI). No need for state machines. – Lundin Sep 29 '17 at 09:10
  • 1
    @Lundin in case you didn't know, this **is** a state machine. It's more or less what my code is doing and it requires storing information about whether the debouncing phase is active and what was the last value read. So please stop your rude comments, thanks. –  Sep 29 '17 at 09:12
  • It's not a state machine. Here's a snippet I wrote for a commercial, mission-critical product that uses the median3 method. Init code and 3 functions. `xxx_val = 0x00; timer_add(xxx_timer, xxx_callback, xxx_READ_MS); ... bool xxx_active (void) { return bool_median3 (xxx_val & 0x07); } inline bool bool_median3 (uint8_t bitfield) { return (bitfield == 3 || bitfield > 4); } static void xxx_callback (void) { xxx_val <<=1; if( (xxx_PORT & xxx_PIN) > 0) { xxx_val |= 0x01; } }` That's all there is. The only code excluded is the timer driver. – Lundin Sep 29 '17 at 09:20
  • Could be easily modified to use several buttons by changing `xxx_val` and the port definitions to arrays. (xxx is called something else in the real code obviously, but its proprietary code) – Lundin Sep 29 '17 at 09:23
  • @Lundin this **is** a state machine. It doesn't matter HOW you do it, but you're storing state and repeated calls to your callbacks use this state. In the code I linked, there's more happening than just debouncing, it also detects very short and very long presses and as such isn't an example I would give in an **answer**, because it's not immediately obvious how just the debouncing works. But no matter what, to do it correctly/reliably, you **need** a) a timer and b) some state. And that's what my first comment was about. –  Sep 29 '17 at 09:27
  • 1
    Also asked at http://forum.arduino.cc/index.php?topic=502885 – per1234 Sep 29 '17 at 13:18

1 Answers1

0

Overall, using a busy-delay is a rather crude way to de-bounce buttons, but it will work for hobbyist purposes.

  • Change estadoAnterior into an array of expected button states.
  • Make an array of ints for the button pins boton. (In real MCU programming, this would be an array of ports + masks.)
  • In the debounce function, make an array of de-bounce bool values for buttons that need debouncing. Check which ones that need debouncing in a loop.
  • If any button needed debouncing, wait 5ms. Not per button, but once. (Btw 5ms may or may not be enough depending on button type)
  • Read that button again and use the result.

A more professional approach might be something along the lines of this.

Once done, rewrite all identifiers to English. We don't use our native language when programming, because that turns the source code into a mess. Your code is some mix of English and your native language, it is very hard to read.

Lundin
  • 195,001
  • 40
  • 254
  • 396