Need help with syncing Virtual Pins after a reboot

Hello All
As I said in the title I’m struggling trying to get my virtual pins to recall the last data point from the server. If I lose power, or if it disconnects from wifi, each time it reboots back to 0. What I am trying to do is recall the last value that was stored for V2 and V3, which are a totalizer and a resettable totalizer.

My project is for a flowmeter on my house, and its working fine, but the total flow resets each time I reboot the ESP32 I am using.

If you look at my code pasted below, I have tryed the Blynk.syncVirtual command in the setup and its not working. I also tried the Blynk.syncAll command as well and each time it reverts back to 0.

Thank you in advance!

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

BlynkTimer timer;

volatile int flow_frequency; 
unsigned int flowrate; 
unsigned char flowsensor = 5; 
unsigned long currentTime;
unsigned long cloopTime;
float a;
int total;

void flow (){
   flow_frequency++;
}


void sensor(){
   
   {
   currentTime = millis();
   if(currentTime >= (cloopTime + 1000))
   {
      cloopTime = currentTime; 
     
      flowrate = (flow_frequency * 60 / 5.5); 
      flow_frequency = 0;
      a = (flowrate*0.004402867539062501);

  Blynk.virtualWrite(V1, a);
 

}}}

void flowmeter(){
  
    total =  total + a;
    
    Blynk.virtualWrite(V2, (total*.016));
    

}

BLYNK_WRITE(V4)
{
  if (param.asInt()) 
  {
      Blynk.virtualWrite(V3, 0); 
  }
  else
  {
        Blynk.virtualWrite(V3, (total*.016)); 
  }      
}


   

void setup(){
  Serial.begin(9600);
  Blynk.begin(auth, ssid, pass);
  Blynk.syncVirtual(V2, V3);
  timer.setInterval(1000L, sensor);
  timer.setInterval(1000L, flowmeter);
  pinMode(flowsensor, INPUT);
  digitalWrite(flowsensor, HIGH); 
  attachInterrupt(5, flow, RISING); 
  sei(); 
  currentTime = millis();
  cloopTime = currentTime;
}


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

You have to wait until the device has negotiated its connection with the Blynk server, which isn’t immediately after Blynk.begin has been called.

You need to use the BLYNK_CONNECTED() callback function and put your Blynk.syncVirtual(vPin) command in there.

Blynk.syncAll() could be used instead, but this actually only synchronises the datastreams that have the “Sync with latest server value every time device connects to the cloud” option enabled in the advanced settings.

Pete.

Pete,

I was referencing this link. I have tried the BLYNK_CONNECTED() callback function with no luck,

Where in the code should I put the BLYNK_CONNECTED() function?

It doesn’t matter, provided you don’t put it inside another function.

Rather than saying “I’ve tried x, y, z” post your sketch which demonstrates this, and your datastream configurations if you’re using syncAll.

Pete.

Thanks Pete.
Is it an issue with initializing the flow being initialized as a variable a?

The way I have it set up is to add the flow to a total, driven by a timer every second. So every second, it takes the flow and adds it to a total. Should I define that total as a variable “B”?

I just tried again with this below code, and it again reset to 0. I tried the BLYNK_CONNECTED() command.

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

BlynkTimer timer;

char auth[] = 
char ssid[] =
char pass[] = 

volatile int flow_frequency; 
unsigned int flowrate; 
unsigned char flowsensor = 5; 
unsigned long currentTime;
unsigned long cloopTime;
float a;
int total;

void flow (){
   flow_frequency++;
}

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


void sensor(){
   
   {
   currentTime = millis();
   if(currentTime >= (cloopTime + 1000))
   {
      cloopTime = currentTime; 
     
      flowrate = (flow_frequency * 60 / 5.5); 
      flow_frequency = 0;
      a = (flowrate*0.004402867539062501);

  Blynk.virtualWrite(V1, a);
 

}}}

void flowmeter(){
  
    total =  total + a;
    
    Blynk.virtualWrite(V2, (total*.016));
    

}

BLYNK_WRITE(V4)
{
  if (param.asInt()) 
  {
      Blynk.virtualWrite(V3, 0); 
  }
  else
  {
        Blynk.virtualWrite(V3, (total*.016)); 
  }      
}


   

void setup(){
  Serial.begin(9600);
  Blynk.begin(auth, ssid, pass);
  timer.setInterval(1000L, sensor);
  timer.setInterval(1000L, flowmeter);
  pinMode(flowsensor, INPUT);
  digitalWrite(flowsensor, HIGH); 
  attachInterrupt(5, flow, RISING); 
  sei(); 
  currentTime = millis();
  cloopTime = currentTime;
}


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

Nevermind, tried cleaning up the calculations and its still not working. As soon as it reboots and connects, the value goes to 0

#include <WiFiClient.h>
#include <BlynkSimpleEsp32.h>

BlynkTimer timer;

char auth[] = "JI6jZxv44RR_uw2hxKWGXMafVKBGmPIA";
char ssid[] = "cait&caiden";
char pass[] = "Kinghenry3";

volatile int flow_frequency; 
unsigned int flowrate; 
unsigned char flowsensor = 5; 
unsigned long currentTime;
unsigned long cloopTime;
float a;
float b;
int total;

void flow (){
   flow_frequency++;
}

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


void sensor(){
   
   {
   currentTime = millis();
   if(currentTime >= (cloopTime + 1000))
   {
      cloopTime = currentTime; 
     
      flowrate = (flow_frequency * 60 / 5.5); 
      flow_frequency = 0;
      a = (flowrate*0.004402867539062501);

  Blynk.virtualWrite(V1, a);
 

}}}

void flowmeter(){
  
    total =  total + a;
    b = (total*.016);
    
    Blynk.virtualWrite(V2, b);
    Blynk.virtualWrite(V3, b);
    

}

BLYNK_WRITE(V4)
{
  if (param.asInt()) 
  {
      Blynk.virtualWrite(V3, 0); 
  }
   
}


   

void setup(){
  Serial.begin(9600);
  Blynk.begin(auth, ssid, pass);
  timer.setInterval(1000L, sensor);
  timer.setInterval(1000L, flowmeter);
  pinMode(flowsensor, INPUT);
  digitalWrite(flowsensor, HIGH); 
  attachInterrupt(5, flow, RISING); 
  sei(); 
  currentTime = millis();
  cloopTime = currentTime;
}


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

You don’t have any BLYNK_WRITE(v3) or BLYNK_WRITE(v4) callbacks, so how do you expect the synchronisation process to work?

Pete.

Pete, like this?

Still didn’t work.

BLYNK_CONNECTED(){
Blynk.syncVirtual(V2, V3);
BLYNK_WRITE(V2); 
BLYNK_WRITE(V3);
}

No, like this…

Pete.

I guess I’m confused what youre saying,

would it look like this?

BLYNK_CONNECTED(){
Blynk.syncVirtual(V2, V3);
BLYNK_WRITE(V2){
 param.asInt()}
BLYNK_WRITE(V3){
 param.asInt()}
}

No.

All that Blynk.syncVirtual(vPin) does is to cause the corresponding BLYNK_WRITE(vPin) callback to ‘fire’.

You need to have a BLYNK_WRITE(V2) and BLYNK_WRITE(V3) callback that will accept the incoming value from those virtual datastreams and assign those values to variables, in a similar way to what you’ve done with the V4 datastream.

Maybe you should read this to gain a better understanding…

Pete.

Okay Pete,

I’ve read the above post. When you say assign it to a variable, does this make sense?

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

  if (param.asFloat()) 
  {
      Blynk.virtualWrite(V2, b);
}
 } 

Where as this is the flowmeter code representing the variable b

void flowmeter(){
  
    total =  total + a;
    b = (total*.016);
    
    Blynk.virtualWrite(V2, b);

or are you talking about this

float virtual_pin_value = param.asFloat();



}


BLYNK_CONNECTED(){
Blynk.syncVirtual(V2);

}
BLYNK_WRITE(V2){

  if (param.asFloat()) 
  {
      Blynk.virtualWrite(V2, virtual_pin_value);
      }
 }

No.

Nowhere in the examples I linked to do you see one function inside another. That’s because C++ doesn’t allow the definition of a function within a function.

You already have the BLYNK_WRITE(V4) function, and if you wanted to pull the value from the V4 datastream at startup, by triggering the BLYNK_WRITE(V4) function without touching the widget that is attached to the V4 datastream, you’d do this:

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

This seems to be heading in the right direction (I think) but there are clearly some things you don’t understand about the logic of your BLYNK_WRITE(V4) function that you don’t understand, so when you copy that function for V2 you’re just blindly copying code without understanding it.

The widget attached to V4 is presumably a switch, and this has two states - 0 (or logic level false) for off and 1 (or logic level true) for on.
You want different things to be written to datastream V3 depending on whether the V4 switch widget is on or off…

This line:
if (param.asInt()) effectively translates to this in plain English…

“If the integer value coming from the V4 switch is true (1) then do this…”

It could also be written as:

if (param.asInt() == 1)

When you’re retrieving the float value stored against datastream V2, you won’t want to be doing a logical test to see if it’s 1 or 0 so you won’t want an if statement in your BLYNK_WRITE(V2) function.

Also, there is absolutely no sense in asking the Blynk server to tell you what the V2 datastream value is, then writing that value back to the V2 datastream on the Blynk server in the BLYNK_WRITE(V2) function.

What (I think) you are trying to achieve is to obtain the V2 value and store it in the a float variable in your sketch so that it can be used in future calculations.

To do that, your BLYNK_WRITE(v2) function would look like this:

BLYNK_WRITE(V2)
{
  a = param.asFloat();
}

Pete.

Hi Pete,

I am struggling with resetting the trip value for the flowmeter. I have a BLYNK_WRITE function looking at V4. V4 is attached to a switch on my dashboard. I am trying to have a lifetime water usage value represented by V2, and a trip (resettable) value represented by V3.

What I am doing is taking the flow and adding the flow to a variable every second (blynk timer)

Flow is represented in Gallons Per Minute, so when writing the value to the virtual pin, I multiply by .016 (1minute divided by 60seconds)

I set up a variable b for the V3 resettable value. Each second, it is writing the data to the server.

My BLYNK_WRITE command is just reading the value of the switch on my dashboard, and if the param.asInt() function comes back with a 1, it should set the variable to 0 which would then be written by the Blynk.virtualWrite() command.

Why isn’t this working? It will show a 0 for V3, but only for a second and then the previous value comes back.

See my attached code below


BLYNK_WRITE(V4)
{
 if (param.asInt() == 1)
 
  {(b = 0);}
  }

  
void flowmeter(){
  
    total =  total + a;
    
    b = (total);
    Blynk.virtualWrite(V2, total*.016);
    Blynk.virtualWrite(V3, b*.016); 

}

Because that’s exactly what your code is telling it to do.

Let’s say that total = 1,000,000 and a = 1

total is now = 1,000,001

b (which you’ve previously reset to 0) is now equal to 1,000,001

What you actually want is for b to be 1, so this line…

should actually say:

b = b + a;

Pete

I am still having trouble syncing a value from the server after a reboot.

Screenshot 2023-03-15 160837

The server is storing my data, but whenever the ESP32 reboots, it doesnt sync with the server and the data resets to 0.

image

My Code is below,

#define BLYNK_TEMPLATE_ID           "TMPLvQM2iWfK"
#define BLYNK_DEVICE_NAME           "Basement Flowmeter and Temperature"
#define BLYNK_AUTH_TOKEN            "V9DD9TcsN-CXuqlMSgDXJVxRgEkizT8-"
#define BLYNK_PRINT Serial
#include <WiFi.h>
#include <WiFiClient.h>
#include <BlynkSimpleEsp32.h>
#include "DHT.h"

#define DHTPIN 18    
#define DHTTYPE DHT22   

char auth[] = BLYNK_AUTH_TOKEN;
char ssid[] = "cait&caiden";
char pass[] = "Kinghenry3";

DHT dht(DHTPIN, DHTTYPE); 

BlynkTimer timer;


volatile int flow_frequency; 
unsigned int flowrate; 
unsigned char flowsensor = 5; 
unsigned long currentTime;
unsigned long cloopTime;
float a;
float b;
unsigned long total;
unsigned long dailyTotal;
unsigned long weeklyTotal;
unsigned long monthlyTotal;


BLYNK_CONNECTED()
{
 Blynk.syncVirtual(V2);
 Blynk.syncVirtual(V3);
 Blynk.syncVirtual(V16);
 Blynk.syncVirtual(V17);
 Blynk.syncVirtual(V18);
}


void flow()
{
  flow_frequency++;
}

void sensor()
{
  currentTime = millis();
  if (currentTime >= (cloopTime + 1000))
  {
    cloopTime = currentTime;
    flowrate = (flow_frequency * 60 / 5.5);
    flow_frequency = 0;
    a = (flowrate * 0.004402867539062501);

    Blynk.virtualWrite(V1, a);
  }
}

BLYNK_WRITE(V4)
{
  if (param.asInt() == 1)
  {
    b = 0;
  }
}
void flowmeter() {

  total = total + a;
  dailyTotal = dailyTotal + a;
  weeklyTotal = weeklyTotal + a;
  monthlyTotal = monthlyTotal + a;

  b = b + a;

  Blynk.virtualWrite(V2, total * 0.016);
  Blynk.virtualWrite(V3, b * 0.016);
  Blynk.virtualWrite(V16, dailyTotal * 0.016);
  Blynk.virtualWrite(V17, weeklyTotal * 0.016);
  Blynk.virtualWrite(V18, monthlyTotal * 0.016);

static unsigned long lastDailyUpdate = 0;
static unsigned long lastWeeklyUpdate = 0;
static unsigned long lastMonthlyUpdate = 0;
unsigned long now = millis();



  
  if (now - lastDailyUpdate >= 24 * 3600 * 1000) {
    dailyTotal = 0.0;
    lastDailyUpdate = now;
  }
  
  if (now - lastWeeklyUpdate >= 7 * 24 * 3600 * 1000) {
    weeklyTotal = 0.0;
    lastWeeklyUpdate = now;
  }
  
  if (now - lastMonthlyUpdate >= 30 * 24 * 3600 * 1000) {
    monthlyTotal = 0.0;
    lastMonthlyUpdate = now;
  }
}



void temp(){

float h = dht.readHumidity();
float t = dht.readTemperature(true);
Blynk.virtualWrite(V5, h);
Blynk.virtualWrite(V6, t-3);
}

void setup(){
Serial.begin(115200);
dht.begin();
Blynk.begin(auth, ssid, pass);
timer.setInterval(1000L, sensor);
timer.setInterval(1000L, flowmeter);
timer.setInterval(10000L, temp);
pinMode(flowsensor, INPUT);
digitalWrite(flowsensor, HIGH);
attachInterrupt(5, flow, RISING);
sei();
currentTime = millis();
cloopTime = currentTime;

}

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

I have tried moving the blynk sync function to the setup part of my code, in my datastreams, I have the checkbox selected that says "Sync with latest server value every time device connects to the cloud
"

I am saving the raw value. I have 15 devices all connected to blynk and not once have I been able to successfully get them to sync to the cloud on reboot.

I am trying to collect data that stores my daily, weekly, and monthly water usage but it does not store these values whatsoever.

Thank you in advance for the help.

It makes no difference whereabouts in your code you place the BLYNK_CONNECTED function (provided of course you don’t place it inside another function).

That setting is only relevant if you use the Blynk.syncAll() command, which you are mot using (and which you should NOT be using).

That’s because you aren’t writing your sketches correctly, because you don’t understand how the Blynk.syncVirtual(vPin) command works.

You’re writing these values to the Blynk cloud server ro datastreams V16, V17 and V18.
You have Blynk.syncVirtual commands for these datastreams in your `BLYNK_CONNECTED() function…

But you do not have corresponding BLYNK_WRITE(V16), BLYNK_WRITE(V17) and BLYNK_WRITE(V18) functions to receive the stored values back from the server and use these values as the starting point for your totals

Add this piece of code to the bottom of your sketch…

BLYNK_WRITE(V16)
{
  int old_daily_total = param.asInt();  
  Serial.print("The DAILY total stored on the server is ");
  Serial.println(old_daily_total);
  dailyTotal = old_daily_total; // use the old total as the starting point
}

Does this help you understand?

Pete.

I tried this in my code. I also tried calling the BLYNK_WRITE functions in the setup to only run when reconnected. I am still having my totalizers reset to 0. I tried adding a delay between when blynk connects and when my functions start and that didnt work either. I also tried changing the BLYNK_WRITE function to param.asFloat as my variables were float values and not int. I followed the virtual pin documentation and put the Blynk.syncVirtual before the BLYNK_WRITE, and then following that is my Blynk.virtualWrite

I know im missing one small thing and its driving me nuts.

#define BLYNK_TEMPLATE_ID           "TMPLvQM2iWfK"
#define BLYNK_DEVICE_NAME           "Basement Flowmeter and Temperature"
#define BLYNK_AUTH_TOKEN            "V9DD9TcsN-CXuqlMSgDXJVxRgEkizT8-"
#define BLYNK_PRINT Serial
#include <WiFi.h>
#include <WiFiClient.h>
#include <BlynkSimpleEsp32.h>
#include "DHT.h"
#define DHTPIN 18    
#define DHTTYPE DHT22   
char auth[] = BLYNK_AUTH_TOKEN;
char ssid[] = "cait&caiden";
char pass[] = "Kinghenry3";
DHT dht(DHTPIN, DHTTYPE); 
BlynkTimer timer;

volatile int flow_frequency; 
unsigned int flowrate; 
unsigned char flowsensor = 5; 
unsigned long currentTime;
unsigned long cloopTime;
float a;
float trip;
float total;
float dailyTotal;
float weeklyTotal;
float monthlyTotal;

BLYNK_CONNECTED()
{
  Blynk.syncVirtual(V2);
  Blynk.syncVirtual(V3);
  Blynk.syncVirtual(V16);
  Blynk.syncVirtual(V17);
  Blynk.syncVirtual(V18);
}

 BLYNK_WRITE(V2) {
    float old_total = param.asFloat();
    Serial.print("The Total stored on the server is ");
    Serial.println(old_total);
    total = old_total;
  }

 BLYNK_WRITE(V3) {
    float old_trip_total = param.asFloat();
    Serial.print("The trip total stored on the server is ");
    Serial.println(old_trip_total);
    trip = old_trip_total;
  }

  BLYNK_WRITE(V16) {
    float old_daily_total = param.asFloat();
    Serial.print("The DAILY total stored on the server is ");
    Serial.println(old_daily_total);
    dailyTotal = old_daily_total;
  }

  BLYNK_WRITE(V17) {
    float old_weekly_total = param.asFloat();
    Serial.print("The WEEKLY total stored on the server is ");
    Serial.println(old_weekly_total);
    weeklyTotal = old_weekly_total;
  }

  BLYNK_WRITE(V18) {
    float old_monthly_total = param.asFloat();
    Serial.print("The MONTHLY total stored on the server is ");
    Serial.println(old_monthly_total);
    monthlyTotal = old_monthly_total;
  }





void flow()
{
  flow_frequency++;
}

void sensor()
{
  currentTime = millis();
  if (currentTime >= (cloopTime + 1000))
  {
    cloopTime = currentTime;
    flowrate = (flow_frequency * 60 / 5.5);
    flow_frequency = 0;
    a = (flowrate * 0.004402867539062501);

    Blynk.virtualWrite(V1, a);
  }
}

BLYNK_WRITE(V4)
{
  if (param.asInt() == 1)
  {
    trip = 0;
  }
}
void flowmeter() {

  total = total + a;
  trip = trip + a;
  dailyTotal = dailyTotal + a;
  weeklyTotal = weeklyTotal + a;
  monthlyTotal = monthlyTotal + a;

 

  Blynk.virtualWrite(V2, total * 0.016);
  Blynk.virtualWrite(V3, trip * 0.016);
  Blynk.virtualWrite(V16, dailyTotal * 0.016);
  Blynk.virtualWrite(V17, weeklyTotal * 0.016);
  Blynk.virtualWrite(V18, monthlyTotal * 0.016);




//static unsigned long lastDailyUpdate = 0;
//static unsigned long lastWeeklyUpdate = 0;
//static unsigned long lastMonthlyUpdate = 0;
//unsigned long now = millis();



//  
//  if (now - lastDailyUpdate >= 24 * 3600 * 1000) {
//    dailyTotal = 0.0;
//    lastDailyUpdate = now;
//  }
//  
//  if (now - lastWeeklyUpdate >= 7 * 24 * 3600 * 1000) {
//    weeklyTotal = 0.0;
//    lastWeeklyUpdate = now;
//  }
//  
//  if (now - lastMonthlyUpdate >= 30L * 24L * 3600L * 1000L) {
//    monthlyTotal = 0.0;
//    lastMonthlyUpdate = now;
//  }
}

void temp(){

float h = dht.readHumidity();
float t = dht.readTemperature(true);
Blynk.virtualWrite(V5, h);
Blynk.virtualWrite(V6, t-3);
}




void setup(){
Serial.begin(115200);
dht.begin();
Blynk.begin(auth, ssid, pass);
BLYNK_WRITE(V2);
BLYNK_WRITE(V3);
BLYNK_WRITE(V16);
BLYNK_WRITE(V17);
BLYNK_WRITE(V18);
timer.setInterval(1000L, sensor);
timer.setInterval(1000L, flowmeter);
timer.setInterval(10000L, temp);
pinMode(flowsensor, INPUT);
digitalWrite(flowsensor, HIGH);
attachInterrupt(5, flow, RISING);
sei();
currentTime = millis();
cloopTime = currentTime;

}

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

 


  
 



You mean like this…

BLYNK_WRITE(vPin) is a function name. This means that it needs to appear like this…

BLYNK_WRITE(vPIN)
{
  // The code to be executed when the function is called in here
}

As I’ve explained and re-iterated since, you cannot put one function inside another in C++
void setup() is a function, so you can’t put another function inside it.

Please remove these lines of code from your void setup…

Do you mean that you tried adding a delay between when Blynk connects and when your timers are initialised?
If so then this won’t work, because of the blocking nature of the delay() command

That makes sense. I used para.asInt() because in the previous version of your code they were unsigned long integers…

Which documentation is this, and where does it say that the order of these functions in the code are important?

As far as trying to debug the operation once these changed have been made, you’d need to share the contents of your serial monitor as well as info about the values that are shown in Blynk at each stage if the boot/re-boot process.

Your code is also cluttered-up with other stuff that makes it difficult to follow.

I don’t understand the role of the currentTime and cloopTime variables and this millis comparison stuff in your sensor function…

Isn’t this redundant when using BlynkTimer to call your sensor function?

I’m also unsure why you have sensor and flowmeter as two separate functions called one after the other. Wouldn’t it make sense to have this as one function, called once per second with a single BlynkTimer?

Alo, your void setup contains this line…

What is/was this line of code meant to achieve?

Pete.

No the utilization of that function is quoted below. My intentions with the BLYNK_WRITE(VPIN) in the setup was to only call the functions during setup, as I thought my code is running too fast, causing it to write a new value of 0 to the server before it has the time to read the value and update it. Thats also why I tried the delay. That has been removed. I was trying to delay the sequence of starting by starting blynk, running the sync virtual and blynk write functions, and then starting my timers.

yes youre correct its redundant, removed. Thanks for the help

This line was supposed to enable interrupts. Might not be required though. I agree

Yes, i could and probally should have both of these under one blynk timer. My intentions were to get my code working first and then go back and optimize it to run smoother.

This was the reference I was following in regards to syncing my values.

I appreciate your help with this. Thanks Pete