3
\$\begingroup\$

I created state change detection for multiple buttons, which is intended to run on my Arduino for a touchpad project.

In a nutshell, the code makes sure that the Arduino only reacts to button presses and not to holding in the buttons.

My code:

unsigned int buttonStates[] = {0, 0, 0}; unsigned int previousButtonStates[] = {0, 0, 0}; //The Arduino pins for detecting a button press. const unsigned int buttonPins[] = {A3, A4, A5}; void setup() { //Start communication with the serial monitor (console). //9600 is the data transfer speed of USB. Serial.begin(9600); //Wait until the serial port is open, before continuing. while(!Serial); //Defining the buttons as input. for (int i = 0; i < 3; i++) { pinMode(buttonPins[i], INPUT); } } void buttonStateChangeDetect() { for (int i = 0; i < 3; i++) { //Read the button states. buttonStates[i] = digitalRead(buttonPins[i]); //Determines if a button has been released after a press. if (buttonStates[i] != previousButtonStates[i]) { //Checks if the button is pressed. If pressed, the state will change from 0 to 1. if (buttonStates[i] == HIGH) { //The variable i represent a button. 0 is the first button. if (i == 0) { Serial.println("Button 1 is pressed."); } else if (i == 1) { Serial.println("Button 2 is pressed."); } else if (i == 2) { Serial.println("Button 3 is pressed."); } } } previousButtonStates[i] = buttonStates[i]; delay(10); } } void loop() { buttonStateChangeDetect(); } 

Currently, the code works fine but I still see some flaws in my implementation:

  • A lot of if-statements need to be added if the Arduino uses more buttons.
    Example:if(i==3), if (i==4), if(i==5)..
  • The responsiveness of the buttons is dependent on the number of buttons.
    Example: When 30 buttons are used, the for loop will have to loop 30 times and it could be that a button press isn't registered. The higher the index of the button, the higher the chance is that a button press will not be registered or it will take longer to register.

The only idea that came to my mind for improving my code was instead of using if-statements, I could use switch cases. Any other suggestions would be more than welcome.

Extra detail:
The official documentation with a example and my inspiration for writing this code.
Arduino - StateChangeDetection
I created an online example with code. No need for physical hardware if someone wants to try out my code.
Online Arduino Simulation

\$\endgroup\$

    1 Answer 1

    2
    \$\begingroup\$

    Not a review, but an extended comment.

    This is a very common problem. Polling the bunch of event sources is easy to implement, but it leads to the flaws you've discoverd. The only way out is to abandon polling, and switch to interrupts. In your case, consider to

     attachInterrupt(digitalPinToInterrupt(pin), ISR, RISING); 

    for each pin you are interested in, during setup. The ISR shall push a pin which triggered it into a queue. Then the loop would pick the pin numbers from the queue, and do whatever is relevant.

    Be careful with synchronizing the queue between the ISR and the main line. Solving the synchronization is hard, but very enlightening.

    \$\endgroup\$