SimpleTimer Implementation

I’m trying to ditch millis as a timer as I understand it can cause errors with Blynk. I’d like to try to implement SimpleTimer.h in its place. Is there a way to use this library as a timer? Basically, I have a function that needs to be running while the time is less than a specified time. My millis function works as a simple while statement comparing it to the amount of time since the function has been entered. How would I use simpletimer instead?

Yes you can and should be using SimpleTimer with Blynk and that is why it is one of the 4 libraries you should have manually installed when you started Blynking.

Type the following into Google and it will show you how it works:

“SimpleTimer”

@Costas I’ve googled to get a better idea of how it works and I have a rough understanding. I can’t however wrap my head around how to reset the timer. If I call timer.run() at the beginning of my function, will it start at 0?

Just put timer.run() in the loop() to ensure SimpleTimer continues to run.

Stopping and starting is all covered at http://playground.arduino.cc/Code/SimpleTimer

Let us know if you have already studied this and precisely how you want the timer to work and we should be able to provide further guidance.

@Costas My code is listed below. A temperature comparison is what causes the function to be executed (if temp is higher than set point, M_timer1();. This current method of timing is not working. I thought I could use SimpleTimer instead, but I do not understand the examples on the arduino playground. Essentially, I set a time value (M_time) via a Blynk slider widget. This value is multiplied by 60000 to convert it from minutes to seconds in the code. Once the set amount of time has passed, it’ll go to a different function (not loop, it’s just there as a place holder). Please let me know if you need more info and, as always, thanks so much for your help.

void M_timer1()
{
  mDelay = millis() + M_time;
  while (mDelay >= M_time) {

    sensors.requestTemperatures();
    float tempF_1 = sensors.getTempFByIndex(0);
    //float tempF_2 = sensors.getTempFByIndex(1);
    Blynk.virtualWrite(3, tempF_1);
    lcd.setCursor(0, 0);
    lcd.print("[MS 1] T: ");
    lcd.print(tempF_1);
    lcd.print("F)");
    lcd.setCursor(0, 2);
    lcd.print("Elapsed t: ");
    lcd.print(" min");
    Input1 = tempF_1;
    myPID1.Compute();
    unsigned long now = millis();
    if (now - windowStartTime > WindowSize) {
      windowStartTime += WindowSize;
    }
    if (Output1 > now - windowStartTime) {
      digitalWrite(heater, HIGH);
      Blynk.virtualWrite(heaterindicator, 255);
    }
    else {
      digitalWrite(heater, LOW);
      Blynk.virtualWrite(heaterindicator, 0);
    }
  }
  tone(alarm, 2000);
  delay(1000);
  noTone(alarm);
  lcd.clear();
  loop();
}

That’s not a good move now is it?

How so? What would you suggest?

On my stopwatch there are 60 seconds to each minute.

Right, but Arduino reads everything in milliseconds, does it not? So if I have an input of 1 (unitless) from the blynk app, I’d need to put that into milliseconds. Since I’m assigning minutes to the number obtained from the blynk app, I’d need to convert that to milliseconds for the Arduino to understand - hence 1min * (60000milliseconds / 1min).

No, Arduino reads everything in whatever time frame YOU set.
microseconds, milliseconds, mins, hours, years etc and multiplying a minute by 60,000 will not give you seconds. Understand?

Depends what accuracy you need as to what time frames you pass to the Arduino.

I could look through the code you have supplied but I would prefer if you laid out your requirement in words e.g. when temperature is x do something for y duration and then …

Okay. Let me try to lay it out in words.

When temp x is hit, the function I mention above is called. While the time that the function has been running is LESS THAN the set time obtained via Blynk, the code in the while loop will run. Once the time the function has been running is MORE THAN the set time obtained via Blynk, the code jumps out of the while loop and executes another function.

Take a look at the logic in this sketch and the lines marked with // COSTAS are the main lines of code for SimpleTimer. You need to do a sanity check of the code and then use in your sketch.

// SimpleTimerExample.ino by Costas 3/10/2016

#include <SimpleTimer.h>

SimpleTimer timer;
long DurationRequired;
unsigned int triggerTemperature;
int functionCall = 1; // SimpleTimer used to stop and start a function // COSTAS
bool timerHasStarted = false;
int temperatureReading;

void myFunction(){
  // do something  
}

void CheckTemperature(){  // done every 3 seconds
  if((temperatureReading >= triggerTemperature) && (timerHasStarted == false)){
    functionCall = timer.setInterval(DurationRequired, myFunction);     // COSTAS
    timerHasStarted = true;  
  }
  if((temperatureReading < triggerTemperature) && (timerHasStarted == true)){
    timer.disable(functionCall);                                       // COSTAS
    timerHasStarted = false;  
  }
}

void setup() {
  timer.setInterval(3000L, CheckTemperature);  // check temperature every 3 seconds
}

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

@Costas This does not seem like it will work with my code, unfortunately. I don’t want to check the temp all the time, just when a function is called where the temp is relevant. Here are the two functions that run consecutively:

void MS_1()
{
while (digitalRead(floatswitch) == HIGH) {
sensors.requestTemperatures();
float tempF_1 = sensors.getTempFByIndex(0);
//float tempF_2 = sensors.getTempFByIndex(1);
Blynk.virtualWrite(3, tempF_1);
lcd.setCursor(0, 0);
lcd.print(“Step 1”);
lcd.setCursor(0, 2);
lcd.print("temp: ");
lcd.print(tempF_1);
Input1 = tempF_1;
myPID1.Compute();
unsigned long now = millis();
if (now - windowStartTime > WindowSize) {
windowStartTime += WindowSize;
}
if (Output1 > now - windowStartTime) {
digitalWrite(heater, HIGH);
Blynk.virtualWrite(heaterindicator, 255);
}
else {
digitalWrite(heater, LOW);
Blynk.virtualWrite(heaterindicator, 0);
}
if (tempF_1 >= Setpoint1) {
lcd.clear();
MT_1();
}
}
}

/***************************************************************************************************/

void MT_1()
{
while (digitalRead(floatswitch== HIGH)) {
sensors.requestTemperatures();
float tempF_1 = sensors.getTempFByIndex(0);
//float tempF_2 = sensors.getTempFByIndex(1);
Blynk.virtualWrite(3, tempF_1);
lcd.setCursor(0, 0);
lcd.print("[MS 1] T: ");
lcd.print(tempF_1);
lcd.print(“F)”);
lcd.setCursor(0, 2);
lcd.print("Elapsed t: ");

Input1 = tempF_1;
myPID1.Compute();
unsigned long now = millis();
if (now - windowStartTime > WindowSize) {
  windowStartTime += WindowSize;
}
if (Output1 > now - windowStartTime) {
  digitalWrite(heater, HIGH);
  Blynk.virtualWrite(heaterindicator, 255);
}
else {
  digitalWrite(heater, LOW);
  Blynk.virtualWrite(heaterindicator, 0);
}

}
}

If you look, the temp trigger is in that first function (MS_1). Once the set temp is hit, it goes into the MT_1 function. Is there a way to use simpletimer to make MT_1 loop for a set amount of time? I tried implementing your code and realized if I were to call the function for timing within MT_1, it would go to the “check temp” function, and then go back to my MT_1 function, and then go back to check temp…and so on, right?

SimpleTimer calls to functions don’t have to be in setup() but it is common for there to be at least one in setup() to kick off a particular sequence.

I don’t really see that it matters how many functions you have. The first one needs to be linked to a SimpleTimer and then it all follows on from there.

So every X seconds MS_1() function is called, when temperature is at trigger value the timer is disabled and you move on to MT_1() function which can also have it’s own SimpleTimer etc.

Okay @Costas , so I’ve integrated it into my code. Here it is:

void TimerStart() {
  if (timerHasStarted == false) {
    functionCall = timer.setInterval(DurationRequired, MashTimer1);     // COSTAS
    timerHasStarted = true;
  }
  if (timerHasStarted == true) {
    timer.disable(functionCall);                                       // COSTAS
    timerHasStarted = false;
    tone(alarm, 2000);
    delay(1000);
    noTone(alarm);
    lcd.clear();
  }
}

I included the same code as you have in the global deceleration area as well as setup and loop.

void MS_1()
{
  while (digitalRead(floatswitch) == HIGH) {
    sensors.requestTemperatures();
    float tempF_1 = sensors.getTempFByIndex(0);
    //float tempF_2 = sensors.getTempFByIndex(1);
    Blynk.virtualWrite(3, tempF_1);
    lcd.setCursor(0, 0);
    lcd.print("MS 1");
    lcd.setCursor(0, 2);
    lcd.print("HLT temp: ");
    lcd.print(tempF_1);
    Input1 = tempF_1;
    myPID1.Compute();
    unsigned long now = millis();
    if (now - windowStartTime > WindowSize) {
      windowStartTime += WindowSize;
    }
    if (Output1 > now - windowStartTime) {
      digitalWrite(heater, HIGH);
      Blynk.virtualWrite(heaterindicator, 255);
    }
    else {
      digitalWrite(heater, LOW);
      Blynk.virtualWrite(heaterindicator, 0);
    }
    if (tempF_1 >= Setpoint1) {
      lcd.clear();
      TimerStart();
    }
  }
}

/***************************************************************************************************/

void MT_1()
{
  while (digitalRead(floatswitch== HIGH)) {
    sensors.requestTemperatures();
    float tempF_1 = sensors.getTempFByIndex(0);
    //float tempF_2 = sensors.getTempFByIndex(1);
    Blynk.virtualWrite(3, tempF_1);
    lcd.setCursor(0, 0);
    lcd.print("[MS 1] T: ");
    lcd.print(tempF_1);
    lcd.print("F)");
    lcd.setCursor(0, 2);

    Input1 = tempF_1;
    myPID1.Compute();
    unsigned long now = millis();
    if (now - windowStartTime > WindowSize) {
      windowStartTime += WindowSize;
    }
    if (Output1 > now - windowStartTime) {
      digitalWrite(heater, HIGH);
      Blynk.virtualWrite(heaterindicator, 255);
    }
    else {
      digitalWrite(heater, LOW);
      Blynk.virtualWrite(heaterindicator, 0);
    }
  }
}

For some reason, once the set temp is reached in MS_1, it does not seem to start the timer or go into my MT_1 function. Any idea why? BTW I have set the DurationRequired variable to be 10 seconds (10000 milliseconds).

Where is the MashTimer1() function and just show me the single line in setup() you have relating to SimpleTimer.

Sorry, that MashTimer1() function actually says MT_1(). I actually don’t have any line in setup pertaining to simpletimer as the set interval was irrelevant for my code (is this wrong / maybe why it’s not working?).

I need to see how you get into the first function whatever that is.

@costas I get into that first function by pressing a physical button on my circuit. Here’s what that looks like:

void UserIntervention()
{
  while (digitalRead(btn) == HIGH) {
    sensors.requestTemperatures();
    float tempF_1 = sensors.getTempFByIndex(0);
    //float tempF_2 = sensors.getTempFByIndex(1);
    lcd.setCursor(0, 0);
    lcd.print("temp hit.");
    lcd.setCursor(0, 2);
    lcd.print("Do this!");
    tone(alarm, 2000);
    delay(500);
    noTone(alarm);
    Input1 = tempF_1;
    myPID1.Compute();
    unsigned long now = millis();
    if (now - windowStartTime > WindowSize) {
      windowStartTime += WindowSize;
    }
    if (Output1 > now - windowStartTime) {
      digitalWrite(heater, HIGH);
      Blynk.virtualWrite(heaterindicator, 255);
    }
    else {
      digitalWrite(heater, LOW);
      Blynk.virtualWrite(heaterindicator, 0);
    }
  }
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Loading...");
  delay(3000);
  lcd.clear();
  MS_1();
}

@Costas Were you asking how I get into the MS_1() function? Or the TimerStart() function? The TimerStart() function is executed right after MS_1() - at the very end of the function.