Is possible change setInterval dynamically?

Guys,

I’m building a temperature controller for a refrigerator and I’m not finding the solution to change the void reading time.

My question is as follows. When the temperature gets high, the fridge turns on. When the temperature returns to target, I want the void to run again only after a different time. Something like 10 minutes. So as not to be on and off all the time, since the hysteresis I need is low.

After this time, switch back to standard time.

Any idea?

This is the setInterval:

   timer.setInterval(1000L, controle);

The complete sketch:

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

 Controle da Fermentação
  
************************************************************************************/

#define BLYNK_TEMPLATE_ID "xxx"
#define BLYNK_DEVICE_NAME "Controle Fermentador"
#define BLYNK_AUTH_TOKEN "xxx"
#define BLYNK_PRINT Serial

#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
#include <OneWire.h>
#include <DallasTemperature.h>

char auth[] = BLYNK_AUTH_TOKEN;
char ssid[] = "xxx";
char pass[] = "xxx";

#define geladeira D0
#define aquecedor D1
#define ds18b20 D2

BlynkTimer timer;

int estadoGelad = 0;
int estadoAquec = 0;
int desligaGelad = 0;
int desligaAquec = 0;
int tempo = 0;
int tempAlvo;
float histerese;
float refFrio;
float refQuente;
float tempC;
int tempoLiga;
int tempoLigaMin;
char setIntervCont;
int geladLigada = 0;
int aquecLigado = 0;

// Objeto que tratará da troca de dados com o sensor DS18B20
OneWire oneWire(ds18b20);
DallasTemperature sensors(&oneWire);

//Atualiza os pinos virtuais com os dados salvos no servidor Blynk. Importante em caso de quedas de energia/conexão
BLYNK_CONNECTED() {
  Blynk.syncVirtual(V2, V3, V9);
}

//Recebe comando do Blynk para ligar ou desligar a geladeira manualmente
BLYNK_WRITE(V0)
{
  estadoGelad = param.asInt(); //Recebe 1 para ligar ou 0 para desligar
  
  if (estadoGelad == 1){
    digitalWrite(geladeira, HIGH); // Envia comando para relê ligar a geladeira
    digitalWrite(aquecedor, LOW); // Envia comando para relê desligar o aquecedor
    Blynk.virtualWrite(V1, LOW); // Envia comando para o Blynk desligar o botão do aquecedor manual, se estiver ligado
    Serial.printf("Geladeira ligada manualmente!");
  }
  
  if (estadoGelad == 0)  {
    digitalWrite(geladeira, LOW); // Envia comando para relê desligar a geladeira
    Serial.printf("Geladeira desligada manualmente!");
   }
}

//Recebe comando do Blynk para ligar ou desligar o aquecedor manualmente
BLYNK_WRITE(V1)
{
  estadoAquec = param.asInt(); //Recebe 1 para ligar ou 0 para desligar
  
  if (estadoAquec == 1){
    digitalWrite(aquecedor, HIGH); // Envia comando para relê ligar o aquecedor
    digitalWrite(geladeira, LOW); // Envia comando para relê desligar a geladeira
    Blynk.virtualWrite(V0, LOW); // Envia comando para o Blynk desligar o botão da geladeira manual, se estiver ligado
    Serial.printf("Aquecedor ligado manualmente!");
  }
  
  if (estadoAquec == 0)  {
    digitalWrite(aquecedor, LOW); // Envia comando para relê desligar a geladeira
    Serial.printf("Aquecedor desligado manualmente!");    
  }
}

BLYNK_WRITE(V2) // Parâmetro de temperatura alvo
  {
    tempAlvo = param.asInt();
  }

BLYNK_WRITE(V3) // Parâmetro de histerese
  {
    histerese = param.asFloat();
  }

//Se clicar no botão V5, que é só pra mostrar se a geladeira está ligada ou não, desliga novamente o botão, ou seja, não serve pra ligar a geladeira
BLYNK_WRITE(V5)
  {
    Blynk.virtualWrite(V5, LOW);
  }

//Se clicar no botao V5, que é só pra mostrar se o aquecedor está ligado ou não, desliga novamente o botao, ou seja, não serve pra ligar o aquecedor  
BLYNK_WRITE(V6)
  {
    Blynk.virtualWrite(V6, LOW);
  } 

BLYNK_WRITE(V9)
  {
    tempoLiga = param.asInt();
    tempoLigaMin = tempoLiga * 60000;
    setIntervCont = tempoLigaMin + 'L';
  }

void temperatura()
  {
    sensors.requestTemperatures();
    tempC = sensors.getTempCByIndex(0);
    Blynk.virtualWrite(V4, tempC);  //Envia temperatura (DS18B20) para o Blynk
    refFrio = tempAlvo - histerese; // Define temperatura alvo mais histerese para frio
    refQuente = tempAlvo + histerese; // Define temperatura alvo mais histerese para quente
    Blynk.virtualWrite(V7, refFrio);  //Envia refencia para o Blynk
    Blynk.virtualWrite(V8, refQuente);  //Envia referencia para o Blynk
  }

void tempoPLiga() // Quando a geladeira ligar, vai mudar tempo para 1. Esse void Vai rodar a cada setInterv minutos para voltar para 0. O void controle é rodado pelo tempo = 0
  {
    if (tempo == 1){
      tempo = 0;
    }
  }  

void controle()
  {
    if (tempo == 0){

    if (tempC > refQuente) { // Se a temperatura estiver maior que refQuente, liga a geladeira e desliga aquecedor, se estiver ligado
      digitalWrite(geladeira, HIGH);
      digitalWrite(aquecedor, LOW);
      Blynk.virtualWrite(V5, HIGH);
      Blynk.virtualWrite(V6, LOW);
      Serial.println("Geladeira Ligada");
      Serial.print("Temperatura atual: ");
      Serial.println(tempC);
      Serial.print("Temperatura referência: ");
      Serial.println(refQuente);
      tempo = 1;
      geladLigada = 1;
  } 
    else if (tempC < refFrio) 
  { // Se a temperatura estiver menor que refFrio, liga o aquecedor e desliga geladeira, se estiver ligada
      digitalWrite(geladeira, LOW);
      digitalWrite(aquecedor, HIGH);
      Blynk.virtualWrite(V5, LOW);
      Blynk.virtualWrite(V6, HIGH);
      Serial.println("Aquecedor Ligado");
      Serial.print("Temperatura atual: ");
      Serial.println(tempC);
      Serial.print("Temperatura referência: ");
      Serial.println(refFrio);
      tempo = 1;
      aquecLigado = 1;
  }
  }
  }

void noAlvo() //Desliga geladeira e aquecedor se temperatura dentro do alvo + histerese
  {
    if ((geladLigada == 0) && (aquecLigado == 0)){
    if ((tempC < refQuente) && (tempC > refFrio)){
      digitalWrite(geladeira, HIGH);
      Blynk.virtualWrite(V5, LOW);
      digitalWrite(aquecedor, HIGH);
      Blynk.virtualWrite(V6, LOW);
      Serial.println("Confirma geladeira e aquecedor desligados!");
  }
  }
  }
  
void controleLigados() //Desliga geladeira e aquecedor quando ligados por ultrapassar faixa e voltarem ao alvo
  {
    if (geladLigada == 1){
    if (tempC < tempAlvo){
      digitalWrite(geladeira, LOW);
      Blynk.virtualWrite(V5, LOW);
      geladLigada = 0;
      Serial.print("Geladeira estava ligada... desligada! Temperatura: ");
      Serial.println(tempC);
      }     
    }
    if (aquecLigado == 1){
    if (tempC > tempAlvo){
      digitalWrite(aquecedor, LOW);
      Blynk.virtualWrite(V6, LOW);
      aquecLigado = 0;
      Serial.print("Aquecedor estava ligado... desligado! Temperatura: ");
      Serial.println(tempC);
     }      
    }
  }
  
void setup()
  {
    pinMode(geladeira,OUTPUT);
    pinMode(aquecedor,OUTPUT);
    Serial.begin(9600);
    Blynk.begin(auth, ssid, pass);
    timer.setInterval(1000L, temperatura);
    timer.setInterval(1000L, controle); //60000L
    timer.setInterval(1000L, noAlvo);
    timer.setInterval(1000L,controleLigados); //60000L
    timer.setInterval(1000L, tempoPLiga); //60000L
  }

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

I think you’d need to delete the timer then declare it again with a different time period, but that’s very messy.

A better option might be to use a flag to indicate if the timed function should execute, then have anif statement at the beginning of your timed function to check the status of this flag variable. If it’s true then execute the rest of the code in that function. If not then the function returns.

Then, you set the flag variable to false when your fridge has reached it’s target.
You could use a timeout timer to set the flag back to true after a predefined time.

You might find the Auto/Manual discussion, and the section on Timeout timers in this tutorial useful…

Pete.

Hi Pete,

I’ve tried with using flags but I haven’t figured out how to change the flag after time passes.

I’ll read your article to see if I can find out.

Thanks!

Change it when the timeout timer expires…

  timer.setTimeout(5000L, []() 
  {  
    // Reset your flag in here
  }); 

Pete.

Excellent article @PeteKnight and thanks for the idea!!

The point is that this timer can only start when the fridge turns off. Otherwise, I run the risk of the timer being almost up when it turns off

I liked this part of the article…

timer.disable(control_heater_timer_ID);
timer.enable(control_heater_timer_ID);

I think something can be done with it

It works with timer.disable and timer.enable!!!

Thanks @PeteKnight

Other question:

I want to change the setInterval time via Blynk’s slider but I’m not getting it.

I tried something like this:

long setIntervCont;

BLYNK_WRITE(V9)
  {
    setIntervCont = param.asLong();
    setIntervCont = setIntervCont  * 60000; //
  }

void setup(){
tempoPLiga_ID = timer.setInterval(setIntervCont, tempoPLiga);
}

but Blynk returns this error:

Exception (0):
epc1=0x4000e25d epc2=0x00000000 epc3=0x00000000 excvaddr=0x00000000 depc=0x00000000

Well, void setup will have completed before it gets a value back from the Blynk server, so setIntervCont will be zero at that point.

You would need to put this:
tempoPLiga_ID = timer.setInterval(setIntervCont, tempoPLiga); in BLYNK_WRITE(V9) and add a BLYNK_CONNECTED() function with a Blynk.syncVirtual(V9) command in it.

But, don’t you need to have a timer.disable and timer.enable in BLYNK_WRITE(V9) to force the new duration value work?

Pete.

This is a bit confusing for me… I’ve had a look at BLYNK_CONNECTED and Blynk.syncVirtual and I don’t understand how this will update the timer.

Would it be something like this?

BLYNK_WRITE(V9)
  {
    setIntervCont = param.asLong();
    setIntervCont = setIntervCont  * 60000;
    tempoPLiga_ID = timer.setInterval(setIntervCont, tempoPLiga);
	BLYNK_CONNECTED(){
	 Blynk.syncVirtual(V9)
	}
  }

Even if it is, I don’t understand why this works because from what I’ve read, BLYNK_CONNECTED() returns true or false and Blyn.syncVirtual(V9) simulates pressing a slider.

I’m doing like this:

Temperature above target:

void controle() 
  {
    if (tempC > refQuente) { 
      digitalWrite(geladeira, LOW);
      Blynk.virtualWrite(V5, HIGH);
      timer.disable(controle_ID);
  } 

Temperature on target:

void noAlvo() //Desliga geladeira e aquecedor se temperatura dentro do alvo + histerese
  {
        if (tempC < tempAlvo){
        digitalWrite(geladeira, HIGH);
        Blynk.virtualWrite(V5, LOW);
        timer.enable(tempoPLiga_ID);
        }     
      }

After pass the time:

void tempoPLiga() 
  {
    timer.enable(controle_ID);
    timer.disable(tempoPLiga_ID); 
  }

No, BLYNK_CONNECTED is a stand-alone function called whenever Blynk connects, or re-connects- to the server. You can’t place it inside another function.

No, that’s Blynk.connected()

Yes, it forces the server to send the latest value for the widget in question, which is what you need at start-up, otherwise the variable value is zero.

Pete.

Brightened a little.

Then…

BLYNK_CONNECTED(){
	 Blynk.syncVirtual(V9)
}

Does this cause it to update the setInterval when changing the slider?

Here all right? I thought setInterval would always go in void setup

BLYNK_WRITE(V9)
  {
    setIntervCont = param.asLong();
    setIntervCont = setIntervCont  * 60000;
    tempoPLiga_ID = timer.setInterval(setIntervCont, tempoPLiga);
  }

That way it seems to work but only if I go up or down one by one. If I go up or down two points or more, sometimes it works and sometimes it doesn’t. Also, the Setup timer does not work.

What can it be?

#define BLYNK_TEMPLATE_ID "xx"
#define BLYNK_DEVICE_NAME "Controle Fermentador"
#define BLYNK_AUTH_TOKEN "xxx"
#define BLYNK_PRINT Serial

#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>

char auth[] = BLYNK_AUTH_TOKEN;
char ssid[] = "xxx";
char pass[] = "xxx";

BlynkTimer timer;

int timerid;
long pinValue;

BLYNK_CONNECTED() {
  Blynk.syncVirtual(V9);
}

BLYNK_WRITE(V9)
{ 
pinValue = param.asLong();

timer.disable(timerid);
timerid = timer.setInterval(pinValue * 1000, teste);
timer.enable(timerid);
}

void teste(){
Serial.print("Teste do slider... Intervalo de ");
Serial.print(pinValue);
Serial.println(" segundos!");
}

void testeN(){
Serial.println("Contagem a cada 5 segundos... ");
}

void setup()
  {
    Serial.begin(9600);
    Blynk.begin(auth, ssid, pass);
    timer.setInterval(5000L, testeN);
  }

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

Got it… it’s here for reference if anyone needs it.

#define BLYNK_TEMPLATE_ID "xxx"
#define BLYNK_DEVICE_NAME "Controle Fermentador"
#define BLYNK_AUTH_TOKEN "xxx"
#define BLYNK_PRINT Serial

#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>

char auth[] = BLYNK_AUTH_TOKEN;
char ssid[] = "xxx";
char pass[] = "xxx";

BlynkTimer timer;

int timerid;
int pinValue;

BLYNK_CONNECTED() {
  Blynk.syncVirtual(V9);
}

BLYNK_WRITE(V9)
{ 
pinValue = param.asLong();

timer.deleteTimer(timerid);
timerid = timer.setInterval(pinValue * 1000L, teste);
}

void teste(){
Serial.print("Teste do slider... Intervalo de ");
Serial.print(pinValue);
Serial.println(" segundos!");
}

void testeN(){
Serial.println("Contagem a cada 5 segundos... ");
}

void setup()
  {
    Serial.begin(9600);
    Blynk.begin(auth, ssid, pass);
    timer.setInterval(5000L, testeN);
    timerid = timer.setInterval(1000L, teste);
  }

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

I said in post #2 that this is how I thought you’d need to do it…

Pete.

1 Like