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