Problem with multiple virtualWrite() calls in sequence

Hi everyone.

I have a weird issue I could really use help with.

I have a simple sketch below:

/* Comment this out to disable prints and save space */
#define BLYNK_PRINT Serial

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

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

// Conversion factor for micro seconds to seconds
#define uS_TO_S_FACTOR 1000000

// Time ESP32 will go to sleep (in seconds)
#define TIME_TO_SLEEP 15        

// holds the total boot counts
RTC_DATA_ATTR int bootCount = 0;

// Your WiFi credentials.
// Set password to "" for open networks.
char ssid[] = "";
char pass[] = "-()-";

// Moisture sensor is connected to GPIO 34 (Analog ADC1_CH6) 
const int sensorPin = 34;

// variable for storing the moisture sensor value
int sensorValue = 0;

// this function reads the sensor values and send them to blynk
void publishSensorValues()
{
  // Reading moisture sensor value
  sensorValue = analogRead(sensorPin);

  // Sending to blynk
  Blynk.virtualWrite(V0, sensorValue); 
  
  while (Blynk.connect() == false) {
    // Wait until connected
  }
  
  // Send uptime
  Blynk.virtualWrite(V1, bootCount);
}

void setup()
{
  // Debug console
  Serial.begin(115200);
  delay(500); //Take some time to open up the Serial Monitor

  //Increment boot number and print it every reboot
  ++bootCount;
  Serial.println("Boot number: " + String(bootCount));

  // schedule a wakeup in the future
  esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);

  // connect to blynk
  Blynk.begin(auth, ssid, pass);

  // read and publish the sensor values
  publishSensorValues();

  Serial.println("Going to sleep now");
  Serial.flush(); 
  esp_deep_sleep_start();
}

void loop()
{
}

I realized if I take out this piece:

  while (Blynk.connect() == false) {
    // Wait until connected
  }

then only the first Blynk.virtualWrite(V0, sensorValue) succeeds. If I swap V1 and V0, then V1 succeeds.

Which one is the first, that one succeeds.

But if I put while (Blynk.connect() == false) back, then both succeed.

BUTā€“I get a double connection statements in the console:

21:44:13.197 ā†’ [1615] Connecting to blynk-cloud.com:80
21:44:13.296 ā†’ [1722] Ready (ping: 48ms).
21:44:18.296 ā†’ [6723] Connecting to blynk-cloud.com:80
21:44:18.429 ā†’ [6860] Ready (ping: 43ms).

so, either one virtualWrite succeeds or I have double connections.

Can someone please help?

Thank you!!

Iā€™m pretty sure Blynk.connect() is a blocking function anyway so you could try to remove this:

while (Blynk.connect() == false) {
    // Wait until connected
  }

And just put this at the start of your function:

Blynk.connect();
1 Like

Coding for deep sleep is very different to regular Blynk coding - where the void loop needs to be kept clean. With deep sleep, the opposite is true, you want the void loop to execute once, so you put everything in there.

I have no experience of coding ESP32s for deep sleep, but i think the general principals should be the same.

Your code contains no Blynk.run(); commands, which in my experience are needed to get most Blynk functions to work correctly. Youā€™re also trying to use Blynk.connect when I suspect that you should be using Blynk.connected()```

Also, using Blynk.begin, which is a blocking function, isnā€™t good for battery powered devices as a failure to connect to Wi-Fi or Blynk will result in the device continually trying to connect until it either succeeds or the batteries are flat.
Itā€™s better to use do your own Wi-Fi connection management then use Blynk.config and Blynk.connect.

Hereā€™s a bit of code that I contributed to in the earlier stages when it was running on an ESP8266, but was then ported over to ESP32 by @christophebl and he reports that itā€™s working well for himā€¦

Pete.

1 Like

Unfortunately, that didnā€™t work :frowning:

the new function:

// this function reads the sensor values and send them to blynk
void publishSensorValues()
{
  Blynk.connect();
  
  // Reading moisture sensor value
  sensorValue = analogRead(sensorPin);

  // Sending to blynk
  Blynk.virtualWrite(V0, sensorValue); 
 
  // Send uptime
  Blynk.virtualWrite(V1, bootCount);
}

Still double connections:

08:35:03.769 ā†’ [1582] Connecting to blynk-cloud.com:80
08:35:04.365 ā†’ [2185] Ready (ping: 41ms).
08:35:09.365 ā†’ [7186] Connecting to blynk-cloud.com:80
08:35:09.630 ā†’ [7430] Ready (ping: 190ms).

1 Like

I think the ā€œdouble connectionsā€ are because your device isnā€™t talking to the Blynk server after the first connection, so it then tries to re-connect.
This is because of the lack of Blynk.run statements.
Any ā€˜while/wendā€™ command is also likely to cause disconnections unless thereā€™s a Blynk.run command in the loop.

Pete.

2 Likes

ā€œDouble Connectionsā€ happen because Blynk.connect() is called again. Use Blynk.connected() to check if there is connection.
Try this code

/* Comment this out to disable prints and save space */
#define BLYNK_PRINT Serial

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

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

// Conversion factor for micro seconds to seconds
#define uS_TO_S_FACTOR 1000000

// Time ESP32 will go to sleep (in seconds)
#define TIME_TO_SLEEP 15        

// holds the total boot counts
RTC_DATA_ATTR int bootCount = 0;

// Your WiFi credentials.
// Set password to "" for open networks.

char cloudBlynkServer[] = "****";

char ssid[] = "****";
char pass[] = "****";

// Moisture sensor is connected to GPIO 34 (Analog ADC1_CH6) 
const int sensorPin = 34;

// variable for storing the moisture sensor value
int sensorValue = 0;

// this function reads the sensor values and send them to blynk
void publishSensorValues()
{
  #define KAVG      10
   
  sensorValue = 0;

  // Reading moisture sensor value
  for (int i = 0; i < KAVG; i++)  //
  {
    sensorValue += analogRead(sensorPin); 
    delay(20);   
  }
  sensorValue = sensorValue / KAVG;

  // Sending to blynk
  Blynk.virtualWrite(V5 /*V0*/, sensorValue); 
   
  // Send uptime
  Blynk.virtualWrite(V3 /*V1*/, bootCount);
}

#define BLYNK_SERVER_HARDWARE_PORT    8080

void setup()
{
  // Debug console
  Serial.begin(115200);
  
  //Increment boot number and print it every reboot
  ++bootCount;

  // schedule a wakeup in the future
  esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);

  // connect to blynk
  Blynk.begin(auth, ssid, pass, cloudBlynkServer, BLYNK_SERVER_HARDWARE_PORT);

  if (Blynk.connected())
  {
    // read and publish the sensor values
    publishSensorValues();
  }

  Serial.println("Boot number: " + String(bootCount));  
  Serial.println("Going to sleep now");
  Serial.flush();

  Blynk.disconnect();

  esp_deep_sleep_start();
}

void loop()
{
}
1 Like

Thank you, will try tonight.

ok, this is a neat trickā€“you are taking 20 readings and then averaging them?

Heheā€¦ cute :slight_smile:

Is this a typical pattern for reading sensor values?

(very cool, btw).

Will try this tonight alsoā€“thank you, thank you!

to be fair, I removed Blynk.run based on this and other searchable discussions.

This could be my ignorance though. Iā€™m still not sure itā€™s needed but happy to add if required.

Thank you.

I think that dispensing with Blynk.run is a risky strategy, and the effects arenā€™t really well understood.
Iā€™ve seen other discussions where a timer can call a function that contains Blynk.run, but Iā€™m not really convinced and it doesnā€™t have a place in the code that youā€™re using.

As far as what youā€™re trying to achieve, Iā€™d read through the comments that are in beehive code that I linked to. Itā€™s well commented (I know because I put them in there :blush:) and Iā€™m told that it the code works well.

Pete.

Just tried this, it worksā€“thank you!!

Understood.

Going over the bee code now, thereā€™s quite a bit to unpack there.

Thank you for your help.

For future reference, this is the code that works:

thank you @khoih and @PeteKnight for all your help!

/* Comment this out to disable prints and save space */
#define BLYNK_PRINT Serial

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

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

// Conversion factor for micro seconds to seconds
#define uS_TO_S_FACTOR 1000000

// Time ESP32 will go to sleep (in seconds)
#define TIME_TO_SLEEP 15        

// holds the total boot counts
RTC_DATA_ATTR int bootCount = 0;

// Your WiFi credentials.
// Set password to "" for open networks.
char ssid[] = "";
char pass[] = "-()-";

// Moisture sensor is connected to GPIO 34 (Analog ADC1_CH6) 
const int sensorPin = 34;

// this function reads the sensor values and send them to blynk
void publishSensorValues()
{
  // how many readings to take
  #define MAX_SENSOR_READS 10

  // variable for storing the moisture sensor value
  int sensorValue = 0;

  // Reading moisture sensor values
  for (int i = 0; i < MAX_SENSOR_READS; i++) 
  {
    sensorValue += analogRead(sensorPin); 
    delay(20);   
  }
  sensorValue = sensorValue / MAX_SENSOR_READS;
  
  // Sending to blynk
  Blynk.virtualWrite(V0, sensorValue); 
 
  // Send uptime
  Blynk.virtualWrite(V1, bootCount);
}

void setup()
{
  // Debug console
  Serial.begin(115200);
  delay(500); //Take some time to open up the Serial Monitor

  //Increment boot number and print it every reboot
  ++bootCount;
  Serial.println("Boot number: " + String(bootCount));

  // schedule a wakeup in the future
  esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);

 // setup the connection to blynk
  Blynk.config(auth);

  // setup WiFi
  Blynk.connectWiFi(ssid, pass);

  //will continue trying to connect to Blynk server. 
  //Returns true when connected, false if timeout has been reached. 
  //Default timeout is 30 seconds.
  bool result = Blynk.connect();

  if (Blynk.connected())
  {
    // read and publish the sensor values
    publishSensorValues();
  }

  Serial.println("Going to sleep now");
  Serial.flush(); 

  Blynk.disconnect();
  
  esp_deep_sleep_start();
}

void loop()
{
}

Iā€™m not sure why youā€™re saving the outcome of the Blynk.connect() test to the variable ā€˜resultā€™ if youā€™re not going to use it in the next stage. Wouldnā€™t it be better to do this:?

  //will continue trying to connect to Blynk server. 
  //Returns true when connected, false if timeout has been reached. 
  //Default timeout is 30 seconds.
  bool result = Blynk.connect();

  if (result)
  {
    // read and publish the sensor values
    publishSensorValues();
  }

Pete.

Absolutely. Fixed!

:wink:

1 Like