Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 11 of 11

Thread: Question about "delay()"

  1. #1
    Junior Member
    Join Date
    May 2021
    Posts
    7

    Question about "delay()"

    Hiya, folks!
    I've got a footswitch button connected to my Teensy 2.0 and this code is working beautifully, except for one thing: I'd like the "PLAY START" function to start a few milliseconds after the button's been pressed. I'm very, VERY new at this, but from my research it seems like "delay()" is the simplest and best option for me. However, no matter where I place that code, it doesn't work the way I need it to. I've tried putting "delay(1000)" beneath almost every line in the code (see below), one line at a time, and either:
    • nothing happens,
    • the target will play immediately, go for 1 second and then stop (whereas I *want* it to wait for 1 second and then START playing), or
    • I can see that the target is receiving a message of some kind (an indicator light flashes) 1 second after the button is pressed, but then nothing else happens (no play start, etc.).


    All of the above seems to only depend on where the "delay(1000)" code is placed, but I can't make heads nor tails of it. I know I'm missing something; this seems like it should be really simple. Is anyone able to lend a noob like me a hand with this?

    TIA!

    Here's the code:

    Code:
    #include <Arduino.h>
    #include "Button.h"
    
    #define BUTTON_1 PIN_B0
    
    Button *buttons[1];
    
    void setup() {
      buttons[0] = new Button(BUTTON_1);
    }
    
    void sendMMC(uint16_t length, uint8_t* msg) {
      static uint8_t buffer[20] = { 0xf0, 0x7f, 0x7f, 0x06 };
      memcpy(buffer + 4, msg, length);
      buffer[length + 4] = 0xf7;
      usbMIDI.sendSysEx(length + 5, buffer, true);
    }
    
    void loop() {
      if (buttons[0]->update()) {
      // PLAY START
        if (buttons[0]->wasPressed()) {
          sendMMC(1, (uint8_t*)"\x02"); // Play
        }
      // RESET
        if (buttons[0]->wasLongPressed()) {
          sendMMC(1, (uint8_t*)"\x01"); // Stop
          sendMMC(8, (uint8_t*)"\x44\x06\x01\x00\x00\x00\x00\x00"); // Locate zero
        }
      }
      
      while (usbMIDI.read()) {} // ignore incoming messages
    }

  2. #2
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    24,497
    Code:
      // PLAY START
        if (buttons[0]->wasPressed()) {
          //            <----  Try adding the delay here!
          sendMMC(1, (uint8_t*)"\x02"); // Play
        }

  3. #3
    Junior Member
    Join Date
    May 2021
    Posts
    7
    Thanks, Paul! Unfortunately though, when I add the delay there all that happens is that I can see that the target is receiving a message of some kind (an indicator light flashes) 1 second after the button is pressed, but then nothing else happens (no play start, etc.). Do you have any thoughts as to why that might be?

  4. #4
    Senior Member
    Join Date
    Apr 2020
    Location
    DFW area in Texas
    Posts
    266
    Quote Originally Posted by ALDad View Post
    Thanks, Paul! Unfortunately though, when I add the delay there all that happens is that I can see that the target is receiving a message of some kind (an indicator light flashes) 1 second after the button is pressed, but then nothing else happens (no play start, etc.). Do you have any thoughts as to why that might be?
    @ALDad:

    Posting your modified sketch (see Forum Rule above) would make it much easier for anyone else to analyze why it might not be working as you expect.

    So, without benefit of the modified sketch, I'll propose a slightly different approach: since you only want either the short-press or the long-press to be detected with each release of the button, maybe you could try this (which, if my thinking is right, *should* allow a long-press to take precedence over a short-press):

    Code:
    void loop() {
      if (buttons[0]->update()) {
        // check if long-press (RESET) has been detected
        if (buttons[0]->wasLongPressed()) {
          sendMMC(1, (uint8_t*)"\x01"); // Stop
          sendMMC(8, (uint8_t*)"\x44\x06\x01\x00\x00\x00\x00\x00"); // Locate zero
        } else {
          // if a long-press was NOT detected, then check if a short-press (PLAY START) has been detected
          if (buttons[0]->wasPressed()) {
            // if you want a short delay before the PLAY command is sent, then add your call to delay() here (as Paul previously indicated)
            sendMMC(1, (uint8_t*)"\x02"); // Play
          }
        }
      }
      
      while (usbMIDI.read()) {} // ignore incoming messages
    }

  5. #5
    Senior Member
    Join Date
    Aug 2013
    Location
    Gothenburg, Sweden
    Posts
    419
    Try to place a delay(1000) both directly and after before sending the play message.

  6. #6
    Junior Member
    Join Date
    May 2021
    Posts
    7
    Quote Originally Posted by mlu View Post
    Try to place a delay(1000) both directly and after before sending the play message.
    Thanks so much, mlu! It works... sort of. Here's my code:

    Code:
    #include <Arduino.h>
    #include "Button.h"
    
    #define BUTTON_1 PIN_B0
    
    Button *buttons[1];
    
    void setup() {
      buttons[0] = new Button(BUTTON_1);
    }
    
    void sendMMC(uint16_t length, uint8_t* msg) {
      static uint8_t buffer[20] = { 0xf0, 0x7f, 0x7f, 0x06 };
      memcpy(buffer + 4, msg, length);
      buffer[length + 4] = 0xf7;
      usbMIDI.sendSysEx(length + 5, buffer, true);
    }
    
    void loop() {
      if (buttons[0]->update()) {
      // PLAY START
        if (buttons[0]->wasPressed()) {
        delay(1000);  //<---- THIS IS WHERE I ADDED DELAY
          sendMMC(1, (uint8_t*)"\x02"); // Play
        delay(4000);  //<---- THIS IS WHERE I ADDED DELAY
        }
      // RESET
        if (buttons[0]->wasLongPressed()) {
          sendMMC(1, (uint8_t*)"\x01"); // Stop
          sendMMC(8, (uint8_t*)"\x44\x06\x01\x00\x00\x00\x00\x00"); // Locate zero
        }
      }
      while (usbMIDI.read()) {} // ignore incoming messages
    }
    What happens now is that it waits to start playback for 1 second, and then plays for 4 seconds. That's actually fine. The problem is that now the long-press also waits for 4 seconds to work and I need that delay to be much shorter, or none at all. I've tried adding more delay() lines before, after, and both before AND after the "sendMMC" lines in the RESET code, but nothing changes. I've also tried delay() lines ONLY in the RESET code (before and after the "sendMMC" lines, but NOT in the PLAY START code). I think @kd5rxt-mark is right in that I need to somehow separate the different presses more, but unfortunately that code didn't work either.

    Any other thoughts?

  7. #7
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    1,527
    What Button library are you using?

  8. #8
    Junior Member
    Join Date
    May 2021
    Posts
    7
    Quote Originally Posted by luni View Post
    What Button library are you using?
    Here's the Button.cpp I'm using (borrowed code):

    Code:
    #include "Button.h"
    
    Button::Button(int pin) {
      pinMode(pin, INPUT_PULLUP);
      debouncer = new Bounce(pin, DEBOUNCE_DELAY);
      pressedAt = 0;
      isActive = false;
      isLongPress = false;
    }
    
    bool Button::update() {
      bool didChange;
      isLongPress = false;
      didChange = debouncer->update();
      if (debouncer->fell()) {
        pressedAt = millis();
        isActive = true;
      }
      if (debouncer->rose()) {
        isActive = false;
      }
      if (isActive && (millis() - pressedAt) > LONG_PRESS) {
        isActive = false;
        isLongPress = true;
        didChange = true;
      }
      return didChange;
    }
    
    bool Button::wasPressed() {
      return debouncer->fell();
    }
    
    bool Button::wasLongPressed() {
      return isLongPress;
    }

    ...and Button.h (also borrowed):

    Code:
    #include <Arduino.h>
    #include <Bounce2.h>
    
    #ifndef Button_h
    #define Button_h
    
    #define DEBOUNCE_DELAY 10
    #define LONG_PRESS 613
    
    class Button {
    public:
      Button(int pin);
      bool update();
      bool wasPressed();
      bool wasLongPressed();
    
    private:
      Bounce *debouncer;
      long pressedAt;
      bool isActive;
      bool isLongPress;
    };
    
    #endif

  9. #9
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    1,527
    Ok, this is using Bounce in the background. AFAIK you are supposed to call update as often as possible. Your delays (where you don't update the buttons) might confuse the debounce algorithm.

    You can try to place a

    Code:
    void yield()
    {
      buttons[0]-> update()
    }
    after your loop() function. This will call buttons[0]->update() while delay spins. Best to use the version Paul recommended in #2.

    BTW: If you want to get quick help it is always a good idea to post everything needed to reproduce your problem. E.g. you now sent the button.cpp but the button.h is still missing to reproduce your problem....

    EDIT: Sorry, must have overlooked button.h in your post

  10. #10
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    1,527
    Played a bit with your code. The problem is that "wasPressed" is true for a short press and a long press which makes detecting a long press somehow difficult. I changed your button class to be able to distinguish between a short and a long press which makes using it more easy:

    button.h
    Code:
    #include <Arduino.h>
    #include <Bounce2.h>
    
    #ifndef Button_h
    #define Button_h
    
    #define DEBOUNCE_DELAY 10
    #define LONG_PRESS 613
    
    class Button {
    public:
      Button(int pin);
      bool update();
      bool wasLongPressed();
      bool wasShortPressed();
    
      private:
      Bounce *debouncer;
      long pressedAt;
      bool isLongPress;
    };
    
    #endif
    button.cpp
    Code:
    #include "Button.h"
    
    Button::Button(int pin)
    {
        pinMode(pin, INPUT_PULLUP);
        debouncer   = new Bounce(pin, DEBOUNCE_DELAY);
        pressedAt   = 0;
        isLongPress = false;
    }
    
    bool Button::update()
    {
        if (debouncer->update())
        {
            if (debouncer->fell())
            {
                pressedAt = millis();
                return false;
            }
            if (debouncer->rose())
            {
                isLongPress = millis() - pressedAt > LONG_PRESS;
                return true;
            }
        }
        return false;
    }
    
    bool Button::wasShortPressed()
    {
        return !isLongPress;
    }
    
    bool Button::wasLongPressed()
    {
        return isLongPress;
    }
    In your sketch I replaced your MMC calls by simple printouts to visualize what happens.
    Code:
    #include "Arduino.h"
    #include "Button.h"
    
    #define BUTTON_1 0
    
    Button* buttons[1];
    
    void setup()
    {
        buttons[0] = new Button(BUTTON_1);
    }
    
    void loop()
    {
        if (buttons[0]->update())
        {
            // PLAY START
            if (buttons[0]->wasShortPressed())
            {
                // sendMMC(1, (uint8_t*)"\x02"); // Play
                Serial.println("short press detected, now waiting");
                delay(1000);
                Serial.println("Play");
            }
            else if (buttons[0]->wasLongPressed()) // RESET
            {
                Serial.println("RESET");
                // sendMMC(1, (uint8_t*)"\x01");                             // Stop
                // sendMMC(8, (uint8_t*)"\x44\x06\x01\x00\x00\x00\x00\x00"); // Locate zero
            }
        }
        // while (usbMIDI.read()) {} // ignore incoming messages
    }
    Works here (T3.2) without issue. I don't have a T2 for testing but I assume that the code should also run on a T2. Hope that fits your needs

  11. #11
    Junior Member
    Join Date
    May 2021
    Posts
    7
    THANK YOU @luni!!!!! You've solved ALL the problems! I can't tell you how much I appreciate this.


Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •