[SOLVED] Virtual button pressed for X seconds

I’m using IOS.

I just tried this but it did not work:

// Button variables
int mashButton = 0; // value read from button
long btnDnTime; // time the button was pressed down
#define holdTime 2000

BLYNK_WRITE(V9) {
  mashButton = param.asInt();
  if (mashButton == 1) {
    btnDnTime = millis();
  }
  if (mashButton == 1 && (millis() - btnDnTime) > long(holdTime)) {
    Alarm();
  }
}

@jeebsinc the code from @Jamin seems to be fine.
Include these items and report back.

#include <SimpleTimer.h>
SimpleTimer timer;
int newTimer = 1;

BLYNK_WRITE(V9){
  if(param.asInt()){
    // button pressed
    newTimer = timer.setTimeout(2000,AlarmOn);
  } 
  else {
    timer.disable(newTimer);
  }
}

void AlarmOn() {
  //tone(alarm, 2000);
  Serial.println("Tone ON");
}

void loop()
{ 
  Blynk.run();
  timer.run();
}

Awesome, @Costas it worked. Quick question: in the global vars, you have int newTimer = 1; Why? Is this just assigning a number to the timer? If I wanted to add another, would I type int newTimer = 2? Although, that wouldn’t make sense because the program wouldn’t be able to differentiate between the timers if they were all newTimer.

You need to understand what is happening, I’ll try to explain:

SimpleTimer timer;

This creates a new object of the class SimpleTimer. You can see an object as a sort of master template which you can use in your code to create instances (basically a working copy of a template).

If you want a second timer instance you need to give it a new name.

Usually setting up multiple timers looks like this:

int timerOne = timer.setTimeout(1000, runThisFunction);
int timerTwo = timer.setInterval(2000, runThatFunction);

Costas already assigned an “ID” to the timer, in my example SimpleTimer will generate those ID’s for you. What this does is creates an instance of the timer object with the name “timerOne” which has the functions of setting a timeout at 1 second and running runThisFunction when it times out. The second one, well, you can imagine :slight_smile:

This is called object oriented programming. It’s not really easy to understand, but once you get you will go “OOOOO, now THAT is a neat trick!” :wink:

@Lichtsignaal thanks, it’s become much more clear. Thanks for that explanation - that is a neat trick. Thanks for all the help @Jamin @Gunner and @Costas!

@jeebsinc some features of SimpleTimer like timeouts and deleting them require them to have a number allocated against them.

Each declaration of SimpleTimer allows up to 10 timers but if you needed 20 it would simply be:

SimpleTimer timer;     // first 10 timers and timer.run(); in loop()
SimpleTimer timer1;   // second 10 timers and timer1.run(); in loop()

This allows the “Simple” part of SimpleTimer to call up to 20 functions at your chosen times intervals for each of the timers. The power functions of SimpleTimer use an allocated number for each timer.

If you wanted a second timer with a timeout, within the first group of 10 timers it would take the following syntax:

int 2ndTimer = 2;  // any name will do as long as you use this for the timeout / deletion etc.

Photo of a buzzer between GND and D2 (GPIO 4) on a WeMos

Full code, just add your normal Blynk stuff

// WeMosBuzzer.ino by @jamin and Costas 3rd Feb 2017 
// see http://community.blynk.cc/t/virtual-button-pressed-for-x-seconds/11379/33
// add all regular Blynk stuff to the sketch

#include <SimpleTimer.h>
SimpleTimer timer;
int newTimer = 1;
int alarm = 4;  // GPIO 4 WeMos D2

void setup(){
  pinMode (alarm, OUTPUT );  
}

BLYNK_WRITE(V9){
  if(param.asInt()){
    // button pressed
    newTimer = timer.setTimeout(2000,AlarmOn);
  } 
  else {
    timer.disable(newTimer);
  }
}

void AlarmOn() {
  Serial.println("Sound Alarm for 3S");
  tone(alarm, 2000, 3000); // sound buzzer a 2000Hz for 3s
}


void loop()
{ 
  Blynk.run();
  timer.run();
}

I’ll look this over when I get back from running some errands. But it looks like it should clear things up for me. Thank you.

It’s got nothing new, just adding the full tone implementation for other Blynkers to use.

I know, but you included a little more theory in the beginning that should be helpful. Thanks!

1 Like

As far as I know SimpleTimer assigns the ID’s itself. It’s not needed to put them there yourself. They can also be called using SimpleTimer functions.

With a static number of timers this is very nice, but if you have a more dynamic approach I think it’s advisable to have SimpleTimer assign it’s own ID’s and use the corresponding functions to do with the timers what you want :slight_smile:

@Lichtsignaal if you don’t allocate the numbers yourselves how would SimpleTimer know which timer to enable / disable / delete etc from a typical setup()?

  timer.setInterval(5000L, function1);
  timer.setInterval(2000L, function2)
  timer.setInterval(1000L, function3); 

These lines only include the function calls so you have “no control” over them without directly allocating a number. So they become:

  timer1 = timer.setInterval(5000L, function1);
  timer2 = timer.setInterval(2000L, function2)
  timer3 = timer.setInterval(1000L, function3); 

and you have full control over them by using the timerX references.

Agree?

Yes, you have to name them, but you don’t have to number them. SimpleTimer assigns them if you don’t. I never do it that way. I just do the timer1 = timer.setEtc

I think the timer1, timer3 etc. part is nothing more than an alias for a int. You declare them like “int timer1 = timer.setInterval” and so on.

Disable a timer with “timer.disable(timer1)”. Easier to read than numbers :slight_smile:

Correct. As you are only declaring them as globals, not a global value, you could, for example just call…

int timer1, timer2, timer3, timer4;

I see what you mean but I think you are still missing a step.
As some timers are not defined in setup() the minimum requirement is that they are defined as a global variable. So to disable the timer you refer to it would be a minimum of:

int timer1; // without this you can’t disable it if it’s not in setup()

We simply allocate a number, in addition, to the variables name so we can keep a tally of how many we have.

int timer1 = 1;

Coders don’t always want to use timer1, timer2, timer3 etc. It might be buzzerTimer, LEDTimer, relayTimer and allocating the specific number to each means you can see just how many you have used.

It’s splitting hairs but there is a logic to it.

Yes, but SimpleTimer provides in that. http://playground.arduino.cc/Code/SimpleTimer#F_getNumTimers with this thing for example.

I agree you need to declare your timers as int (or byte, for that matter, saves a couple bytes of memory :wink: ). You can do the whole setting up timers and declaring them int/byte in one go. SimpleTimer will assign the ID to it. I’m not quit sure for which occasion you would need the specific ID if you can reference to a timer with a readable name, but I agree, it may be splitting hairs and is probably a matter of preference of the coder :slight_smile:

That is not correct, take @Jamin’s example. It will not compile like this:

BLYNK_WRITE(V9){
  if(param.asInt()){
    // button pressed
    newTimer = timer.setTimeout(2000,AlarmOn);
  } 
  else {
    timer.disable(newTimer);
  }
}  

The else doesn’t have a timer to disable so you must declare it beforehand, ergo:

int newTimer = 1;

or

int newTimer;

1 Like

You’re all correct in some way or another.

If you want ot use timer.disable() or timer.enable()… at all… then you must declare it global. Else it just wont work. In my example I chose not to include it… but I should have to help with understanding the compile error.

Costas is also correct. You can declare it global with a value, but the timer will replace it once you declare the same int a timer function.

If you take the PushData example, where it does not declare the timer to a var, then you will have no way to control it, and it will run forever (depending on setTimeout or setInterval)

1 Like

I see what you mean, you have to declare it obviously, but what I meant was, you don’t have to declare them globally to use in functions. They can be scoped to the local function. They do need to exist before messing with them, in that way your example will not work, but if you declare it right before the if, it works fine (provided you do the “int timerNew = timer.set Etc”.

1 Like

Notice that the functions that set timers return an int, which the function descriptions refer to as a “Timer ID”. This is a value that is unique to the individual timer and is meaningful to the SimpleTimer code, but not necessarily to the calling code or to the programmer. In fact, by reading the code, you can find out that a timer ID is just the array index of the timer that was allocated for you, BUT since that isn’t documented, good practice dictates that we do nothing with it other than store it to use for cancelling that same timer later on, if necessary. If you know you won’t be needing to do that, there isn’t even a reason to store it. A timer ID is the equivalent, but better! - of saying, “Hey, you know that timer I set three calls ago? The one that had an interval of 3000ms? Yeah, that one. I’m done with it. Please shut it off and return it to the pool of available timers.” Instead, you save the ID use it to explicitly specify which timer you meant.

You can store a timer ID anywhere, at any scope, that you can store an int, as long as it will still be in scope and undamaged, when & if you need to retrieve it.

I used with your code but after afew times, it not working a void, can explain it, thanks, about 7 or 8 times it went wrong