Allow manual control (override code) with Blynk button?

I am a beginner to Blynk, and have successfully built a simple water temperature control project. It consists of ESP32, a plug-in water heater, and an AC relay board. The ESP32 controls the relay board, while the water heater is plugged into the relay board.

The code I have will turn on the relay once the water temperature dips below 16C. On the Blynk app, I want to add a button that allows the user to manually control the operation of the relay. But I am stumped as to how to code it. Since I have programmed the ESP to turn off the relay once the temperature is above 16C, if I try to switch it on manually at 20C, for example, the relay will not remain on, because IF statement will fail.

How can I code this to have a manual override capability? So that once the user turns on the button inside the Blynk app, the ESP will allow manual control of the digital pin (delay trigger), and will only revert back to automatic temperature control mode once the button is turned off?

#include <WiFi.h>
#include <WiFiClient.h>
#include <BlynkSimpleEsp32.h>
#include <OneWire.h>
#include <DallasTemperature.h>

#define ONE_WIRE_BUS 14       //data wire connected to pin 14
#define RELAY_PIN 23          //IoT relay connected to pin 23

OneWire oneWire(ONE_WIRE_BUS);       //instance to communicate with any OneWire device

DallasTemperature sensor(&oneWire);        //pass reference to Dallas Temperature object

BlynkTimer timer;       //create Blynk timer object for timed intervals

float waterTemp;        //temperature from DS18B20 in C

char auth[] = "xxxxxxx";    
char ssid[] = "xxxxxxx";     
char pass[] = "xxxxxxx";

void setup() {
  Serial.begin(9600);
  sensor.begin();
  Blynk.begin(auth, ssid, pass);
  sensor.setResolution(9);       //default is 9 bit
  timer.setInterval(1000L, sendTemp);
  pinMode(RELAY_PIN, OUTPUT);
  digitalWrite(RELAY_PIN, LOW);
}

void sendTemp(){
  sensor.requestTemperatures();       //must request reading first
  waterTemp = sensor.getTempCByIndex(0);
  if(waterTemp != DEVICE_DISCONNECTED_C){
    Serial.print("Temp = "); 
    Serial.println(waterTemp);   
    Blynk.virtualWrite(V1, waterTemp);
    if(waterTemp < 16){
      digitalWrite(RELAY_PIN, HIGH);          //turn on IoT relay
    }else{
      digitalWrite(RELAY_PIN, LOW);         //turn off IoT relay
    }
  }else{
    Serial.println("Error: Could not read temperature data");
    Blynk.notify("Error: Could not read temperature data");
    digitalWrite(RELAY_PIN, LOW);
  }
}

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

I’ve modified your code and added some comments to explain the changes I’ve added.
You’ll need to add a switch widget on V2 to switch between auto and manual override mode.

#define BLYNK_PRINT Serial  // Added to give useeful information in the serial monitor
#include <WiFi.h>
#include <WiFiClient.h>
#include <BlynkSimpleEsp32.h>
#include <OneWire.h>
#include <DallasTemperature.h>

#define ONE_WIRE_BUS 14       //data wire connected to pin 14
#define RELAY_PIN 23          //IoT relay connected to pin 23

OneWire oneWire(ONE_WIRE_BUS);       //instance to communicate with any OneWire device

DallasTemperature sensor(&oneWire);        //pass reference to Dallas Temperature object

BlynkTimer timer;       //create Blynk timer object for timed intervals

float waterTemp;        //temperature from DS18B20 in C
int auto_mode = 1;      // Added - flag to show if we are in auto mode (1) or manual override mode (0)

char auth[] = "xxxxxxx";    
char ssid[] = "xxxxxxx";     
char pass[] = "xxxxxxx";

void setup() {
  Serial.begin(115200); // Changed from 9600 to what should be the native baud rate of the ESP32
  sensor.begin();
  Blynk.begin(auth, ssid, pass);
  sensor.setResolution(9);       //default is 9 bit
  timer.setInterval(1000L, sendTemp);
  pinMode(RELAY_PIN, OUTPUT);
  digitalWrite(RELAY_PIN, LOW);
}

// Added - get the value from a switch widget on V2
// this will be the auto/manual switch
BLYNK_WRITE(V2)
{
  auto_mode=param.asInt();  // assign the value from the switch widget to our new variable
}

// Added - Force the Blynk server to trigger the BLYNK_WRITE(V2)callback
// when the device boots-up or reconnects to Blynk
BLYNK_CONNECTED()
{
  Blynk.syncVirtual(V2);
}


void sendTemp()
{
  sensor.requestTemperatures();       //must request reading first
  waterTemp = sensor.getTempCByIndex(0);
  if(waterTemp != DEVICE_DISCONNECTED_C)
  {
    Serial.print("Temp = "); 
    Serial.println(waterTemp);   
    Blynk.virtualWrite(V1, waterTemp);
    Serial.print("Auto Mode = "); // Added for debugging/Information
    Serial.println(auto_mode);    // 1=Auto, 0 = manual override
        
    if(auto_mode == 1)  // Addded - only evaluate these if statements if we are in auto mode...
     {   
      if(waterTemp < 16)
      {
        digitalWrite(RELAY_PIN, HIGH);          //turn on IoT relay
      }
      else  // we gere here if we are in auto mode and the temp is 16 or higher...
      {
        digitalWrite(RELAY_PIN, LOW);         //turn off IoT relay
      }
     }
     else // Added - we get here if we are in manual override mode (auto_mode==0)...
     {
       digitalWrite(RELAY_PIN, HIGH);          //turn on IoT relay no matter what the temperature
     }
  }
  else // We get here if the temp reading failed...
  {
    Serial.println("Error: Could not read temperature data");
    Blynk.notify("Error: Could not read temperature data");
    digitalWrite(RELAY_PIN, LOW);
  }
}

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

I’ve changed the serial baud rate to 115200 which should be the native baud rate of the ESP32 you are using. This means that you’ll see boot-up messages from the ESP32 board in your serial monitor, instead of nonsense characters. You’ll need to set your serial monitor to this new baud rate.

BTW, I’ve not tested these changes :slightly_smiling_face:

Pete.

1 Like