0

I'm struggling with getting the button configuration. Simply, I have a LED controlling setup for a button to increase its brightness when pressed. However, I would like to have it setup like this:

  1. When button is pressed.
  2. change the value by 1,
  3. wait for 500ms,
  4. Then go fast (with the usual void loop time).

Is it something to do with interrupts? If I just write it like below, it actually (obviously) goes by +1 by itself, even when button is not pressed.

void loop() {
  if(digitalRead(button_pressed) == HIGH) {
    current_state = current_state+1;
    delay(500);
    current_state = current_state+1;
  }
}
  • It is not clear to me what you want and what you got. – dannyf Jan 31 '17 at 15:37
  • Simply, as you would imagine volume control for instance. You don't want to have it to randomly detect button presses, I mean - sometimes when you want to press the button just once it would detect it as '3' or more. So generally - when button is pressed and hold - to add "1" by the counter, but if it's pressed >1sec, go with the arduino clock in the void loop, changing the volume fast. – john.novak Jan 31 '17 at 20:55
  • Fairly simple. If thee button IS pressed, increment a button counter, otherwise, reset it. Test the button counter to see if it is bigger than a preset number (that determines how long a long press needs to be). If so, increment volume fast. If not, increment volume slowly. – dannyf Jan 31 '17 at 21:23
1

Non-blocking version.

bool old_button_state = LOW;
void loop()
{
    if(digitalRead(button_pressed) == HIGH)
    {
        current_state = current_state+1

        if( old_button_state==LOW )
            delay(500); // long delay
        else
            delay(100); // short delay

        old_button_state = HIGH;
    }
    else
    {
        old_button_state = LOW;
    }
} 

Simplistic version.

void loop()
{
    if(digitalRead(button_pressed) == HIGH)
    {
        current_state = current_state+1
        delay(500);// long delay

        // repeat while the button is being pressed
        while(digitalRead(button_pressed) == HIGH)
        {
            current_state = current_state+1
            delay(100); //short delay
        }
    }
} 

Ideally you wouldn't just wait for 500ms, but 'break out' of this delay as soon as the button is released.

  • Thanks for that, but seems like it's not doing it's job.. not sure why, but it shows blank at first (I've got LCD to show this value), and when trying to go down with the "down" button, it shows the max. value I have set it up to. – john.novak Jan 31 '17 at 14:31
  • That's what you get when you don't post the entire code :-) . The code above will do nothing will the button is being pressed. So while the button is pressed, the LCD will not be updated. – Gerben Jan 31 '17 at 14:52
  • I added a non-blocking version to my answer. – Gerben Jan 31 '17 at 14:57
  • Still something feels not right :) I mean, I would think of something like "check for the HIGH status being ON for 1 sec, add one step, after 1sec, go with the usual clock rate". That's the hard thing here – john.novak Jan 31 '17 at 19:25
  • I don't quit understand. Doesnt the code work? Or do you want something that doesn't use the delay function? – Gerben Jan 31 '17 at 20:32
1
long timenow, timelong=500;
int current_state = 0;
void increase_state()
{
    current_state++;
    Serial.println(current_state);
}

void loop()
 {
    if(digitalRead(button_pressed)) //button is pressed
    {
        timenow=millis();   //get current time
        increase_state(); // increase by 1
        while (digitalRead(button_pressed)) //check if the button is still pressed
            {
                //rapidly increase "current_state" by 1 if button is pressed more than 500ms with interval of 50ms.
                if ((millis()-timenow)>timelong) 
                {
                increase_state();   
                delay(50);
                }
            }
    }
    delay(500)
 } 

The increment of current_state is always by 1. If button is pressed, it will always increase by 1, but if it's not a long press, you have to wait another 500ms to increase it values again.

  • Could you add a line with Serial monitor to print out the value? As I cannot quite adapt this to my code... let's say that starting value is 0, and then you would add values to it. – john.novak Feb 1 '17 at 13:11
  • answer edited :) – dhimaspw Feb 2 '17 at 1:16
0

Fairly simple.

I thought I would lay out my code here so it is more clear.

if (BTN_PRESSED()) {            //button is pressed now
    btn_cnt += 1;               //increment button counter
    if (btn_cnt >= BTN_LONGPRESS) {
        volume += VOLINC_FAST;  //btn has been pressed for a long time, so increment volume fast
    } else {
        volume += VOLINC_SLOW;                              //otherwise increment the button slowly
    }
} else btn_cnt = 0;             //button is not pressed so reset the counter

It basically follows what I laid out earlier and is self explanatory, I hope.

Formatting needs more work, obviously.

edit: reformatted the code a little bit to make it more readable.

here is an example of this code at work:

enter image description here

here, the code is used to detect a button press (active low) on RA0. Once the button counter (btn_cnt) has been pressed sufficiently long (set by BTN_LONGPRESS), it increments volume by VOLINC_FAST (=4); otherwise, it increments volume by VOLINC_SLOW (=1).

the simulation shows just that. the value of volume is output on PB0..7, to a dac to show more graphically what happens to volume's value.

1) when the button is high (=not pressed), volume is not changed and you see a flat line on the DAC output; 2) when the button is just pressed (but not sufficient to trigger BTN_LONGPRESS), volume is incremented slowly and you see the DAC's output goes up slowly (1 at a time); 3) when the button is pressed long enough, volulme is incremented fast and you see the DAC's output goes up much steeper.

Obviously, you can modulize the code so it can process multiple buttons and return multiple states - not pressed, pressed, long pressed, double pressed. or if you wish, allow it to process bounces.

all sorts of possibilities but the basic idea is the same.

  • I see, but thing with arduino is that you have it all in this "big" void loop, so even if you say it to "add 1", it could detect one button press as "5", and in fact add 1 five times. – john.novak Feb 1 '17 at 13:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.