How to decrease response time with Blynk

Hey,

I’m a new Blynk user. I’m using it to command a little simulation of a smart home with a Node MCU ESP32 via WIFI.

The code is not really complexe since it’s my fist experience with microcontrollers, i’m using ADC pins to collect datas from few sensors (gaz detection, infrared, temperature and humidity etc…) and switch on/off some leds, buzzers, fans and a DC motor with two end switches.

So I did the entire code (I can add it here if it’s useful) and implemented the Blynk function after. But I’ve met two problems :

  • The MCU is quite heating when I execute this program with Blynk (compared to its heat when WIFI is off, I don’t know its real temperature, after an two hours it’s not burning me but it’s still hot)

  • The reponse time has increased pretty well. When i’m not using it’s really low, the outputs are responding instantaneously, but when i turn the same sketch with Blynk it’s increasing a lot, for maybe 1 second at least.

My program goes that way :

Global variables

Void setup() {

Blynk.begin(..);
timer.setInterval(200L, myprogram);

Inputs/outputs etc..
}

Void loop () {

Blynk.run();
timer.run();
}

Void myprogram() {
My sketch is here, all the measures, actions on the outputs, virtual writings etc..
}

I also tried to reduce the timer’s interval to 1L, but i don’t really think it’s the right thing to do.

What i need is to let my original program work with a response time as low as possible, but I guess the way I did is not correct, thank’s for any help. :slight_smile:

First question, what do you mean by “response time” and how are you measuring it?

Second question, are you using Blynk Legacy (0.1) or Blynk IoT ?

Well, the code snippet you posted tells us nothing.

You’ve got that right. Trying to run whatever code is in your myprogram() once every millisecond (1000 times per second) isn’t likely to work. INCREASING that number to a more realistic value may work, but it depends on what is in your myprogram() function, and what the answer to the “response time” question is.

Pete.

At first I’d like to say thank you for the fast answer. ^^

By time response i mean the time that my outputs take to answer, for example without Blynk the DC motor stops working at the instant i press on the end switch, but when i add the blynk feauture it spends more time. Same for the other outputs, I had set a buzzer to blink when a gas is detected, and when it works with Blynk the intervals on/off of the buzzer are increasing, that’s pretty annoying.

And I’m not meausuring it, the outputs directly seem to be late.

I’m using the first version for now, the 0.1 one.

Okay, I’ll post it in ten minutes the time for me i set the comments on it in english.

That’s what i was thinking, in fact the main thing i want is the outputs to reacts fast, for the transmission of the datas to Blynk even if it is only few seconds later it would be great, i’ll add the code.

As I said this code controlls a smart house, an LDR, infrared sensor, gas sensor, rain sensor, a DHT 22 and an rfid module.

The particular outputs are :

  • When a gas is detected, a led blinks twice then waits 1s, it makes a loop.
  • When water is detected by the rain sensor it deploys a sliding roof until it reaches a first end switch, it waits 5s, if there’s no water on it this time it closes untill it reaches the second end switch.

As i did here, the outputs are responding late compared to how fast it were responding before i add the Blynk feature (the blinking output of the gas sensor turning slowly, the motor keeps working 1s after it reaches the end switches, etc…).

I tried different values for the Blynk.timer and it’s still slow, i’m very probably doing something wrong.

The thing i want is to keep the time response low and use this sketch with Blynk. :slight_smile:

EDIT : I just corrected the title of the topic, i want to DECREASE the response time to make my outputs answer faster. ^^’

Here is the code :

#define BLYNK_PRINT Serial

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

char ssid[] = "wifi";
char pass[] = "pass";
char auth[] = "auth";

BlynkTimer timer;         


                                          //Rain sensor

#include <Arduino.h>                                     
#include <analogWrite.h>                                

int PL;                                        

#define PL_Pin               39
#define Led_Blanche          27
#define fin_de_course_ext    35      
#define fin_de_course_int    34
#define Ouverture             0
#define Fermeture             4

const int Com7 = 2800;                             
const int Com8 = 3200;                                 

int Fin_int;                          
int Fin_ext;                                   
                             
unsigned long ref_pluie;
const unsigned long temporisation_moteur = 5000;          //Period before the motor answers

const int V = 250;                                        //Motor Speed (PWM)


                                          //RFID

#include <SPI.h>                              
#include <Wire.h>                                
#include <MFRC522.h>                            

#define SS_PIN    13                                      //Pin SDA sur Pin 33
#define RST_PIN    2                                      //Pin RST sur Pin 32
#define Led_Verte 12                                      //Led Verte sur Pin 12
#define Led_Rouge 14                                      //Led Rouge sur Pin 14

MFRC522 mfrc522(SS_PIN, RST_PIN);            

unsigned long ref_rfid;                      
const unsigned long temps = 3000;                         //Time the leds stay ON


                                          //LCD

#include <Wire.h> 
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27,16,2);                         //Paramétrage du LCD


                                          //Création de nouveaux caractères

    byte deg[] =                                          //Icône Degré
    {
    B00111,
    B00101,
    B00111,
    B00000,
    B00000,
    B00000,
    B00000,
    B00000,
    };

    byte soleil[] =                                       //Icône Soleil
    {
    B00100,
    B10001,
    B01110,
    B11111,
    B01110,
    B10001,
    B00100,
    B00000,
    };

    byte lune[] =                                         //Icône Lune
    {
    B01110,
    B11101,
    B11010,
    B11000,
    B11101,
    B11111,
    B01110,
    B00000,
    };

    byte pluie[] =                                        //Icône Pluie
    {
    B00110, 
    B11111,
    B11111,
    B00000,
    B10010,
    B00000,
    B00101,
    B00000,
    };


                                          //DHT 22

#include <Adafruit_Sensor.h>               
#include <DHT.h>              
#include <DHT_U.h>          

DHT_Unified dht(25, DHT22);   

#define Ventilateur_dht 15

unsigned long ref_dht;
const unsigned long IDHT = 2000;                          //The period between two temperature/humidity measurements from the DHT22


                                          //LDR
                                          
int LDR;

#define LDR_Pin 33                                        
#define Relais 5                                          //Relay on pin 5

const int Com1 = 3200;                            
const int Com2 = 3400;                             


                                          //Infrarouge
                                          
int INF;

#define INF_Pin  32                                        //Définition de INF
#define Led_Bleue 16

const int Com3 = 700;                                     //Seuil bas  INF
const int Com4 = 1000;                                    //Seuil haut INF


                                          //MQ2

int MQ;                                                                                                

#define MQ_Pin  36                                      
#define Led_Buzzer 17 
#define Ventilateur_Mq 26

const int Com5 = 400;                                    
const int Com6 = 600;                                   

int ledstate = 0;                                         //to initialise the Led_Buzzer blinking 
int general_state;

unsigned long ref_mq;
const unsigned long Blinkon = 100;                        //Period MQ outputs are On
const unsigned long Blinkoff = 30;                        //Period MQ outputs are Off
const unsigned long Blinkoff2 = 1000;                     //Period MQ outputs are Off 2






void setup(){                       


  Serial.begin(9600);                                     
  delay(1000);                                         

  Blynk.begin(auth, ssid, pass,IPAddress(IP and port);
  timer.setInterval(1000L, myprogram);

                                          // RFID

  SPI.begin();   
  mfrc522.PCD_Init();  


                                          // LCD and chars

  lcd.init();
  lcd.backlight();
 
  lcd.createChar(0, deg);
  lcd.createChar(1, soleil);
  lcd.createChar(2, lune);
  lcd.createChar(3, pluie);


                                          // DHT22

  dht.begin();                                            
  sensor_t sensor;
  dht.temperature().getSensor(&sensor);
  dht.humidity().getSensor(&sensor);


                                          // Inputs/Outputs

  pinMode(LDR_Pin ,  INPUT);
  pinMode( Relais , OUTPUT);                              //Définition Pin  5 en sortie     //    Relais                           //    Sortie LDR Pin  5

  pinMode( INF_Pin ,  INPUT);
  pinMode(Led_Bleue, OUTPUT);                             //Définition Pin 16 en sortie     //    Led Bleue (Système ON)           //    Sortie INF Pin 16

  pinMode(    MQ_Pin    ,  INPUT);                        //Définition Pin 36 en entrée     //    Entrée du MQ2
  pinMode(  Led_Buzzer  , OUTPUT);                        //Définition Pin 17 en sortie     //    Led Jaune + Buzzer (Système ON)  //    Sortie MQ2 Pin 17
  pinMode(Ventilateur_Mq, OUTPUT);                        //Définition Pin 26 en sortie     //    Ventilateur 1 (Système ON)       //    Sortie MQ2  Pin 26

  pinMode(Ventilateur_dht, OUTPUT);                       //Définition Pin 15 en sortie     //    Ventilateur 2 (Système ON)       //    Sortie DHT Pin 15

  pinMode(      PL_Pin     ,  INPUT);                     //Définition Pin 39 en entrée     //    Entrée du Détecteur de pluie     //    Entrée PL   Pin 39
  pinMode(fin_de_course_ext,  INPUT);                     //Définition Pin 35 en entrée     //    Entrée du Fin de Course 1        //    Entrée Fin  Pin 35 
  pinMode(fin_de_course_int,  INPUT);                     //Définition Pin 34 en entrée     //    Entrée du Fin de Course 2        //    Entrée Fin1 Pin 34 
  pinMode(   Led_Blanche   , OUTPUT);                     //Définition Pin 27 en sortie     //    Led Blanche (Système ON)         //    Sortie PL   Pin 27
  pinMode(    Ouverture    , OUTPUT);                     //Définition Pin  0 en sortie     //    Déploiement de la terrasse       //    Sortie PL 1 Pin  0
  pinMode(    Fermeture    , OUTPUT);                     //Définition Pin  4 en sortie     //    Retour de la terrasse            //    Sortie PL 2 Pin  4

  pinMode(Led_Verte, OUTPUT);                             //Définition Pin 12 en sortie     //    Led Verte (Système ON)           //    Sortie RFID Pin 12
  pinMode(Led_Rouge, OUTPUT);                             //Définition Pin 14 en sortie     //    Led Rouge (Système OFF)          //    Sortie RFID Pin 14

                                          //If the roof is deployed, this will undeploy it

  if (Fin_int < 2000)
  {
      analogWrite(Fermeture, V);
  }

  else if (Fin_int > 2000)
  {
      analogWrite(Fermeture, 0);
  }

                                          //Initialising millis references

ref_mq    =  millis();
ref_pluie =  millis();
ref_dht   =     0    ;
ref_rfid  =  millis(); 
ref_blynk =  millis();
}


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

 
void myprogram(){                              
                                         
                                          //LDR
  {
    LDR = analogRead(LDR_Pin);                                
    Blynk.virtualWrite(V4, LDR);
    
    if (LDR < Com1)                                       //Condition 1 : LDR is in the dark
    {
      digitalWrite(Relais, HIGH);                             //Pin 12 HIGH
      
      lcd.setCursor(15,0);
      lcd.write(2);

      WidgetLED led_LDR(V7);
      led_LDR.on();
    }
    else if (LDR > Com2)                                  //Condition 2 : LDR is exposed to the light
    {
      digitalWrite(Relais, LOW);                              //Pin 12 LOW
      
      lcd.setCursor(15,0);
      lcd.write(1);

      WidgetLED led_LDR(V7);
      led_LDR.off();
    }
  }

                                          //INFRARED
  {
    INF = analogRead(INF_Pin);                                 
    Blynk.virtualWrite(V3, INF);
    
    if (INF > Com4)                                       //Condition 1 : INF detects something
    {
      digitalWrite(Led_Bleue, HIGH);                             //Pin 16 HIGH
    }
    else if (INF < Com3)                                  //Condition 2 : INF doesn't detect anything
    {
      digitalWrite(Led_Bleue, LOW);                              //Pin 16 LOW
    }
  }

                                          //Programme du MQ2
  {
    MQ = analogRead(MQ_Pin);                                  
    
    if (millis() - ref_blynk >= temps_blynk)
    {
    Blynk.virtualWrite(V2, MQ);
    }

    if (MQ >= Com6)                                       //Condition 1 : MQ detects a gaz
    {
      digitalWrite(Ventilateur_Mq, HIGH);
      general_state = 1;

      Blynk.notify("Gaz détecté !");
      
      if ((millis() - ref_mq >= Blinkoff2)  && ledstate == 0)         //Step one, waits 1s
      {
        ref_mq = millis();        
        digitalWrite(Led_Buzzer, HIGH);                               //Out is HIGH
        ledstate = 1;
      }

      else if ((millis() - ref_mq >= Blinkon) && ledstate == 1)       //Step two, waits 100ms
      {
        ref_mq = millis();                                            //Out is LOW
        digitalWrite(Led_Buzzer, LOW);                                        
        ledstate = 2;
      }
      
      else if ((millis() - ref_mq >= Blinkoff)  && ledstate == 2)     //Step three; waits 30ms
      {
        ref_mq = millis();        
        digitalWrite(Led_Buzzer, HIGH);                               //Out is HIGH
        ledstate = 3;
      }
      
      else if ((millis() - ref_mq >= Blinkon) && ledstate == 3)       //Step four and the last one, waits 100ms again then comes back to Step one.
      {
        ref_mq = millis();
        digitalWrite(Led_Buzzer, LOW);                                //Out is LOW      
        ledstate = 0;
      }
    }

    else if (MQ <= Com5)                                   //Condition 2 : no GAZ
    {
      ref_mq = millis();
      digitalWrite(Ventilateur_Mq, LOW);
      digitalWrite(Led_Buzzer, LOW);                             
      ledstate = 0;
      general_state = 0;
    }

                                                  

    else if (Com5 <= MQ <= Com6)                          //This part is to create an Hysteresys for the outputs
    {
      if (general_state == 0)                             //If the outputs were previously LOW, keep them LOW
      {
      ref_mq = millis();
      digitalWrite(Ventilateur_Mq, LOW);
      digitalWrite(Led_Buzzer, LOW);                               
      ledstate = 0;
      }
      
      else if (general_state == 1)                        //If the outputs were previously HIGH, keep them HIGH
      {
        digitalWrite(Ventilateur_Mq, HIGH);
      
      if ((millis() - ref_mq >= Blinkoff2)  && ledstate == 0)       
      {
        ref_mq = millis();        
        digitalWrite(Led_Buzzer, HIGH);                          
        ledstate = 1;
      }

      else if ((millis() - ref_mq >= Blinkon) && ledstate == 1)
      {
        ref_mq = millis();
        digitalWrite(Led_Buzzer, LOW);                              
        ledstate = 2;
      }
      
      else if ((millis() - ref_mq >= Blinkoff)  && ledstate == 2)
      {
        ref_mq = millis();        
        digitalWrite(Led_Buzzer, HIGH);                     
        ledstate = 3;
      }
      
      else if ((millis() - ref_mq >= Blinkon) && ledstate == 3)
      {
        ref_mq = millis();
        digitalWrite(Led_Buzzer, LOW);                                   
        ledstate = 0;
      }
      }
    }
  }


                                          //Rain sensor
  {       
    Fin_ext = analogRead (fin_de_course_ext);
    Fin_int = analogRead (fin_de_course_int);

    if (Fin_ext > 2000)                                     //If i press on the external end swith
    {
      analogWrite(Ouverture, 0);                            //Stops the opening of the "garage"
    }
        
    if (Fin_int > 2000)                                     //If i press on the internal end swith
    {
      analogWrite(Fermeture, 0);                            //Stops the garage from closing
    }

    { 
      PL = analogRead(PL_Pin);                           
                
      if (PL < Com7)                                        //Condition 1 : PL detects rain
      {      
        if (millis() - ref_pluie >= temporisation_moteur)         
        {
          digitalWrite(Led_Blanche, HIGH);                          
      
          lcd.setCursor(15,1);
          lcd.write(3);

          if (Fin_ext < 2000)
            {
              ref_pluie = millis(); 
              analogWrite(Ouverture, V);                  //Deploys the roof
              analogWrite(Fermeture, 0); 
            }
        }
      }    
            
      else if (PL > Com8)                                   //Condition 2 : No rain
      {
        if (millis() - ref_pluie >= temporisation_moteur)
        {
          digitalWrite(Led_Blanche, LOW);                              
     
          lcd.setCursor(15,1);
          lcd.write(' ');

          if (Fin_int < 2000)
            { 
              ref_pluie = millis();   
              analogWrite(Ouverture, 0);
              analogWrite(Fermeture, V);                    //Returns the roof inside
            }
        }
      }    
    }    
  }

                                          // DHT22
  {
    if (millis() - ref_dht >= IDHT)                            
    { 
      sensors_event_t event;                              
      dht.temperature().getEvent(&event);
      if (isnan(event.temperature)) 
      {
        Serial.println(F("Error reading temperature!"));
      }
      
      else 
      {
        Serial.print(F("Temperature: "));             
        Serial.print(event.temperature);
        Serial.println(F("°C"));
      }

        lcd.setCursor(0,0);
        lcd.print("Tp. : ");
        lcd.print(event.temperature);
        lcd.print(" ");
        lcd.write(0);
        lcd.print("C");

        Blynk.virtualWrite(V0, event.temperature);

      dht.humidity().getEvent(&event);
      if (isnan(event.relative_humidity)) 
      {
        Serial.println(F("Error reading humidity!"));   
      }
      else 
      {
        Serial.print(F("Humidity: "));                  
        Serial.print(event.relative_humidity);
        Serial.println(F("%"));
        Serial.println();                          

        lcd.setCursor(0,1);
        lcd.print("Hu. : ");
        lcd.print(event.relative_humidity);
        lcd.print("  ");
        lcd.print("%");

        Blynk.virtualWrite(V1, event.relative_humidity);

        if (event.relative_humidity > 50)
    {
      digitalWrite(Ventilateur_dht, HIGH);
    }
    else if (event.relative_humidity < 50)
    {
      digitalWrite(Ventilateur_dht, LOW);
    }
      }      
        
      ref_dht = millis();                                 
    }
  }                                  

                                          // RFID :
{
  
  if ( ! mfrc522.PICC_IsNewCardPresent()) 
  {
    void();
  }

  if ( ! mfrc522.PICC_ReadCardSerial())         //If there are no cards on the module
  {
  if ((millis() - ref_rfid) >= temps)           //Counts 3 seconds then sets the Leds OFF
  { 
    digitalWrite(Led_Verte, LOW);
    digitalWrite(Led_Rouge, LOW);
  }
  return;
  }
  
  String content= "";
  byte letter;
  for (byte i = 0; i < mfrc522.uid.size; i++) 
  
  {
     content.concat(String(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " "));
     content.concat(String(mfrc522.uid.uidByte[i], HEX));
  }
  
  content.toUpperCase();
  
  
  if (content.substring(1) == "Right Card")    //If the right card is detected
  { 
    ref_rfid = millis();
    digitalWrite(Led_Verte, HIGH);           
    digitalWrite(Led_Rouge, LOW);      
    
    Blynk.notify("Module RFID : Accès Autorisé");
  }  

  else                                        //If the wrong card is detected
    {
    ref_rfid = millis();
    digitalWrite(Led_Verte, LOW);
    digitalWrite(Led_Rouge, HIGH);
    
    Blynk.notify("Module RFID : Accès Refusé");
    }
}

}
                                          //end

Well, I’m not surprised that you’re having issues.

First of all, I’d avoid using a BlynkTimer and millis comparisons in the same sketch.

Secondly, I’d suggest that you split your processes into separate functions and decide what your priorities are for these processes.
Do you really need to take light and humidity readings more frequently than once every 10 seconds?

The “end button” that you mentioned earlier appears to be connected to an analogue input, is this correct?
Is there a reason for this?
You’d be better having buttons attached to GPIOs and use interrupts to monitor these buttons rather than having to poll them constantly.

Also, when you’re sending Blynk notifications you need to use a flag to ensure that only one notification is sent, otherwise you’ll easily exceed the notification limit.

Pete.

So i should replace my millis comparisions by other timers ?

Yes I had this idea after searching on the forum but I was wondering if there were no easier way to make it work well, as it was the case untill now. :no_mouth:

So i’ll put the priority on the end switches and the gas sensor I guess, for the remaining ones i’ll see.

I used the end switches like this :

  • With the wiring i used, when i press on the switch it sends a HIGH signal to the input (4095 after the conversion), and when i don’t presse on it it stays at 0 with a pulldown resistor.

I didn’t know there was another method.

And for the interrupts i could and i should use them you’re right, it would be better. In fact I was waiting for the Blynk sketch to work properly before I do it, i never tried to do an interrupt. :no_mouth:

I was searching for this too, and your answer is really helpful.

So to summurize, I should :

  • Replace the “millis” by timers
  • Separate the functions one by one and set the timers by priority order.
  • Use interrupts for the end switches.
  • Creat flags for the blynk notifications.

Is it all ?

If you split your myprogram() function into separate functions then these will be called with separate timers.
Just ensure that you design these timers so that they don’t all align at regular intervals.

Pete.

Okay i’ll do this, thank you again for your help. :slight_smile:

Edit : I’m just here for a little update, I did follow your advices Pete and now it works like a charm, no spam notifications, quick response of the outputs… I still have some stuff to do like studiying the different possible schematics for the execution of the program, and make few tries to get exactly what i want but now it’s gonna be easy. :slight_smile:

Even the heating issue is gone, the old sketch was probably the problem since it was executing a lot of tasks in a short interval. Actually the temperature of the microcontroller is so much better than before.

I still have a little question and then I’ll be done.

Is there a limit for the timer function I shoulnd’t cross, for example if i want the infrared sensor’s response to be in “real time”, can i set the interval as “timer.setInterval(1L, infrared)” (or any value close enough to it like 10L or something kind of it) ?

To be honest, you probably,y need the IR sensor code in the void loop if you want it to work correctly, as it will be very timing dependent.

My preference is always to have multiple MCUs, each dedicated to a particular task. This is usually dictated by the location of the things they are controlling, or where it is most convenient to locate them. It’s very rare that I have multiple input/output devices in the same location, unless it’s something like a weather station where multiple sensors are located in t(e same place and therefore feeding their data to one MCU.

Pete.

1 Like

I see, then for a bigger project or a more realistic one i’ll probably choose to use multiple MCUs as you said.

For this one i’ll consider it as done since I had a limited time to realize it. And maybe try adapt it for multitasking with the two cores someday when I’ll have enough knowledge to do it.

Okay so i guess that’s all, thanks a lot for your help. :slight_smile:

1 Like