Re-setting a button count

I cannot get button press count to reset no matter what I do, and switch case defaults immediately. Can anyone help please. Have spent ages on this. I just want to run through specific code options by pressing button.
/*

#include <ezButton.h>

ezButton button(12); // create ezButton object that attach to pin 12

void setup() {
Serial.begin(9600);
button.setDebounceTime(50); // set debounce time to 50 milliseconds
button.setCountMode(COUNT_FALLING);
}

void loop() {
button.loop(); // MUST call the loop() function first

unsigned long count = button.getCount();
Serial.println(count);

if (count >= 4)
count = 0;

  switch(count)
  {

case ‘1’:
Serial.println(“will go to action 1”);
break;

case ‘2’:
Serial.println(“will go to action 2”);
break;

case ‘3’:
Serial.println(“will go to action 3”);
break;

case ‘4’:
Serial.println(“will go to action 4”);
break;
default:
Serial.println(“defaulted”);

  // count=0; 
    
  }

}

In the Arduino IDE, use Ctrl T or CMD T to format your code then copy the complete sketch.

Use the </> icon from the ‘reply menu’ to attach the copied sketch.


what does Serial.println(count); print ?


How is your switch wired ?

Show us a good schematic of your circuit.

Show us a good image of your ‘actual’ wiring.

Give links to components.

This should do what you want for the button…

#include <mechButton.h>

mechButton  button(12); // create mechButton object that attach to pin 12
int         count;

void setup() {
   
   Serial.begin(9600);
   button.setCallback(btnClicked); // set the button's callback.
   count = 0;
}


// Function the button calls when it changes.
void btnClicked(void) { if (!button.trueFalse()) count++; }


void loop() {
   
   idle();                 // MUST call the idle() function first
   if (count > 4) {
      count = 0;
   }
   switch(count) {
      case 0 : break;   // do nothing.
      case 1 : Serial.println("will go to action 1"); break;
      case 2 : Serial.println("will go to action 2"); break;
      case 3 : Serial.println("will go to action 3"); break;
      case 4 : Serial.println("will go to action 4"); break;
      default:
         Serial.println("defaulted");    
   }
}

It uses mechButton instead of ezButton. And it has you keeping the count yourself. If you would like to try it this way, you’ll need to install LC_baseTools from the Arduino IDE library manager.

Good Luck!

-jim lee

1 Like

Thanks very much Jim. I have run your code and it worked first time, with switches working and count now resetting. The serial monitor now prints for instance “will go to action 1” , on first button press-however this message repeats continuously down the screen. I assume due to, for example, case1 being within the loop. Does this mean my action 1 code (not yet prepared ) will be called continuously and if so will this have a negative effect?
Regards
Steve B

Hi Larry,
Thanks for your reply and tips which are very much appreciated. This is my first forum use session but I am amazed at the promptness of the replies. I have just tried Jims code and it seems to do what I want so will get back to you shortly. The code I was using was a suggestion from the Arduino getstarted tutorial so I am intrigued as to why it didnt work for me.
Regards
Steve B

Your code:

Jim’s code:

case 1 : 
Serial.println("will go to action 1"); 
break;

I don’t use libraries for handling switches, they are too limiting and they hide what is happening from the user.

The big difference between your code and Jim’s, your code uses case ‘1’: Jim’s uses case 1:

You should note in C++ ‘1’ (note the two apostrophes) is the ASCII code for the character 1 which is 0x31, you want 1 as an integer number not the ASCII code for 1.


BTW, Please follow the forum guidelines for posting question.

Summary:
In the Arduino IDE, use Ctrl T or CMD T to format your code then copy the complete sketch.
Use the </> icon from the ‘reply menu’ to attach the copied sketch.

Show us a good schematic of your circuit.
Show us a good image of your ‘actual’ wiring.
Give links to components.

I was wondering if you only wanted one call per press… All you need to do is move the call into the clicked function. Like this…

#include <mechButton.h>

mechButton  button(12); // create mechButton object that attach to pin 12
int         count;

void setup() {
   
   Serial.begin(57600);
   button.setCallback(btnClicked);  // set the button's callback.
   count = 0;                       // Inintialise to zero.
}


// Function the button calls when it changes.
void btnClicked(void) {
   
   if (!button.trueFalse()) {
      switch(count) {
         case 0 : Serial.println("will go to action 0"); break;
         case 1 : Serial.println("will go to action 1"); break;
         case 2 : Serial.println("will go to action 2"); break;
         case 3 : Serial.println("will go to action 3"); break;
         case 4 : Serial.println("will go to action 4"); break;
         default:
            Serial.println("defaulted");    
      }
      count++;             // BUmp up count
      if (count > 4) {     // If count is over 4..
         count = 0;        // Reset to zero.
      }
    }
}


void loop() { idle(); }

-jim lee

1 Like

Thanks Jim, your code now does exactly what I was struggling to achieve.
When the call was within the loop, I wondered if that would have had a detrimental effect on the output of the signal generator I am trying to build, which uses a AD9833 breakout board. Each switch case invokes a different waveform output (Sine, Square, triangle, none). I have now tested the first code you gave me, it worked fine I and could not see any detrimental effects on my oscilloscope. However, I will use this second version just incase

Regards

Steve B.

Hi Larry.
I am finding getting to grips with C++ a difficult and slow process, and I thank you for your
very useful information.

Regards
Steve B

Hi Jim,
Please can I ask a question about the 'idle' term which is in the loop of the code you suggested for me.
I can find no mention of it in the Arduino Reference - is it defined within mechbutton library?
The reason I ask is because I have now confirmed that if the AD9833 frequency generator is accessed continually within a loop it does cause some noise on the output waveform. This means that if I want a fixed frequency waveform output, the code you gave me using idle in the loop is ideal for fixed frequency waveforms.
However, if I want to also have an output facility option where I can produce a waveform adjustable in frequency (by using map command and a potentiometer), then that does seem to need to be constantly scanned in a loop and I can just put up with the slight noise for that option. To code this, it seems to mean to me that I maybe need to put some code for the variable frequency option within the loop containing idle, or else have two loops, one with idle and one not.
Is it possible to use 2 loops in an Arduino sketch do you know? and/or can any extra code be put in an 'idle' loop.

Regards

Steve B

idle() is part of LC_baseTools. Certain things use it, mechButton uses it. If you want a square wave? Just use blinker, its already there for you.

From blinker.h

blinker(int inPin=defPin,float inOnMs=defOnMs, float inPeriodMs=defPeriodMs,bool inInverse=false);

Here is the blink without delay_2 example .ino. Shows the basics.

#include "blinker.h"

// So everyone wants newbies to write blink without delay. This is good
// because delay() is bad. Well, here's the simple way to do it..

// Allocate a global blinker object.
blinker aBLinker;             

void setup() {

   // Fire it up.
   aBLinker.setOnOff(true);   
}


void loop() {

   // blinker is an idler. Calling idle() once in loop lets ALL idlers run.
   idle();                    
}

Edit : And yes you can reset those values on the fly using a mapper. And LC_baseTools has.. Float based mappers for you to use as well. Ain't that cool?
Here GitHub - leftCoast/LC_baseTools: Tools to make programming Arduinos easier. at the bottom of this page lists the goodies you have in that bag of tricks you installed.

Put up with noise?! You also get a running average object.

runningAvg(int inNumData);
float addData(float inData);

Set up a smoother..

runningAvg smoother(5);   // Lets say 5 values for now.

Then just read your raw data into it.

float smoothed = smoother.addData(analogRead(A0));

Run the output into your mapper..

float periodMS = periodMapper.map(smoothed);

And the output of that into your blinker.

myBlinier.setPeriod(periodMS);

Maybe not every time through loop(), but once every 100 ms? We have timeObj for that bit as well..

ALl the bits that need to, know how to put themselves into the idle loop.

Enjoy!

-jim lee

1 Like

Thanks for the info Jim. There's a whole lot to investigate now.

Regards
Steve B

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.