Help with IF statement and global /local variables

Hi all,
Im using an ESP32 and trying to make a heater thermostat that checks the temperature, sends an RF signal to turn on and off the heater. Im stuck with what I thought would be a super simple part! I`m using Blynk which is new to me and whilst playing with arduino for years, I only just get by so probably something simple!

I`ve put all my code below which individually all works. The RF signal can be sent, the temperature is being read OK. I have an overall ON OFF button in blynk which is a switch in the app that writes to Virtual Pin 2.

The issue is this: I`ve got a global variable called “HeaterFlag” which I define right at the start of the code.

I use Blynk_write on V2 which flips a variable called HeaterFlag - it turns off and on an LED and also writes the value of HeaterFlag 1 and 0. This ALWAYS works. When I press the button in blynk, the LED correctly switches and the HeaterFlag correctly shows 0 or 1. However the error below occurs when I put the IF statement in the main loop, then the LED still comes on and off but HeaterFlag is constantly 0.

BLYNK_WRITE(V2) {
  // any code you place here will execute when the virtual pin value changes

  HeaterFlag=!HeaterFlag;
  ledState=!ledState;

  digitalWrite(LED, ledState);
  Serial.print("HeaterFlag: ");
  Serial.println(HeaterFlag);
}

In my main loop Ive got an IF statement which uses HeaterFlag. Im basically trying to say if HeaterFlag is on, I want the code in the loop to run and send an RF signal. When I boot up the board the HeaterFlag is 0 but then immediately changes to 1 and the loop code ALWAYS runs! It is driving me crazy and cant see why. However what is mad is that when I press the button I still get HeaterFlag 0 and it wont change and yet the LED is doing what it should do. It is like the HeaterFlag is not being set as a global variable and the heaterflag is just doing its own thing in the main code!

Can anyone explain why.
Ive also snipped some of the serial monitor as well to show you. The single "HeaterFlag" lines are just coming from the BlynkWrite function when I hit the button in the app but as you can see it isnt setting it as a global variable! When I remove the “If Statement” in the main loop, the heater flag sets properly but then Im obviously not using the IF and my code isnt doing what is should.

Thanks in advance!

SERIAL MONITOR:

Set temperature:35 Min temperature:15 Room temperature:15.75 HeaterFlag:1
Set temperature:35 Min temperature:15 Room temperature:15.75 HeaterFlag:1
Set temperature:35 Min temperature:15 Room temperature:15.75 HeaterFlag:1
HeaterFlag: 0
Set temperature:35 Min temperature:15 Room temperature:15.75 HeaterFlag:1
Set temperature:35 Min temperature:15 Room temperature:15.75 HeaterFlag:1
HeaterFlag: 0
Set temperature:35 Min temperature:15 Room temperature:15.75 HeaterFlag:1
HeaterFlag: 0

Full code.


#define BLYNK_TEMPLATE_ID "TMPL5aPhEfQeM"
#define BLYNK_TEMPLATE_NAME "20B18 Temp Semsor"
#define BLYNK_FIRMWARE_VERSION "0.1.0"
#define BLYNK_PRINT Serial
#define APP_DEBUG  //#define BLYNK_DEBUG
#define BLYNK_PRINT Serial
#define ONE_WIRE_BUS 4  // Your ESP8266 pin (ESP8266 GPIO 2 = WeMos D1 Mini pin D4)
#define LED 2           //this is the onboard LED for testing

#include "BlynkEdgent.h"
#include <OneWire.h>
#include <DallasTemperature.h>
#include <RCSwitch.h>

OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
BlynkTimer timer;
RCSwitch mySwitch = RCSwitch();  //switches the heater on and off

char ssid[] = "I`ve removed this because its personal info;
char pass[] = I`ve removed this
char auth[] = I`ve removed this

float roomTemperature;    // Room temperature in F
bool HeaterFlag = false;  // if this is ON, the thermostat will work, if not, the transmitter is not running
bool ledState = false;    //initiate the LED as off

//delay without delay setup
unsigned long previousMillis = 0;
unsigned long heaterInterval = 3000;

//setup of the RF TX
int transmitterValue;                  //somewhere to put the on/off code
int txOFF = 001111101010110101010100;  //off signal for TX
int txON = 001111101010110101011000;   //on signal for TX
int tempRange = 20;                    // THIS IS THE BUFFER/RANGE BETWEEN HIGH AND LOW/ON AND OFF
int setTemp = 35;                      // THIS IS THE SET TEMPERATURE
int lowTemp = setTemp - tempRange;

void setup() {
  // setup Transmitter info
  mySwitch.enableTransmit(12);   // Transmitter is connected to Pin #12
  mySwitch.setPulseLength(415);  // Transmitter pulse length.
  // mySwitch.setProtocol(2);// set protocol (default is 1, will work for most outlets)
  mySwitch.setRepeatTransmit(15);  // repetitions of transmissions to ensure transmit.

  Serial.begin(9600);  // Debug console
  Blynk.syncVirtual(V2);
  Blynk.begin(auth, ssid, pass);
  sensors.begin();                      // Starts the DS18B20 sensor(s).
  sensors.setResolution(10);            // More on resolution: http://www.homautomation.org/2015/11/17/ds18b20-how-to-change-resolution-9101112-bits/
  pinMode(LED, OUTPUT);                 //setup the test LED
  timer.setInterval(2000L, sendTemps);  //sets the temp sending frequency 2s
}

//Read TemperatureFunction
void sendTemps() {
  sensors.requestTemperatures();                 // Polls the sensors.
  roomTemperature = sensors.getTempCByIndex(0);  // Stores temperature. Change to getTempCByIndex(0) for celcius.
  Blynk.virtualWrite(1, roomTemperature);        // Send temperature to Blynk app virtual pin 1.
}


//This is the function which turns on and off the thermostat function.
BLYNK_WRITE(V2) {
  // any code you place here will execute when the virtual pin value changes

  HeaterFlag=!HeaterFlag;
  ledState=!ledState;

  digitalWrite(LED, ledState);
  Serial.print("HeaterFlag: ");
  Serial.println(HeaterFlag);
}

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

  if (HeaterFlag = true) {  //ONLY RUN IF THE HEATERFLAG IS TURNED ON
    unsigned long currentMillis = millis();
    if (currentMillis - previousMillis > heaterInterval) {
      previousMillis = currentMillis;
      Serial.print("Set temperature:");
      Serial.print(setTemp);
      Serial.print(" Min temperature:");
      Serial.print(lowTemp);
      Serial.print(" Room temperature:");
      Serial.print(roomTemperature);
      Serial.print(" HeaterFlag:");
      Serial.println(HeaterFlag);

      if (roomTemperature > setTemp) {  //if the temp reading is higher than the set temp, turn off the heater
        mySwitch.send("001111101010110101010100");
        Serial.println("OFF SIGNAL SENT");
      }

      if (roomTemperature < lowTemp) {  //if the temp reading is lower than the low temp buffer reading, turn the heater on.
        mySwitch.send("001111101010110101011000");
        Serial.println("ON SIGNAL SENT");
      }
    }
  }
}


This is the cause of the problem you e described. It should say…

if (HeaterFlag == true)

One equals sign makes the value of HeaterFlag equal to true.
Two equals signs test whether HeaterFlag is true or not.

But, sadly, that’s not the end of your problems by any means :slightly_frowning_face:

You should start by reading this…

Also, I suspect that you’d be better-off getting the value of the switch widget by using the param.asInt() functionality in your BLYNK_WRITE() function so that you actually synchronise the switch widget with the state of your heater status, rather than simply inverting HeaterFlag each time you press the widget button.

You might also want to use BLYNK_CONNECTED() and Blynk.syncVirtual(VPin) to synchronise your device with the Blynk app on startup/re-connection.

More on all of this in the documentation.

Pete.

@PeterKnight thank you so much for that help and advice. I read the document you sent me and removed all the code from the main loop. I have also changed the if statement to == which was very stupid of me. Ive also spent a lot of time figuring out param.asInt() and this now makes sense and Ive also implemented this. The code is now functioning as it should. Again, I cant thank you enough. Ive been pulling my hair out with this for the last few evenings.

You obviously know your stuff and Id love to take your advice and impliment the BLYNK_CONNECTED() and Blynk.syncVirtual(VPin). Ive genuinely spent some time reading the help documents and even searching the forums where quires about these functions have been asked. In all honesty, I still don`t really understand fully what they are and where or how they should be implemented in my code.

Thanks again, my working code:

#define BLYNK_TEMPLATE_ID "TMPL5aPhEfQeM"
#define BLYNK_TEMPLATE_NAME "20B18 Temp Semsor"
#define BLYNK_FIRMWARE_VERSION "0.1.0"
#define BLYNK_PRINT Serial
#define APP_DEBUG  //#define BLYNK_DEBUG
#define BLYNK_PRINT Serial
#define ONE_WIRE_BUS 4  // Your ESP8266 pin (ESP8266 GPIO 2 = WeMos D1 Mini pin D4)
#define LED 2           //this is the onboard LED for testing
#include "BlynkEdgent.h"
#include <OneWire.h>
#include <DallasTemperature.h>
#include <RCSwitch.h>

OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
BlynkTimer timer;
RCSwitch mySwitch = RCSwitch();  //switches the heater on and off

char ssid[] = "SKYHE6PV";
char pass[] = "PKDdN9PiigRu";
char auth[] = "xB-GYRvJxObr9ZGhRTXZxZiWPt8lpLxG";

float roomTemperature;    // Room temperature in F
bool HeaterFlag = false;  // if this is ON, the thermostat will work, if not, the transmitter is not running
bool ledState = false;    //initiate the LED as off

//delay without delay setup
unsigned long previousMillis = 0;
unsigned long heaterInterval = 3000;

//setup of the RF TX
int transmitterValue;                  //somewhere to put the on/off code
int txOFF = 001111101010110101010100;  //off signal for TX
int txON = 001111101010110101011000;   //on signal for TX
int tempRange = 20;                    // THIS IS THE BUFFER/RANGE BETWEEN HIGH AND LOW/ON AND OFF
int setTemp = 35;                      // THIS IS THE SET TEMPERATURE
int lowTemp = setTemp - tempRange;
int value;

void setup() {
  // setup Transmitter info
  mySwitch.enableTransmit(12);   // Transmitter is connected to Pin #12
  mySwitch.setPulseLength(415);  // Transmitter pulse length.
  // mySwitch.setProtocol(2);// set protocol (default is 1, will work for most outlets)
  mySwitch.setRepeatTransmit(15);  // repetitions of transmissions to ensure transmit.

  Serial.begin(9600);  // Debug console
  Blynk.syncVirtual(V2);
  Blynk.begin(auth, ssid, pass);
  sensors.begin();                      // Starts the DS18B20 sensor(s).
  sensors.setResolution(10);            // More on resolution: http://www.homautomation.org/2015/11/17/ds18b20-how-to-change-resolution-9101112-bits/
  pinMode(LED, OUTPUT);                 //setup the test LED
  timer.setInterval(2000L, sendTemps);  //sets the temp sending frequency 2s
  timer.setInterval(3000L, sendRFsignal);
}

//Read TemperatureFunction
void sendTemps() {
  sensors.requestTemperatures();                 // Polls the sensors.
  roomTemperature = sensors.getTempCByIndex(0);  // Stores temperature. Change to getTempCByIndex(0) for celcius.
  Blynk.virtualWrite(1, roomTemperature);        // Send temperature to Blynk app virtual pin 1.
}

void sendRFsignal() {
  if (HeaterFlag == true) {  //ONLY RUN IF THE HEATERFLAG IS TURNED ON
    unsigned long currentMillis = millis();
    if (currentMillis - previousMillis > heaterInterval) {
      previousMillis = currentMillis;
      Serial.print("Set temperature:");
      Serial.print(setTemp);
      Serial.print(" Min temperature:");
      Serial.print(lowTemp);
      Serial.print(" Room temperature:");
      Serial.print(roomTemperature);

      if (roomTemperature > setTemp) {  //if the temp reading is higher than the set temp, turn off the heater
        mySwitch.send("001111101010110101010100");
        Serial.println("OFF SIGNAL SENT");
      }

      if (roomTemperature < lowTemp) {  //if the temp reading is lower than the low temp buffer reading, turn the heater on.
        mySwitch.send("001111101010110101011000");
        Serial.println("ON SIGNAL SENT");
      }
    }
  }
}

//This is the function which turns on and off the thermostat function.
BLYNK_WRITE(V2) {
  HeaterFlag = param.asInt();          // Get heaterFlaf value from On/Off switch
  digitalWrite(LED, HeaterFlag);       //turn on the LED to show thermostat is active or not
  Serial.print("HeaterFlag: ");
  Serial.println(HeaterFlag);
}

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

BLYNK_CONNECTED() is basically a special function (a callback if you want to think of it that way) that is triggered automatically when the device connects to the Blynk server, of if it re-connects after a communication provblem.
It can go anywhere in your sketch - provided you don’t put it inside another function.

The code inside the BLYNK_CONNECTED() function will execute once when the connection/reconnection occurs.

Blynk.syncVirtual(Vpin) asks the Blynk server to send the latest value of the [Vpin] datastream. When this data arrives at the device, it will trigger the corresponding BLYNK_WRITE(Vpin) function.

You need to remove the Blynk.syncVirtual(V2); from your void loop. It doesn’t do anything in there.

So, in your case, you’ll add this code somewhere in your sketch…

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

With this code in place, when the device connects to the Blynk server at startup, BLYNK_WRITE(V2) will be triggered, so HeaterFlag will be set to the value of the switch widget in the app. If the widget is off, HeaterFlag will be 0. If the switch widget is on it will be 1.

Does this help?

I have to say that I’m impressed with t speed at which you’ve taken the empty void loop concept onboard and implemented it. Most people struggle with this a bit.

Pete.

1 Like