Questions about Smart Arduino library for debouncing switches and buttons

Do you have a Project Guidance question?

No, it's meant to collect here all the questions about the swich library.

Works very nicely, thanks for the library!

Nice work, Thank you!
My question is how to modify the .cpp, in order to add a Single-Click feature - this could be very, very useful!

The problem is that the singleClick needs to return a TRUE only when there is a Click && doubleClickPeriod is exired.

I thought it would be quite easy, but since I am new to the Arduino I didn't get it to work.
Cheers!

swenodor:
Nice work, Thank you!
My question is how to modify the .cpp, in order to add a Single-Click feature - this could be very, very useful!

Use pushed() for the Single-Click feature.

avandalen:
Use pushed() for the Single-Click feature.

The thing is that pushed() is good when you want to get just the Single-Click. But if you want your button to do one thing on Single-Click, and something different on a Double-Click - that's not an option - Double-Click will be made up from two Single-Clicks, and this would mess things up.

Of course, you can always fix this in the void loop() with some code, but having a singleClick() function is very handy.

Fortunately, I managed to get things working now - and given my coding skills, this should be considered a miracle :slight_smile:

Here's the code:
(you need to modify the Switch.cpp & Switch.h with the lines commented with '// ADDED' or '// REPLACE' below, most of the code is omitted)

/* --------------------------------------------Switch.cpp------------------------------------------------ */
bool Switch::process()											
{ singleClickFlag();						// ADDED these two functions
  calcSingleClick();						// ADDED these two functions
 }
void inline Switch::calcDoubleClick()
{ _doubleClick = false;
  if(_switched && !(debounced^polarity))
  { _doubleClick = (ms - pushedTime) < doubleClickPeriod; // pushedTime of previous push
    dcFlag = (ms - pushedTime) < doubleClickPeriod;		// ADDED flag for double-click
	pushedTime = ms;
	scFlag = false;						// ADDED flag for single-click, nullify on push
	lpFlag = false;						// ADDED flag for long-press, nullify on push
  } 
}
void inline Switch::calcLongPress()
{ _longPress = false;
  if(!longPressDisable)
  { _longPress = on() && ((ms - pushedTime) > longPressPeriod); // true just one time between polls
	longPressDisable = _longPress; // will be reset at next switch
  } 
  else lpFlag=true;						// ADDED condition to flag a long-press
}
//============================================================ ADDED the two functions below
void inline Switch::singleClickFlag()
{ 
  if(_switched && (debounced^polarity)) scFlag=true;		//on release, flag for singleClick action
}
 
void inline Switch::calcSingleClick()
{ _singleClick = false;
  if(scFlag && !dcFlag && !lpFlag)	// conditions for singleClick
  { 
	_singleClick = (ms - pushedTime) >= doubleClickPeriod;	//produce a single click once the doubleClickPeriod is expired
	scFlag=!_singleClick;	//break to exit
  }
}
bool Switch::singleClick() 
{ return _singleClick;
}
/* ------------------------------------------end of Switch.cpp------------------------------------------------ */
/* ------------------------------------------begining of Switch.h--------------------------------------------- */
public:
  bool singleClick();						// ADDED singleClick definition
 protected:
  void inline calcSingleClick();				// ADDED
  void inline singleClickFlag();				// ADDED
//============================================================REPLACE the line below

  bool input, lastInput, equal, deglitched, debounced, _switched, _longPress, longPressDisable, _doubleClick, _singleClick, dcFlag, lpFlag, scFlag;
//============================================================that's it
/* ------------------------------------------end of Switch.h--------------------------------------------- */

Note that a doubleClick() always will be preceded by pushed() from the first push. This can’t be avoided, because then the pushed() function would have to wait on a possible second click, which would introduce an annoying delay. So, the action on doubleClick() has to undone the previous action on pushed().

Hi,
I really like the Switch library, thanks for creating it!
Will you be publishing it on GitHub? If not, I'd be happy to do it.
Thanks!
-dean

blackketter:
Hi,
I really like the Switch library, thanks for creating it!
Will you be publishing it on GitHub? If not, I'd be happy to do it.
Thanks!
-dean

Yes, if you can do that for me!

Ah, I never got notified of your response!

I've uploaded the library here: GitHub - blackketter/Switch: Arduino library for debouncing switches and buttons

Let me know if you have any issues...

avandalen:
Yes, if you can do that for me!

Excellent library

Hello, excellent library. Congratulations ..!!
I want check 4 similar buttons.
The abbreviated code:

Switch ButtonMODE = Switch(PinMODE);
Switch ButtonDOWN = Switch(PinDOWN);
Switch ButtonSET = Switch(PinSET);
Switch ButtonUP = Switch(PinUP);

but I don't want write

/*** CHECK BUTTON MODE ***/
ButtonMODE.poll();
if (ButtonMODE.pushed())
{
..........
}

/*** CHECK BUTTON DOWN ***/
ButtonDOWN.poll();
if (ButtonDOWN.pushed())
{
..........
}

/*** CHECK BUTTON SET ***/
ButtonSET.poll();
if (ButtonSET.pushed())
{
..........
}

/*** CHECK BUTTON UP ***/
ButtonUP.poll();
if (ButtonUP.pushed())
{
..........
}

I want use 'for', for example:
for(x=0;x<=3; x++)
{
/*** CHECK BUTTON x ***/
Buttonx.poll();
if (Buttonx.pushed())
{
..........
}
}

Sorry, but I don´t know C++
Thanks very much ..!!

dang it

Thanks Brittond14
Here is my abbreviated code:

#define BUTTON_A 22
#define BUTTON_B 23
#define BUTTON_A 24
#define BUTTON_C 25

Switch Button[CANT_BUTTONS] =
{
  Switch(BUTTON_A, INPUT_PULLUP, LOW),
  Switch(BUTTON_B, INPUT_PULLUP, LOW),
  Switch(BUTTON_C, INPUT_PULLUP, LOW),
  Switch(BUTTON_D, INPUT_PULLUP, LOW)
};

void setup()
{
     ...
     ...
     ...
     ...

}
  
void loop()
{
   for(byte f = 0; f < CANT_BUTTONS; f++)
   {
      Button[f].poll();
      if (Button[f].pushed())
     {
        ...
        ...
        ...
        ...
      }
   }
}

It is a great library (GitHub - avandalen/avdweb_Switch: Switch library with longPress and doubleClick) and very nice to use.

However, I am looking for an interrupt-driven (instead of polling) version of it: E.g., if there are hours without button activity, the arduino (or esp8266) should not poll the button at all and should be fully free for other activities.

Any hints that someone did the job?

I have just loaded and tried the avdweb_Switch.h library for use on an ESP8266-01.

When I compile it, I get this error

WARNING: library avdweb_Switch-master claims to run on (avr, samd) architecture(s) and may be incompatible with your current board which runs on (esp8266) architecture(s).
Archiving built core (caching) in: C:\Users\JRPICO~1\AppData\Local\Temp\arduino_cache_534881\core\core_esp8266_esp8266_generic_CpuFrequency_80,ResetMethod_ck,CrystalFreq_26,FlashFreq_40,FlashMode_dio,FlashSize_1M512,led_2,LwIPVariant_v2mss536,Debug_Disabled,DebugLevel_None____,FlashErase_none,UploadSpeed_115200_8838c858789fdd4ffb6ec16e5e914eb6.a
Sketch uses 437881 bytes (87%) of program storage space. Maximum is 499696 bytes.
Global variables use 39360 bytes (48%) of dynamic memory, leaving 42560 bytes for local variables. Maximum is 81920 bytes.
warning: espcomm_send_command: wrong direction/command: 0x01 0x00, expected 0x01 0x08

But then it seems to compile to 100%

When the ESP boots, I get this response in serial every 5-10 seconds, or so:

ets Jan 8 2013,rst cause:4, boot mode:(3,6)

wdt reset
load 0x4010f000, len 1384, room 16
tail 8
chksum 0x2d
csum 0x2d
v614f7c32
~ld

Here are code snippets I am using:

#include <FS.h>  // this needs to be first, or it all crashes and burns...
#include "arduino.h"
#include <WebSocketsClient.h>   // get it from https://github.com/Links2004/arduinoWebSockets/releases 
#include <ArduinoJson.h>        // get it from https://arduinojson.org/ or install via Arduino library manager
#include <WiFiManager.h>        // get it from https://github.com/the-real-orca/WiFiManager
#include <WiFiUDP.h>  //get it from https://github.com/esp8266/Arduino/tree/master/libraries/ESP8266WiFi/src
#include "avdweb_Switch.h"  //https://github.com/avandalen/avdweb_Switch

//Switch Contols variables
int GPIO_2 = 2; //To control Device 1
int GPIO_0 = 0; //To control Device 2
const byte RX = 3;  //To manually toggle device 1
const byte TX = 1;  //To manually toggle device 2
const byte buttonTime = 8; //used in debounce
int GPIO_2State; //State of device 1
int GPIO_0State; //State of device 2
int i;

//set up butoon debounce with Switch
Switch RXState = Switch(RX); //button to ground
Switch TXState = Switch(TX); //button to ground
Switch button10ms = Switch(buttonTime, INPUT_PULLUP, LOW, 1); //debounce time is 1ms

void setup(){
...
}

void loop(){
 //Get the state of device pins
 GPIO_2State = digitalRead(GPIO_2); //State of device 1 (on/Off)
 GPIO_0State = digitalRead(GPIO_0); //State of device 2 (on/Off)

 //What to do with button presses
 RXState.poll();
 TXState.poll();

 if(RXState.pushed() && TXState.pushed()) {
   WiFiManager wifiManager;
//    SPIFFS.format();
   delay(1000);
   wifiManager.resetSettings();
   delay(1000);
     ESP.reset();  //reset and try again, or maybe put it to deep sleep
     delay(3000);
     
 } else if (RXState.pushed()){
     digitalWrite(GPIO_2, !GPIO_2State);
     
 } else if (TXState.pushed()) {
       digitalWrite(GPIO_0, !GPIO_0State);
 }

...
}

A couple of questions:

  1. Why does the ESP keep resetting? Have I set something wrong in the void loop()?
  2. What does this do? Is 8 a pin?
const byte buttonTime = 8;
Switch button10ms = Switch(buttonTime, INPUT_PULLUP, LOW, 1); //debounce time is 1ms
  1. Have I appropriately coded my loop so that it will first poll to see if BOTH buttons are pushed, the poll to see if either button is pushed?
  2. Finally, why is it saying it might not be compatible with ESP8266? Is it?

THANK YOU for any support you can offer.

I've been working with the switch library and was having a lot of success until very recently. Suddenly my doubleClick no longer works. I did rebuild my computer and, as such reloaded Arduino IDE and avdweb_switch library using the zip installation process.

Arduino IDE 1.8.5 programming an ESP8266-01. Using pins 1,3 as pushbuttons to ground with external pullup resistor.

I have tried the master and avendalen patch versions of the library found on Github. Please, I am so confused about what happened. Here are the relevant code snippets:

#include <arduino.h>
#include <avdweb_Switch.h>

const byte RX = 3;
const byte TX = 1;


Switch RXState = Switch(RX);
Switch TXState = Switch(TX);

void setup() {
  pinMode(RX, INPUT_PULLUP);
  pinMode(TX, INPUT_PULLUP);
}

voide loop() {
  RXState.poll();
  TXState.poll();

  if (RXState.doubleClick()) {
     // do stuff

   } else if (RXState.longPress()) {
      // do stuff
    
   } else if (RXState.pushed()){
     // do stuff
   }

I've also tried it using just if statements rather than if else statements

#include <arduino.h>
#include <avdweb_Switch.h>

const byte RX = 3;
const byte TX = 1;


Switch RXState = Switch(RX);
Switch TXState = Switch(TX);

void setup() {
  pinMode(RX, INPUT_PULLUP);
  pinMode(TX, INPUT_PULLUP);
}

voide loop() {
  RXState.poll();
  TXState.poll();

  if (RXState.doubleClick()) {
     // do stuff
  }

   if (RXState.longPress()) {
      // do stuff
   }

if (RXState.pushed()){
     // do stuff
   }

In both cases, pushed() and longPress() work, but doubleClick does not. I've also played with the order of if statements...

Thank you for helping.

@swenodor
I just tried the cpp and h modifications you posted and they have done exactly what I need to solve my problem. I hope you will consider compiling the full files and loading them to github as a branch to the original work.
Thank you and avendale for this great library.

Very nice library.
Can I change default time for longPress() and doubleClick() ?
And how.

Thx.