Using clickButton for first time - not working for me

I'm setting up a button for the first time and using the previous generation Photon. @peekay123 - tagging you for your knowledge of this library

I got the button working with some test code, but it worked inconsistently - and then found the clickButton library. However, after setting up clickButton when I press the button nothing happens - added some log statements but function always equals 0. Tried some things to get working with no luck which brings me here hoping for help...


Here's the processor board setup:

  • one button pin goes to GND
  • other button pin to D2

For the code, I followed the clickButton sample code as much as possible but here are my key code snippets:

#include <Particle.h>
#include <clickButton.h>

SYSTEM_THREAD(ENABLED); 
SYSTEM_MODE(SEMI_AUTOMATIC);

const uint8_t BUTTON_STARTSTOP_PIN = D2; // Start/Stop button pin
const uint8_t buttonPin = 2;

ClickButton ButtonStartStop(buttonPin, LOW, CLICKBTN_PULLUP); // the Button
int function = 0; // Button results 

void setup() {

    Particle.connect(); // connect to the cloud
    pinMode(BUTTON_STARTSTOP_PIN, INPUT_PULLUP); 
    //ButtonStartStop.debounceTime   = 20;   // Debounce timer in ms
    //ButtonStartStop.multiclickTime = 250;  // Time limit for multi clicks
    //ButtonStartStop.longClickTime  = 1000; // time until "held-down clicks" register
}

void loop() {
    
    Particle.publish("loop before timer check.  timer_on= ", String(timer_on));
    
    /***** Verify the button and buzzer are working properly - commented out*****
    while (digitalRead(BUTTON_STARTSTOP_PIN) == LOW) {
        Particle.publish("Button pushed test");
        digitalWrite(WARNING_LED_PIN, HIGH);          // sets the LED on
        delay(1000);
        digitalWrite(WARNING_LED_PIN, LOW);
        delay(1000);
    }
    *************/

    // Update button state - wait for button push
    ButtonStartStop.Update();

    if (ButtonStartStop.clicks != 0) function = ButtonStartStop.clicks;
    
    if (function == 1 || function == -1) {
        Particle.publish("SINGLE click");
        NUM_SECONDS_WARN_LOW=120; // 2 minutes
    }
    if (function == 2 || function == -2){
        Particle.publish("DOUBLE click");
        NUM_SECONDS_WARN_LOW=300; // 5 minutes
    }
    if (function == 3 || function == -3) {
        Particle.publish("TRIPLE click");
        NUM_SECONDS_WARN_LOW=600; // 10 minutes
    }
    if (function == -1) {
        Particle.publish("SINGLE LONG click");
    }
    if (function == -2) {
        Particle.publish("DOUBLE LONG click");
    }
    if (function == -3) {
        Particle.publish("TRIPLE LONG click");
    }

    Particle.publish("function= ", String(function));

    function = 0;
    delay(5);
}

@LuckGuy, this is an old library which extends the built-in millis() function and is likely not suitable anymore. You may want to use either a "polled" button Arduino library or interrupts to service your buttons. This polled button library by JChristensen with good examples is a good start:

1 Like

:open_mouth:

Ouch, thanks for your help @peekay123! And thanks for the link to another option.

Unfortunately clickButton is one of the libraries that Particle has in it's list when you search for "button".

Hey Particle Support Team - if you're reading this can the clickButton library be removed from the list of libraries?

@LuckGuy, actually, I'm the one who published that library a long time ago in the Spark and Spark Core days!

However, I just realized why your code is not working! You basically call Particle.publish() every 5ms, quickly exceeding the 4 pubs-per-sec limit and causing the cloud to stop publishing until your stream stops for at least 4 secs. The documentation says:

NOTE 1: Currently, a device can publish at rate of about 1 event/sec, with bursts of up to 4 allowed in 1 second. Back to back burst of 4 messages will take 4 seconds to recover.

You may want to use Serial.print() and use the USB with a terminal program (or the Particle CLI) to view your messages instead.

3 Likes

Thanks @peekay123 - Once I took out all blocking statements including Particle.publish and delay() the clickButton works great!

Now it's learning how to delay without blocking - and looks like there's a whole separate set of libraries for that

Hi!

here's a snippet I use a lot, modify 10000 (msec) to fit your needs.
Call executeAfterDelay() from your loop() function, or just embbed the contents in loop().

void executeAfterDelay()
{
    static unsigned long logTime = 0;
    if (millis() - logTime > 10000)
    {
        logTime = millis();
        Log.info("Executing after delay");
        // Do something here
    }
}

Add this at the top of your FW so the logger works properly, right after the imports:

SerialLogHandler logHandler(LOG_LEVEL_INFO);

PS: to execute different things after different delays or events you can use a Finite State Machine

2 Likes