Ideas on only allowing one button press at a time...

Hi! I´m new here...

I used to code in C about 20 years ago... so as a hobby I´m beginning with Arduino. I´m doing an interface to a DC motor controller.

I got a library from JChristensen (GitHub - JChristensen/JC_Button: Arduino library to debounce button switches, detect presses, releases, and long presses) to deal with button presses, long presses and debouncing.

In one of his examples (up/down counter), short presses in one button increases the counter by one unit, short presses on the other decreases by one. Long presses increase/decrease in a faster rate. And it works properly.

So I´m thinking of using his button library to my project.

My problem is.. (I searched already in google for something similar but couldn´t find an answer so far...)

I´d like to .. when a button is pressed, no other button could interfere with the action of that button. So I want the opposite of multiple presses allowed. I want only a single button allowed at a time...

Let´s say I press the button for the motor to run forward. I´d like to not be possible for pressing both at the same time and the two orders be sent for the motor to run forward and reverse at the same time.

I was trying to adapt his code (which is simple to use) but with no success so far...

So, if anyone could give me a hint on how to perform it... Having multiple buttons (more than two.. in fact maybe 5) but only allowing action on the first pressed and ignoring the others... Or giving me an idea on where to look for it, it would be nice.

If it was possible using this library I´m using it would be better and simpler yet...

Thanks for reading...

This is the example-code I´m using...

I also included the header file and cpp file from the library.

Thanks a lot for reading!

UpDown.pde (3.96 KB)

Button.h (1.79 KB)

Button.cpp (5.38 KB)

Control where your button reads take place if you want other buttons ignored

INTP:
Control where your button reads take place if you want other buttons ignored

Hi! Thanks for the quick answer..

In this code, the buttons (the two of them in this example) are always read in sequence in the beginning of the loop()

How could I do it?

Check the first. I the first was pressed, don´t read the next? Something like that?

What if there are 5 buttons? I´d have to check for all combinations in the beginning of the loop()?

I tried this with the 2 buttons,, but pressing at the same time means a variation of milliseconds between the presses.. If I use a wait() function between each button check, the code slows down...

So as I´m a newbie, I couldn´t do it..

Rimbaldo wrote (in part):

If I use a wait() function between each button check, the code slows down...

What is a wait() function?

In any case, INTP already gave you an answer.

I suppose that you could use millis() or micros() to record the time of all button pushes and only act on the earliest press but you would have to deal with wraparound correctly.

Avoid the delay(...) function or anything that resembles the delay(...) function unless you want to waste the considerable power of an Arduino and really slow down the code.

The question is theoretical until some actual code is properly posted.

vaj4088:
Rimbaldo wrote (in part):

What is a wait() function?

In any case, INTP already gave you an answer.

I suppose that you could use millis() or micros() to record the time of all button pushes and only act on the earliest press but you would have to deal with wraparound correctly.

Avoid the delay(...) function or anything that resembles the delay(...) function unless you want to waste the considerable power of an Arduino and really slow down the code.

The question is theoretical until some actual code is properly posted.

Hi!

Sorry, it was not wait()... it´s the delay() I used between each check that slowed down.. I´m re-learning coding..

I did assume local variables after reading each button and recorded the time with the millis(). But I checked for the time difference between them (couldn´t make it work), not the first one pressed.

But you idea makes a lot of sense. I´ll try to do a check to the earliest push.. Sorry, I´m not native English speaker, so .. what does the "deal with wraparound properly mean?"

Thanks a lot again!

Hi,

The millis() function counts up to a ceiling and then "wraps around"--that is, it resets to zero. Takes about 50 days. So if you're using it to track the time, and your sketch could run for that long, your arithmetic has to account for this.

best,
Michael

I would try to add another variable, buttonBlockedBy (or bbb for short). When 0, all buttons allowed.

When a button is button press is detected, set bbb to button number that is active so you can keep track of which button blocked out the other buttons, and the same button can continue to be allowed.

if (digitalRead(button3)=HIGH && (buttonBlockedBy==0 ||buttonBlockedBy==3)){
  buttonBlockedBy=3
  //code for button3
  }

Keep track of your last keypress and return bbb to 0 after a few seconds.

I am just giving a very simple implementation, there are so many ways you can do it.

  1. Assume you have 5 switches.
  2. Define an array of bool with size 5, says the array name is 'status'
  3. Each switch represents the index of the array. For e.g. switch 1 represent 0, switch 2 represent 1 and so on.
  4. When a button is pressed, you just iterate through the 'status' array and check whether any value is true.
    4.1 True means a button is pressed and action is in progress. So ignore the button press.
    4.2 False means no button is pressed, can respond to a button press, set the index to true. For e.g if switch 1 then status[0]=true, if switch 2 then status[1]=true
  5. Once the respective function associated with the button is finished set the status back to false, say Function1 will execute when Switch 1 pressed. When Function1 finishes set status[0]=false.

All the above steps needed if you want to track which button is pressed.

Another simple approach is

  1. Declare a variable, say anyButtonPressed.
  2. In case any button pressed, set anyButtonPressed to true.
  3. Second time a button pressed check anyButtonPressed is true, if true ignore the button press.
  4. Once the action/function associated to the button finishes, set anyButtonPressed to false, thus allowing other button to perform action.

Its pretty much similar to the answer provided by @Gabriel_swe.

Hope it gives you a starting point.

I assume since you are measuring the press length, you are triggering the count on the release of the button (LOW -> HIGH transition for a button with a pull-up).

In order to implement this properly you need to specify what will happen in edge cases, situations that might be abnormal but are still possible. The devil is in the details with programming. For example, using the two buttons you named (I'll color them), what should happen in these situations:

  1. Hold down UP, press and release DOWN, release UP. It seems pretty obvious that you want this to ignore DOWN and perform the UP action.

  2. Hold down UP, hold down DOWN, release UP, release DOWN. It's trickier when the actions are alternated, but it's an important case to think about. Do you want to ignore DOWN completely because is started being held while UP was pressed, or do you want to accept DOWN because it was released after UP was?

  3. Hold UP, hold DOWN, release UP, press and release UP, release DOWN. Do you ignore the second UP because it was pressed while DOWN was held, or accept it because you decided to completely ignore DOWN in scenario 2? Do you accept or ignore DOWN's release at the end?

FYI
Jacks library is great, another library to review is Nick Gammon's SwitchMonitor.
You may want to download it:
The link is near the bottom of his writeup:

Or this link directly:
http://gammon.com.au/Arduino/SwitchManager.zip

.

Thank you all guys!!

It's a lot for me to try over the weekend!

Thanks so much... Will post in some days if I managed to succeed or not!

:slight_smile:

Ok, using JChristensen library, I managed to do what I want in a practical way....

The only glitch happens sometimes when I hold both buttons for a couple of seconds and release them, and the code acts as there's a buffer os values that are written down on the serial monitor, in sequence, increasing or decreasing, instead of not writing anything. Most of times, maybe depending the way I realease both buttons I get it right..

Any ideas on what's happening?

The code is attached... The headers are on the first post!

Thanks!

UpDown11.ino (3.37 KB)