Need help with timers

I came upon a problem with timers.
If the pump is off and the temperature difference is <2 degrees, it needs to be active for 20 seconds (depends on PumpOnTime),.
After that, if the pump is on and the temperature difference is <2 degrees, it needs to be shut off for 10 seconds (depends on PumpOffTime),

#define BLYNK_PRINT Serial
#include <WiFi.h>
#include <WiFiClient.h>
#include <BlynkSimpleEsp32.h>
#include <OneWire.h>
#include <DallasTemperature.h>

#define ONE_WIRE_BUS 2                    // Data wire is plugged into port 2 on the Arduino
OneWire oneWire(ONE_WIRE_BUS);            // Setup a oneWire instance to communicate with any OneWire devices
DallasTemperature sensors(&oneWire);      // Pass our oneWire reference to Dallas Temperature.

// Addresses of 3 DS18B20s
uint8_t hot[8] = { 0x28, 0x69, 0x7A, 0x25, 0x51, 0x20, 0x01, 0x25 };   //Hot water sensor
uint8_t cold[8] = { 0x28, 0x84, 0x5D, 0x21, 0x51, 0x20, 0x01, 0xE1 };    //Returning cold water
uint8_t boiler[8] = { 0x28, 0xDD, 0xC4, 0x0C, 0x51, 0x20, 0x01, 0xF0 };     //Boiler


// You should get Auth Token in the Blynk App.
char auth[] = "zdn5X3XAlwFU69sOppwOezhjgz6gX0sc";

// Your WiFi credentials.
// Set password to "" for open networks.
char ssid[] = "Teo-4CA03F-Greitasis";
char pass[] = "7035EB8038";

BlynkTimer timer;
WidgetLED Relay_LED(V9);

int RelayPin = 5;
int RelayState = LOW;

long Interval = 1000;

float Hot_s;
float Cold_s;
float Boiler_s;
float Difference;
long previousMillis = 0;
long PumpOnTime = 20000;
long PumpOffTime = 10000;
long OffTime = 0;
long OnTime = 0;


void TemperatureMeasurement()
{
  sensors.requestTemperatures();
  Hot_s = sensors.getTempC(hot);  
  Cold_s = sensors.getTempC(cold);  
  Boiler_s = sensors.getTempC(boiler);   
  Difference = Hot_s-Cold_s;     
}

void ResultsToSerial()
{
  Serial.print("Hot water: ");
  Serial.print(Hot_s);
  Serial.print(" C ");
  
  Serial.print("Cold water: ");
  Serial.print(Cold_s);
  Serial.print(" C ");
  
  Serial.print("Boiler: ");
  Serial.print(Boiler_s);
  Serial.print(" C ");
  
  Serial.print ("Difference:");
  Serial.print(Difference);
  Serial.println(" C ");

  unsigned long OffStart = millis();
  unsigned long OnStart = millis();
  
  if ((RelayState == LOW) &&(Difference >= 2)) {
    Relay_LED.on();
    RelayState = HIGH;
    digitalWrite (RelayPin, RelayState);
    Serial.println("Pump ON");
      
  } else if ((RelayState == LOW) && (Difference < 2) && (OffStart - OffTime >= PumpOffTime)) {
    Relay_LED.on();
    RelayState = HIGH;
    digitalWrite (RelayPin, RelayState);
    Serial.println("Pump On");
    OffTime = OffStart;
    
  } else if ((RelayState == HIGH) && (Difference < 2) && (OnStart - OnTime >= PumpOnTime)){
    Relay_LED.off();
    RelayState = LOW;
    digitalWrite (RelayPin, RelayState);
    Serial.println("Pump Off");
    OnTime = OnStart;
  } 
}

void ResultsToBlynk()
{
  Blynk.virtualWrite(V5, Hot_s);
  Blynk.virtualWrite(V6, Cold_s);
  Blynk.virtualWrite(V8, Boiler_s);
  Blynk.virtualWrite(V7, Difference);
}

void setup()
{
  Serial.begin(9600);
  sensors.begin();
  Blynk.begin(auth, ssid, pass);
}

void loop()
{
  unsigned long currentMillis = millis();
  unsigned long EsamosMillis = millis();
  Blynk.run();
  if (currentMillis - previousMillis > Interval) {
    previousMillis = currentMillis;
    
    TemperatureMeasurement();
    ResultsToSerial();
    ResultsToBlynk();

    
    }
 }

However, there is a problem somewhere in the code. Please take a look at the provided picture for code. The pump turns on for 30 seconds, but after that time period it shuts off for only 1 second. Can somebody help me to correct the code. Thank you.

Dear,

I don't know if you already did it, but just to be sure please replace your Blynk token and wifi info (SSID and pass) to something else.

Also, it is good to use unsigned long for variables that you are going to store millis(). "Even signed long may encounter errors as its maximum value is half that of its unsigned counterpart."

Try using a lambda timer

Example:
Code to turn a pump on
timer.setTimeout (5000L, []()
{
  Code to turn pump off
  Any other actions you want to happen here
});

I think what you are asking for is once pump goes ON it must stay on for 20sec
Once the pump goes OFF it must stay off for 10sec
Try this code. I commented out some of your stuff to check the compile.
You need to keep track of when the timers are running or timed out. The millisDelay class does that for you.
Edit: added the time timeout checks

#include <millisDelay.h>  // included in the SafeString library available from the Library manager
// see also https://www.forward.com.au/pfod/ArduinoProgramming/TimingDelaysInArduino.html

#define BLYNK_PRINT Serial
//#include <WiFi.h>
//#include <WiFiClient.h>
//#include <BlynkSimpleEsp32.h>
//#include <OneWire.h>
//#include <DallasTemperature.h>
//
//#define ONE_WIRE_BUS 2                    // Data wire is plugged into port 2 on the Arduino
//OneWire oneWire(ONE_WIRE_BUS);            // Setup a oneWire instance to communicate with any OneWire devices
//DallasTemperature sensors(&oneWire);      // Pass our oneWire reference to Dallas Temperature.
//
//// Addresses of 3 DS18B20s
//uint8_t hot[8] = { 0x28, 0x69, 0x7A, 0x25, 0x51, 0x20, 0x01, 0x25 };   //Hot water sensor
//uint8_t cold[8] = { 0x28, 0x84, 0x5D, 0x21, 0x51, 0x20, 0x01, 0xE1 };    //Returning cold water
//uint8_t boiler[8] = { 0x28, 0xDD, 0xC4, 0x0C, 0x51, 0x20, 0x01, 0xF0 };     //Boiler
//
//
//// You should get Auth Token in the Blynk App.
//char auth[] = "zdn5X3XAlwFU69sOppwOezhjgz6gX0sc";
//
//// Your WiFi credentials.
//// Set password to "" for open networks.
//char ssid[] = "Teo-4CA03F-Greitasis";
//char pass[] = "7035EB8038";
//
//BlynkTimer timer;
//WidgetLED Relay_LED(V9);

int RelayPin = 5;
int RelayState = LOW; // LOW is OFF

unsigned long Interval = 1000;
millisDelay measureAndPrintDelay;

float Hot_s;
float Cold_s;
float Boiler_s;
float Difference;
unsigned long PumpOnTime = 20000;
unsigned long PumpOffTime = 10000;
millisDelay pumpOnDelay;
millisDelay pumpOffDelay;

void TemperatureMeasurement()
{
//  sensors.requestTemperatures();
//  Hot_s = sensors.getTempC(hot); 
//  Cold_s = sensors.getTempC(cold); 
//  Boiler_s = sensors.getTempC(boiler);   
//  Difference = Hot_s-Cold_s;     
}

void ResultsToSerial()
{
  Serial.print("Hot water: ");
  Serial.print(Hot_s);
  Serial.print(" C ");
 
  Serial.print("Cold water: ");
  Serial.print(Cold_s);
  Serial.print(" C ");
 
  Serial.print("Boiler: ");
  Serial.print(Boiler_s);
  Serial.print(" C ");
 
  Serial.print ("Difference:");
  Serial.print(Difference);
  Serial.println(" C ");

  // if relay off and diff >= 2 AND pump off delay not still running start pump
  if ((RelayState == LOW) &&(Difference >= 2) && (!pumpOffDelay.isRunning())) {
//    Relay_LED.on();
    RelayState = HIGH;
    digitalWrite (RelayPin, RelayState);
    Serial.println("Pump ON");
    pumpOnDelay.start(PumpOnTime); // start ON timer, cannot turn off until this times out
  }
       // if pump on and diff < 2 AND pumpON delay has timed out,  turn pump off
  if ((RelayState == HIGH) && (Difference < 2) && (!pumpOnDelay.isRunning())){
 //   Relay_LED.off();
    RelayState = LOW;
    digitalWrite (RelayPin, RelayState);
    Serial.println("Pump Off");
    pumpOffDelay.start(PumpOffTime); // start Off timer cannot turn ON until this times out
  }

  
}

void ResultsToBlynk()
{
//  Blynk.virtualWrite(V5, Hot_s);
//  Blynk.virtualWrite(V6, Cold_s);
//  Blynk.virtualWrite(V8, Boiler_s);
//  Blynk.virtualWrite(V7, Difference);
}

void setup()
{
  Serial.begin(9600);
//  sensors.begin();
//  Blynk.begin(auth, ssid, pass);
  measureAndPrintDelay.start(Interval);
}

void loop()
{
 if (pumpOffDelay.justFinished()) { // check for timer timeout
}
 if (pumpOnDelay.justFinished()) {
}
 // Blynk.run();
 if (measureAndPrintDelay.justFinished()) {
    measureAndPrintDelay.repeat();  
    TemperatureMeasurement();
    ResultsToSerial();
    ResultsToBlynk();
    }
 }

Just one more thing I noticed, if your are using blynk you have to keep your loop clean, otherwise you will flood the server and thrown off. That is how bkynk works. So all your functions should use a timer in the setup.

Example
timer.setInterval(1000L, TemperatureMeasurement);
//and your loop should be
void loop()
{
  timer.run;
  Blynk.run;
}

#include <millisDelay.h>

I am not sure this is compatible with Blynk. Blynk comes with its own set of timers. Its best to use them, hence I posted about the lambda timer.

It seems the only requirement for BlynkTimer is to call timer.run() in the loop, often.
i.e. next to Blynk.run(). The current sketch does not use any BlynkTimers so there should be no problems.
Blynk.run() is outside any of the millisDelay timers so no effect on that.

Code wise millisDelay is completely independent as it uses millis() and class private variables.

From my scan of the BlynkTimer.h code, I did not see a method call to find out if the timer had expired, which what is needed here. Of course you could code extra variables, set them when you start the timer and then in the BlynkTimer call back clear them to keep track of when the timer finishes, but millisDelay handles all that internally already so no need to add any extra code, just check millisDelay.isRunning().

Blynk has its own protocol of writing code. From experience if not followed it does not work efficiently

http://help.blynk.cc/en/articles/2091699-keep-your-void-loop-clean

The sketch above follows those suggestions.
The gist of that link is

  • Keep the loop responsive so Blynk.run() is called often. My Multi-tasking in Arduino provides a detailed tutorial on how to keep your loop responsive. It also covers how to avoid the often ignore delays due to Serial prints()
  • Don't send data too often.

This code block prevents flooding Blynk with data.

if (measureAndPrintDelay.justFinished()) {
    measureAndPrintDelay.repeat(); 
    TemperatureMeasurement();
    ResultsToSerial();
    ResultsToBlynk();
 }

The repeat Interval is currently set to 1sec (Interval = 1000) which is the same as the mentioned in that Blynk article.

@drmpf whilst I agree with your comment above in fact I use the SafeString library, the OP is using Blynk. Blynk has the option of doing exactly as the OP wants without including further libraries. So I cant see why using a further library is needed.

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