Concurrency of BLYNK_WRITE / syncing virtual pin with esp8266

Hi All,

I am trying to create a low power application with deep_sleep on ESP8266. On wake up, the processor shall get some remembered values from Blync. So the idea is:

  1. After start, log in to Blync and do a syncVirtual on a pin
  2. Set a variable to the synced value using BLYNK_WRITE (since there is no virtualRead) triggered by syncVirtual
  3. Increment the value and write it to the virtual pin
  4. Go to sleep until next reboot

This is a proof of concept of course.

Its not working and I wonder how BLYNK_WRITE works. Will it be executed and the main program get interrupted? I think the sketch shows what I mean:

#include <SPI.h>
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
#include <SimpleTimer.h>

// You should get Auth Token in the Blynk App.
// Go to the Project Settings (nut icon).
char auth[] = "fgdfgdfgdfgdf";

double onCycles = 0;

BLYNK_WRITE(V5) 
{
    onCycles = param.asDouble();
}


// This function sends the number of cycles the board was started
void doSomething()
{
 
  onCycles++;
  Blynk.virtualWrite(V5, onCycles);
  digitalWrite(BUILTIN_LED, LOW);   // Turn the LED on (Note that LOW is the voltage level
  delay(10);
  digitalWrite(BUILTIN_LED, HIGH);   // Turn the LED on (Note that LOW is the voltage level

  WiFi.disconnect();
  ESP.deepSleep(10000000, WAKE_RF_DEFAULT); // Sleep for 10 seconds
}

void setup()
{
  pinMode(BUILTIN_LED, OUTPUT);     // Initialize the BUILTIN_LED pin as an output

  Blynk.begin(auth,"SSID", "PASSWORD");

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

  Blynk.syncVirtual(V5);
  doSomething();
  
}

void loop()
{
  Blynk.run(); // Initiates Blynk
}

Thanks for helping!

Hello. It is not working cause setup is called only once (I suppose). You need to follow example for sync command and use BLYNK_CONNECTED for sync command. All other seems correct. Also I don’t see any place where you trying to reconnect again.

Thanks for looking into this Dmitry. Actually the idea is to reconnect on next boot. This is not visible in the sketch - but this is (AFAIK) the way deep_sleep works. It will reset the processor after a while and make it boot (if I manage to solder the right wire on my ESP-01). This is how I test it: Wait until it has disconnected, reset it. The expectation is that it comes up completely fresh but gets its old value from the sync. Just it doesn’t work.

Did you check it? Does setup function called again? If so, please follow Sync Sketch example with BLYNK_CONNECTED

Hi Dmitriy,

I believe this is a bug in the ESP8266 implementation. I added some log output:

Serial started
[211] Connecting to Mydomain
[4313] Connected to WiFi
[4313] My IP: 192.168.1.84
[4313] Blynk v0.3.3-beta
[5001] Connecting to cloud.blynk.cc:8442
[5900] Ready (ping: 1ms).
Connected
[6150] Synced
[6255] Wrote V5: 1

Itt appears that BLYNK_WRITE is never called, but it should so. According to the doc page, syncAll should initiate it. May be there is a problem with the timing, because it must be executed somehow in the background like an interrupt routine.
Here is the code:

#define BLYNK_PRINT Serial    // Comment this out to disable prints and save space
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>

//#define BLYNK_DEBUG        // Optional, this enables more detailed prints

char auth[] = "xxxxxxxxxxxxxxxxxxxxx";
WidgetLED led1(V3); //register to virtual pin 3


double onCycles = 0;

BLYNK_WRITE(V5) 
{
    onCycles = param.asDouble();
    BLYNK_LOG("Read V5: %f", onCycles);
}


// This function sends the number of cycles the board was started
void doSomething()
{
  onCycles++;
  Blynk.virtualWrite(V5, onCycles);
  BLYNK_LOG("Wrote V5: %d", int(onCycles));
 
  led1.on();  
  delay(10);
  led1.off();

  WiFi.disconnect();
  ESP.deepSleep(10000000, WAKE_RF_DEFAULT); // Sleep for 10 second
}


void setup()
{
  Serial.begin(115200);
  Serial.println("Serial started");

  //pinMode(BUILTIN_LED, OUTPUT);     // Initialize the BUILTIN_LED pin as an output - destroys serial protocol!

  Blynk.begin(auth,"SSID", "Password");

  while (Blynk.connect() == false) {
    // Wait until connected
      Serial.println("Blynking");
    delay(10);
  }
    Serial.println("Connected");

  Blynk.syncAll();

  BLYNK_LOG("Synced");
  doSomething();
  
}

void loop()
{
  Blynk.run(); // Initiates Blynk
}

Cheers,
Archi

Please try

BLYNK_CONNECTED() {
      Blynk.syncAll();
}

and tell us if that works

It’s more like it executes callback on interrupt. You can also try normal sleep mode which has memory retention (so you don’t need sleep mode) consumes around 0.31 mA according to data sheet.

I removed the syncAll in the setup and added a
BLYNK_CONNECTED() {
Blynk.syncAll();
BLYNK_LOG(“Synced all”);
}

and I know it has been executed because I get its output:

BLYNK_CONNECTED() {
Blynk.syncAll();
BLYNK_LOG(“Synced all”);
}

Sorry I hit the send button by accident.
The log output is:
Serial started
[207] Connecting to xxxxx
[6309] Connected to WiFi
[6310] My IP: 192.168.1.9
[6310] Blynk v0.3.3-beta
[6310] Connecting to cloud.blynk.cc:8442
[7153] Ready (ping: 1ms).
[7409] Synced all
Connected
[7518] Wrote V5: 1

Looks like BLYNK_WRITE still is not executed.

Regarding conkerkh: The deep sleep works on my ESP-01 and its supposed to take µAmps. My hope is to use it with a 3V Lithium cell that runs for years waiting for an event (fire, window open alarm) and then wake up and send me some message. Theoretically this can be done without a “memory”, but if it knows some state that allows it to be smarter.

@vshymanskyy any sugggestions?

Blynk.syncAll(); is an asynchronous call!
it expects to continue looping until it gets the info from the server (BLYNK_WRITE is called only from Blynk.run() context).

Hope that helps

Good hint. I believe I understand it better now.

My goal is to retrieve a value from last session. I cannot do this in setup, because Blynk.run has not been executed even once. I cannot do int in BLYNK_CONNECTED, because it will not get interrupted in order to magically set my global variable in the background. So I think, please correct me, each run of Blynk.run in the main loop checks for events and calls the BLYNK_XXX functions one by one in its own preferred orde.

This means if I want to use the value from last session, I need an event. There is only one event that is available: BLYNK_WRITE triggered by syncAll. Thats basically the way you do it in the sync example.
I may use the global variable somewhere else, but I should use a timer to wait until I am sure it has been set. Or I set a flag in the BLYNK_WRITE that tells another part of the program running in the main loop that something has been set. Although I just want to get a static value I need to catch its change in a self-made event chain.

Well, it probably can be done like this, but wouldn’t it be much more simple to have a command that just reads the virtual pin? Or are you afraid that folks may use your server as a hidden cloud memory storing illegal messages in virtual pins :grinning:

Due to async nature of Blynk - no. I think @vshymanskyy could explain you better.

Why not? It doesn’t look too complex :

BLYNK_WRITE(V5) {
   isV5Set = true;
}

loop() {
   Blynk.run();
   if (isV5Set) {
       //do stuff
   }
}
1 Like

thanks @Dmitriy I was having same problem as @Archimedeus but your little suggestion above solved the problem I had.

1 Like