Blynk - whats going on?


#1

What is the alternative to Blynk for controlling input/outputs via smartphone?

Recently, issues surrounding device connectivity and usage of the Blynk service are increasing. I myself am concerned: even the simplest Blynk examples do not maintain the connection between the app and the device.

 *************************************************************/

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


#include <blynk.h>

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

WidgetLED led1(V1);

BlynkTimer timer;

// V1 LED Widget is blinking
void blinkLedWidget()
{
  if (led1.getValue()) {
    led1.off();
    Serial.println("LED on V1: off");
  } else {
    led1.on();
    Serial.println("LED on V1: on");
  }
}

void setup()
{
  // Debug console
  Serial.begin(9600);

  delay(5000); // Allow board to settle
  Blynk.begin(auth);

  timer.setInterval(1000L, blinkLedWidget);
}

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

Are you also aware of any abnormalities?
Which alternatives do you use?


#2

@Postler, I wouldn’t call Blynk functions from a Software Timer since it has a limited stack size. Instead set a flag that you can read in loop() or use a millis() timer, also in loop().


#3

This is in contrast to the blynk recommendation to keep the loop as clean as possible and to work with timers.

I have now switched from blynk timer to particle timer and in my concrete project everything works - except for blynk.

I’ve updated several photons on FWv1.0.0 today and get red panic attacks on my photons with this program. They restart around 10 seconds. It was not until I commented out Blynk that it worked again. Whether it is the Blynk or the Photon I can not judge.

#include <blynk.h>

//#define BLYNK_DEBUG // Optional, this enables lots of prints
//#define BLYNK_PRINT Serial

int inputBrightness = A3;       // choose the input pin (for ALSPT19 Light - adafru.it/2748) > measure the analog voltage on the OUT pin. The voltage will increase when sensor detects more light.
int inputPIR = D4;              // choose the input pin (for PIR sensor)
int ledPin = D3;                // LED Pin
int pirState = LOW;             // we start, assuming no motion detected
int boardLed = D7;              // photon onBoard LED
int calibrateTime = 5000;       // wait for the thingy to calibrate
int lightThreshold = 1000;      // brightness as analog value to decide its time for more light as analog value
int ambientBrightness;          // Here we are declaring the integer variable ambientBrightness, which we will use later to store the value of the photoresistor.
int i = 0;                      // delay-Ersatz für colorFade - for-Schleife

int red   = 255; 
int green = 255; 
int blue  = 255; 

#define REDPIN A5
#define GREENPIN WKP   
#define BLUEPIN A4

int delayColorFade = 15;   // presents the delay for the colorFade

Timer particle_timer_PIR(1000, reportPIRStatus);
Timer particle_timer_Brightness(10000, readBrightness);

char auth[] = "<<your blync auth-code here>>"; 

// *********    


BLYNK_WRITE(V4) // Blynk app WRITES Slider widget  
{
    lightThreshold = param.asInt();
    Serial.println("******************************");    
    Serial.print(lightThreshold);    
    Serial.println(" analog value = new Threshold for Light");    
    Serial.println("******************************");    
    Blynk.virtualWrite(V3, lightThreshold);
}

// *********  

BLYNK_WRITE(V2) // Blynk app WRITES Slider widget  
{
    delayColorFade = param.asInt(); // macht aus den Blynk-Werten millisekunden
    Serial.println("******************************");    
    Serial.print(delayColorFade);    
    Serial.println(" milli-sec = new Delay for Function ColorFade");    
    Serial.println("******************************");    
    Blynk.virtualWrite(V1, delayColorFade);
}

// *********    

BLYNK_WRITE(V0) // zeRGBa - Color
{ 
  // The param can contain multiple values, in such case:
  int red = param[0].asInt();
  int green = param[1].asInt();
  int blue = param[2].asInt();
  
  analogWrite(REDPIN, red); 
  analogWrite(GREENPIN, green);
  analogWrite(BLUEPIN, blue);
}


/// ********* 

void setup() {

  Serial.begin(9600);
  digitalWrite(boardLed,HIGH);  // Now flash the D7 LED on and off 
  
  // if the sensor is calibrated
  if (calibrated())
  {  

      pinMode(REDPIN, OUTPUT);
      pinMode(GREENPIN, OUTPUT);
      pinMode(BLUEPIN, OUTPUT);
      
      pinMode(boardLed,OUTPUT);         // on-board LED 
      pinMode(ledPin, OUTPUT);          // control PIR LED
      pinMode(inputPIR, INPUT);         // declare sensor as input
      pinMode(inputBrightness, INPUT);  // declare sensor as input
      
      digitalWrite(boardLed,HIGH);  // Now flash the D7 LED on and off 
      Particle.publish("PIR-Motion", "PIR now online - Flur oben", PRIVATE);  // informs user via Particle Cloud
      digitalWrite(boardLed,LOW);   
     
  }
  particle_timer_PIR.start();
  particle_timer_Brightness.start();
  digitalWrite(boardLed,LOW);   
  
      // Blynk magic
  Blynk.begin(auth);    // Start Blynk
  
}
 
// *********  

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

// *********

bool calibrated() {
  return millis() - calibrateTime > 0;
}

// ********

void reportPIRStatus() {
  // check the PIR-Sensor : all 1 sec
  int pirNewState = digitalRead(inputPIR);
  Serial.println(pirNewState);  

  if (pirNewState == pirState) return; // no further action required
  pirState = pirNewState; 

  setLED(pirState);
  
  if (pirState) {
    // send events and start color fading
         if (ambientBrightness <= lightThreshold) {
            Particle.publish("PIR Motion", "LED Streifen an", PRIVATE);
            ColorFade();
         }
  }
}

// *********

void setLED( int state )
{
  digitalWrite(ledPin, state);
}

// *********

void ColorFade() {

    // LED Streifen anschalten
  analogWrite(REDPIN, red); 
  analogWrite(GREENPIN, green);
  analogWrite(BLUEPIN, blue);
  
  // circa! 15 Sekunden bleibt Licht per Default an bzw. solange, wie über den Blynk Slider eingestellt wurde
  for (i = 1; i <= (delayColorFade * 100000); i++)
  
  // LED Streifen ausschalten
  analogWrite(REDPIN, 0);
  analogWrite(BLUEPIN, 0);
  analogWrite(GREENPIN, 0);
  
}

// ********** Neuaufnahme von Funktionen für den TSL2561 - Start

void readBrightness()
{ 
 // read the input on analog pin A3:
 // 0-3.3V input and 0-4095 range
 // https://docs.particle.io/reference/device-os/firmware/photon/#analogread-adc-
  int ambientBrightness = analogRead(inputBrightness);
  
  if (ambientBrightness)
  {
  // print out the value you read:
    Serial.println(ambientBrightness);  
    Blynk.virtualWrite(V7, ambientBrightness);
  }
  else
  {
    Serial.println("Sensor ALSPT19 Light - reading error");
  }
}

ScruffR gaves me also feedback in another older thread here.
I opened also a Thread in Blynk-Community with no feedback.


#4

@Postler, a “clean” loop() to me means non-blocking, thus my recommendation for using millis() timers. Another thing is that you don’t handle any Blynk server disconnection events. If the Blynk connection does down, the code will simply continue trying to send to the Blynk server. You may want to try turning on threading to see if it helps.

Also, I noticed you have a Particle.publish() in one of your Timer callbacks. I would think that @ScruffR may have recommended not doing so in his past advice.


#5

Your ColorFade() function looks odd.
What is that for() loop intended to do?
The comment suggests 15 seconds dead blocking (which is a bad idea since it will break cloud connection) but since you are not terminating the statement you are actually calling analogWrite(REDPIND, 0) 100000 times in rapid succession.

Which code exactly? (SOS + x)


#6

Today I give you more information about my krudes thinking :wink: I’m grateful for any hint, I’m not a trained programmer, but I work out everything through the documentary and your hints. I did not realize that a for loop counts as blocking code. I’m probably not sure what Blynk next to the delay() can still block everything.

Where am I standing right now? After all, after implementing peekay´s hints, the panic mode has stopped. Have enabled threading and introduced Connection Management for Blynk (their treatment is still in vain).
The Particle.publish() is a control tool for me atm and can still be disabled.

I replaced the for or a delay in ColorFade with a timer. I do not know how else I should switch on/off the LED for a temporary period.

My biggest hurdles:

  • Inside the app, Blynk still shows offline,
  • please check if I still have blocking code,
  • the LED strip will turn on, but will not turn off after the timer (15 sec) expires,
  • after a reset, sometimes the LED strip is activated with (any hue), even without PIR triggering.
    maybe this is the reason in setup: while (Blynk.connect() == false) { }
    After a blynk timeout a color appear.

I’ll probably have to put a bounty to the solution.

https://go.particle.io/shared_apps/5c3e5c4bb211a8c25e0016c5


#7

Hi @Postler
sorry to hear that you are having issues with Blynk.
On my side, I use blynk every day at home with few projects that have been running fine for quite some time now. But I may not be running the latest blynk lib. If there was a new blynk lib that introduced something, I wouldn’t know.
I’d say I get in trouble with Blynk around 2 or 3 times a year, not more. Somehow pretty stable!


#8

@Postler, in your timer callback code for reconnectBlynk() you call Blynk.connect() without a timeout. As such, the entire callback will stop until a connection is established. Since this stalls the timer callback, all other timer callbacks will also be stalled since timers are services in a round-robin fashion.

Unfortunately, it seems that Blynk.connect() is a blocking function with a default timeout of 30s. So regardless of where you put this code, it will block during reconnection. It may be best to put in loop() where you it wont block other timers. Since Blynk uses TCP, you may also want to check on WiFi.ready() even if you code is running in AUTOMATIC mode.

Other notes:

  • You call digitalWrite(boardLed,HIGH); before configuring the pinMode() for that pin
  • You qualify ALL the pinMode() calls with if (calibrated()) which will most likely fail every time since millis() will be less than 5000 when setup() is run, especially since you enabled threading. You need to rethink your “calibrated” logic.
  • One note on using millis() for timing is that is returns anunsigned int. As such, any variable used for calculating time differences (eg. calibrateTime) need to be declared as unsigned int as well.

This use of this code is not clear:

            particle_timer_ColorFade.start();
            if (!particle_timer_ColorFade.isActive()) {
                ColorFade_off();

The Software Timer you configured will run forever and will always be active. Also once you start the timer, calling start() again simply resets its timing to start over. Calling stop() or using a one-shot timer (after it times out) would return isActive() as false. I’m not sure what you were trying to achieve here.

I believe there are examples of similar code, possibly using neopixels if I recall, which may be beneficial to look at so it is worth a search.


#9

short status: first thanks again for your help - so far I have the biggest step with an older blynk lib version (instead of 054 back to 047). Smartphone app shows so far “always online”!