Hardware State Sync : App side sometimes not remaining in Sync with Relay Physical Side

Dear Blynk Community.
I have been setting up ESP8266 / Arduino Uno / iPhone 5S / Blynk-Cloud to help automate my greenhouse. My temp and tank volume sensors are all working well on Blynk, but the 4Ch relay is not actuating reliably from the App, particularly when using timer. Without ‘mission critical’ timer actuation, I can’t rely on Blynk to do the job… but would very much like to enact some ‘fail safe’ coding to self check the App state to the Physical State.

My problem with the Relays staying in physical sync with the App button. I find that perhaps around one in five times, the App button does not actuate the relay even if it shows “ON” in the App. The Blynk send “HIGH” to the digital pin D5 gets lost somewhere, and the app is not detecting if its picked up on the physical level and actuated (there appears to be no feedback back to the app from the physical state).

This is most apparent when using the timer widget to actuate the relay via Button( D5 ) : it may sometimes actuate properly but when it comes to turn off (ie send LOW or 0), the App button actuates, but the message does not reliably get through to the Physical State of the relay (via ESP8266 and Arduino) (and vice versa)

As part of my testing, I added a VirtualPin7 to indicate the physical state back on the app :

Blynk.virtualWrite(7, digitalRead(5));  // writes PHYSICAL pin state back to Blynk to cross check

I have also tried the “Hardware State Sync from App” code to no avail.
I am using timers properly with no delays in the void loop() (well best I can)!

I am wondering if any code legends out there can think up a way to detect a state mis-match on the App side between my (D5 button) and the (V7 Physical State of D5 button)?

MANY THANKS!
Please excuse the beginners code and the likely many errors!



/* Sketch using ESP8266 as software serial modem, wifi enabling Arduino
 * 30Nov18 : added BLYNK functionality
 * 30Nov18 : added analogue TEMP function (36GZ)
 * 2 Dec18 : added first  (T0) digital TEMP function (DS18B20)
 * 2 Dec18 : added second (T1) digital TEMP on same oneWire bus
 * 2 Dec18 : added 4ch relay via Blynk.
 * 7 Dec18 : added DHT22 temp humidity sensor (digital) to pin A0 (see TempDHT22 sketch)
 * 13Dec18 : added Volume calc, altered dist pins to A0 / A1.  DHT22 to pin A2
 * 13Dec18 : added Blynk.notify for low tank alarm
 * 14Dec18 : added Averaging for DISTANCE (no good.. clears array to zero each reset)
 * 14Dec18 : added Blynk Timer, and Blynk.synchall()
 
 */
#define BLYNK_PRINT Serial
#include <DHT.h>;
#include <ESP8266_Lib.h>
#include <BlynkSimpleShieldEsp8266.h>
#include <OneWire.h>  // OneWire Bus for Digital Temp Gauge
#include <DallasTemperature.h> // Digital TEMP Gauge support

// BLYNK wireless setup (Blynk runs the ESP8266)
char auth[] = "XXXXXXX"; // BLYNK token
char ssid[] = "XXXXXXX";
char pass[] = "XXXXXX";
int pinV7;
float humDHT01;  // stores first DHT22 humidity value
float tempDHT01; // stores first DHT22 temp values 
float volume;
float temp1; //
float temp2; // 

  BlynkTimer timer;
  void myTimerEvent(){
    Blynk.virtualWrite(2, temp1); // sends temp1 to Blynk virtual pin 2
    Blynk.virtualWrite(3, temp2); // sends temp2 to Blynk virtual pin 3
    Blynk.virtualWrite(4, tempDHT01); // sends tempDHT01 to Blynk virtual pin 4
    Blynk.virtualWrite(5, humDHT01); // sends humDHT01 to Blynk virtual pin 5  
    Blynk.virtualWrite(1, volume); // sends volume to Blynk Virtual Pin 1
    Blynk.virtualWrite(6, digitalRead(11));  // writes PHYSICAL pin state back to Blynk to cross check
      Blynk.virtualWrite(7, digitalRead(5));  // writes PHYSICAL pin state back to Blynk to cross check
      Blynk.virtualWrite(8, digitalRead(6));  // writes PHYSICAL pin state back to Blynk to cross check
      Blynk.virtualWrite(9, digitalRead(7));  // writes PHYSICAL pin state back to Blynk to cross check
      Blynk.virtualWrite(10, digitalRead(8));  // writes PHYSICAL pin state back to Blynk to cross check
      }

// Averaging Setup
  const int numReadings = 10;  // size of array to average over
  int readings[numReadings];   // declares the array
  int readIndex = 0;          // variable 0 to 49 to be used to read / write array bucket position
  float total = 0;              // running total variable - starts at 0
  float average = 0;            // average variable - starts at 0
  int thisReading = 0;        // declares the reading position counter variable

// Keep this flag not to re-sync on every reconnection
bool isFirstConnect = true;



// This function will run every time Blynk connection is established
    BLYNK_CONNECTED() {
    if (isFirstConnect) {
    // Request Blynk server to re-send latest values for all pins
    Blynk.syncAll();

    // You can also update individual virtual pins like this:
    //Blynk.syncVirtual(V0, V2);

    isFirstConnect = false;
  }}

BLYNK_WRITE(V7)
{
  pinV7 = param.asInt(); // assigning incoming value from pin V7 to a variable
  // process received value
}

// or Software Serial on Uno, Nano...
#include <SoftwareSerial.h>
SoftwareSerial EspSerial(2, 3); // RX, TX : sets up an instance of SoftwareSerial called EspSerial

#define ESP8266_BAUD 9600  // Your ESP8266 baud rate  (note no ";" after #define!!)
#define ONE_WIRE_BUS 4     // oneWire bus on PIN 4    (note no ";" after #define!!)

// DHT22 temperature setup : 
#define DHTPIN A2
#define DHTTYPE DHT22      
DHT dht(DHTPIN, DHTTYPE);  // call an instance of the DHT sensor
int chk;

// Setup a oneWire instance to communicate with any OneWire devices  
OneWire oneWire(ONE_WIRE_BUS); // Setup OneWire Instance
// Pass the oneWire reference to Dallas Temperature
DallasTemperature sensors(&oneWire);

ESP8266 wifi(&EspSerial); // not sure what this does

//Distance :  sensor sketch using code from Altronics Z6322 product data sheet tutorial
  const int trig = A0;
  const int echo = A1;
  long time, dist;  // declare the variables being used in Distance calculations

  const int reedPin = A3;

#define RELAY1 5
#define RELAY2 6
#define RELAY3 7
#define RELAY4 8
#define BLYNK_MAX_READBYTES 1024

// --------------SETUP------SETUP-------------------SETUP------------------SETUP------------SETUP--------------
   
void setup()
{
  // TIMER Setup to be called 
    timer.setInterval(5000L, myTimerEvent);
  
  //not sure if need to set pinMode or if Blynk does that
  pinMode(RELAY1, OUTPUT);
  pinMode(RELAY2, OUTPUT);
  pinMode(RELAY3, OUTPUT);
  pinMode(RELAY4, OUTPUT);
  pinMode(reedPin, INPUT_PULLUP); // sets A3 HIGH, so closing REED sends it LOW.

  }
  
  // Debug console
  Serial.begin(9600); // allows you to see what is going on to DEBUG if necessary

  sensors.begin(); // Start up the Dallas Temp library
  dht.begin();    // Start up the DHT22 library
  
 // Distance : set the pinmodes 
  Serial.begin(9600);
  pinMode(trig, OUTPUT);  // note OUTPUT must be in CAPS
  pinMode(echo, INPUT);   // note INPUT must be in CAPS
  delay(10);
 
  EspSerial.begin(ESP8266_BAUD);
  delay(10);
  Blynk.begin(auth, wifi, ssid, pass,"45.55.96.146",80);
  
}

// -----------------------LOOP ------------------------- LOOP-------------LOOP ------------

void loop()
{ 
 Blynk.run();
 timer.run();
 
 sensors.requestTemperatures(); // Send the command to get temperature readings 
  temp1 = sensors.getTempCByIndex(0); // gets the temp reading one oneWire index 0, ie temp1
  temp2 = sensors.getTempCByIndex(1); // gets the temp reading two oneWire index 1, ie temp2
       tempDHT01=dht.readTemperature();  // gets the DHT22 temperature reading
       humDHT01=dht.readHumidity();     //  gets the DHT22 humidity reading

 // ULTRASONIC DISTANCE SENSOR & VOLUME section : writing to Virtual Pin 1
  digitalWrite(trig, LOW); // ensure the trig is LOW for a clean HIGH pulse
  delayMicroseconds(2);
  digitalWrite(trig, HIGH);
  delayMicroseconds(10);    //PING triggered by HIGH pulse of more then 2 micro seconds
  digitalWrite(trig, LOW);
  time = pulseIn(echo, HIGH);  // returns HIGH pulse length (microseconds) at pin 'echo'
  dist = 906 - ((time/2)/2.91);      // converts the time into a distance in mm, 2.91 microsec per mm
  volume = (dist * dist * 0.0001659) + (dist * 0.2496272);
  if (volume <= 100) Blynk.notify("Hydroponic Tank level had dropped below 100L"); // ALARM NOTIFY
  
}

// ----- END LOOP ---------- END LOOP -------------- END LOOP ------------------

I’d guess that your one in five failures are happening because of all that code in your void loop that shouldn’t be there.
If the void loop was clean then Blynk would be able to ‘see’ and action the direct pin manipulation commands. As it is, I think your issue is that these commands are being missed, because the your MCU is processing the other code in your void loop.
Read this:

In addition to that, there a a few other changes I’d make…

I’d forget using using digital pins in the widgets. Use virtual pins instead and set the desired state of your relay pins in your code.

I’m also not a fan of using the ’D’ pin designations. Use proper GPIO numbers instead, and translate this into the corresponding D pin in your code comments.

You’ll probably want to do a synchronisation of the MCU to the Blynk server after the initial connection to Blynk. Seacrch for how to use the Blynk.syncVirtual command.

Pete.

Hi Pete
Thanks for your prompt reply, and your clearly very wise words. I’ll hop to it and clean out the loop() asap as well as attend to the other suggestions. many thanks Craig

1 Like