[SOLVED] Problems in reading and writing data simultaneously on the widgets

Dear Blynk Team,

first of all, I’d like to send you my congratulations for your great and hard work ! I’m willing to support you in the job of continuous improvement and development of your creature.

I discovered Blynk a couple of months ago and I’m developing an application with an IMU (MPU 6050) associated to an Arduino Nano and an ESP8266 used as Wi-Fi shield for the Arduino. The ESP8266 is powered with a separate 3.3 volt power supply.

But I’m fighting with a problem that I’d like to share with you. The project dashboard is composed by 3 displays and 3 graphs (one for each axis of the IMU) and also 3 buttons used to select the data to display (Accelerations or Velocity or Inclination). The refresh of data on the dashboard is managed by a simple timer function with a period of 8 sec. The refresh process lasts about 3 sec.

The app works correctly when the data are only displayed. Every 8 sec the data are refreshed and the system is able to works for entire days. No problem !! BUT if I try to activate one of the buttons WHILE the process refresh is active (BLYNK_WRITE function activated simultaneously to a Blynk.virtualWrite instruction) the app stops and loses the connection withthe server.

I have to activate the buttons only during the 5 sec in which the displays refresh is not going-on in order to avoid this problem. So, to work around, I added a led that switches on at the beginning of the refresh period and switches off at the end, in order to know when I can play with the buttons …

I would be very pleased if you could give me a solution to this issue.
Thanks in advance and best regards,
Giancarlo

@Gianca are you sure it is the simultaneous BLYNK_WRITE and Blynk.virtualWrite that is the problem?

The amount of data transferred to the Blynk server under normal circumstances is quite modest unless there is a ‘problem’ with the sketch but I’m guessing the MPU 6050 has quite a lot of data to transfer.

Are you able to provide a small extract of the sketch where the BLYNK_WRITE and Blynk.virtualWrite commands are processed?

1 Like

@Costas +1. @Gianca we need your code :slight_smile:

Hi,
please find attached, the code of the sketch.
I’d like to remark that the issue is not relevant to the MPU 6050. You can emulate the same problem e.g. reading any value from the analog pins of Arduino and then displaying them.
In addition I confirm that the problem arises only when I activate the push buttons during the refresh of displays. If I touch the selection buttons when the refresh is not on going the sketch works fine.
For this reason I have added the led connected to V10 in order to know when I can touch the selection buttons.
Thanks for your support !!


    #define RX 2      // Arduino RX line on pin D2
    #define TX 3      // Arduino TX line on pin D3

    #define MPU 0x68  // I2C address of the MPU-6050

    #define Accl_x_Offset +800
    #define Accl_y_Offset -180
    #define Accl_z_Offset -1800

    #define Gyro_x_Offset -306
    #define Gyro_y_Offset -96
    #define Gyro_z_Offset +12

    #include <SoftwareSerial.h>
    #include <Wire.h>

    #include <ESP8266_SoftSer.h>
    #include <BlynkSimpleShieldEsp8266_SoftSer.h>
    #include <SimpleTimer.h>

    SoftwareSerial esp_8266(RX, TX);

    ESP8266 wifi(esp_8266);

    SimpleTimer timer;

    char token[] = "xxx";
    char  ssid[] = "yyy";
    char  pass[] = "zzz";

    unsigned long Period = 8000;  // Refresh period = 8 sec

    unsigned long New_Time = 0, Old_Time = 0;
    float Loop_Time;

    int Temp_Raw;
    int Accl_x_Raw, Accl_y_Raw, Accl_z_Raw;
    int Gyro_x_Raw, Gyro_y_Raw, Gyro_z_Raw;

    float Temp;
    float Accl_x, Accl_y, Accl_z;
    float Gyro_x, Gyro_y, Gyro_z;
    float Angle_x, Angle_y, Angle_z;

    float New_Accl_x = 0.0, New_Accl_y = 0.0, New_Accl_z = 0.0;
    float Old_Accl_x = 0.0, Old_Accl_y = 0.0, Old_Accl_z = 0.0;

    float New_Velo_x = 0.0, New_Velo_y = 0.0, New_Velo_z = 0.0;
    float Old_Velo_x = 0.0, Old_Velo_y = 0.0, Old_Velo_z = 0.0;

    int meas_type = 0;

    void setup()
    {
      Serial.begin(9600);

      Wire.begin();
      Wire.beginTransmission(MPU);
      Wire.write(0x6B);  // PWR_MGMT_1 register
      Wire.write(0);     // set to zero (wakes up the MPU-6050)
      Wire.endTransmission();

      esp_8266.begin(9600);
      Blynk.begin(token, wifi, ssid, pass);
      timer.setInterval(Period, Display_Refresh);
      
      Blynk.run();
      Blynk.virtualWrite(V7, 0);  // At start-up system is setted as accelerometer
      Blynk.virtualWrite(V8, 1);
      Blynk.virtualWrite(V9, 1);
    }

    void loop()
    {
      // START CUSTOM CODE
      
      New_Time = millis();
      Loop_Time = (New_Time - Old_Time) / 1000.0;  // Loop Time in seconds
      Old_Time = New_Time;
      
      Wire.beginTransmission(MPU);
      Wire.write(0x3B);                         // starting with register 0x3B (ACCEL_XOUT_H)
      Wire.endTransmission();
      Wire.requestFrom(MPU, 14);                // request a total of 14 registers
      
      // Acquisition of raw values from MPU 6050
      Accl_x_Raw = Wire.read()<<8|Wire.read();  // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)
      Accl_y_Raw = Wire.read()<<8|Wire.read();  // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
      Accl_z_Raw = Wire.read()<<8|Wire.read();  // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L)

      Temp_Raw   = Wire.read()<<8|Wire.read();  // 0x41 (TEMP_OUT_H)   & 0x42 (TEMP_OUT_L)

      Gyro_x_Raw = Wire.read()<<8|Wire.read();  // 0x43 (GYRO_XOUT_H)  & 0x44 (GYRO_XOUT_L)
      Gyro_y_Raw = Wire.read()<<8|Wire.read();  // 0x45 (GYRO_YOUT_H)  & 0x46 (GYRO_YOUT_L)
      Gyro_z_Raw = Wire.read()<<8|Wire.read();  // 0x47 (GYRO_ZOUT_H)  & 0x48 (GYRO_ZOUT_L)

      // Offset Elimination
      Accl_x_Raw -= Accl_x_Offset;
      Accl_y_Raw -= Accl_y_Offset;
      Accl_z_Raw -= Accl_z_Offset;
      
      Gyro_x_Raw -= Gyro_x_Offset;
      Gyro_y_Raw -= Gyro_y_Offset;
      Gyro_z_Raw -= Gyro_z_Offset;

      // Conversion from raw values to Accelerations [g],
      // Temperature [°C] and Rotation Speed [°/sec]
      Accl_x = (float) Accl_x_Raw * 4.0 / 65536.0;
      Accl_y = (float) Accl_y_Raw * 4.0 / 65536.0;
      Accl_z = (float) Accl_z_Raw * 4.0 / 65536.0;
      
      Temp = ((float)Temp_Raw + 521.0) / 340.0 + 29.1;  // Default value = + 35
      
      Gyro_x = (float) Gyro_x_Raw * 500.0 / 65536.0;
      Gyro_y = (float) Gyro_y_Raw * 500.0 / 65536.0;
      Gyro_z = (float) Gyro_z_Raw * 500.0 / 65536.0;
      
      // Conversion from acceleration to angle
      Angle_x = atan (Accl_x / sqrt (square (Accl_y) + square (Accl_z))) * 180/PI;
      Angle_y = atan (Accl_y / sqrt (square (Accl_x) + square (Accl_z))) * 180/PI;
      Angle_z = atan (Accl_z / sqrt (square (Accl_x) + square (Accl_y))) * 180/PI;
      
      // Conversion of Accelerations from g to (m/s)/s
      
      Accl_x *= 9.81;
      Accl_y *= 9.81;
      Accl_z *= 9.81;
      
      // Computation of velocity in mm/s

      New_Accl_x = Accl_x;
      New_Accl_y = Accl_y;
      New_Accl_z = Accl_z;

      New_Velo_x = Old_Velo_x + Old_Accl_x * Loop_Time * 1000.0;
      New_Velo_y = Old_Velo_y + Old_Accl_y * Loop_Time * 1000.0;
      New_Velo_z = Old_Velo_z + Old_Accl_z * Loop_Time * 1000.0;

      Old_Accl_x = New_Accl_x;
      Old_Accl_y = New_Accl_y;
      Old_Accl_z = New_Accl_z;

      Old_Velo_x = New_Velo_x;
      Old_Velo_y = New_Velo_y;
      Old_Velo_z = New_Velo_z;

      // START BLYNK CODE
      
      Blynk.run();
      timer.run();
    }

    BLYNK_WRITE(V7)
    {
      int val = param.asInt();
      meas_type = 0;
    }

    BLYNK_WRITE(V8)
    {
      int val = param.asInt();
      meas_type = 1;
    }

    BLYNK_WRITE(V9)
    {
      int val = param.asInt();
      meas_type = 2;
    }

    void Display_Refresh()
    {
      Blynk.virtualWrite(V10, 255);  // Display refres is initiated

      if (meas_type == 0)
      {
        Blynk.virtualWrite(V8, 0);
        Blynk.virtualWrite(V9, 0);
        Blynk.virtualWrite(V7, 1);

        Blynk.virtualWrite(V0, Temp);
        Blynk.virtualWrite(V1, Accl_x);
        Blynk.virtualWrite(V2, Accl_y);
        Blynk.virtualWrite(V3, Accl_z);
        Blynk.virtualWrite(V4, Accl_x);
        Blynk.virtualWrite(V5, Accl_y);
        Blynk.virtualWrite(V6, Accl_z);
      }
      else if (meas_type == 1)
      {
        Blynk.virtualWrite(V7, 0);
        Blynk.virtualWrite(V9, 0);
        Blynk.virtualWrite(V8, 1);

        Blynk.virtualWrite(V0, Temp);
        Blynk.virtualWrite(V1, Velo_x);
        Blynk.virtualWrite(V2, Velo_y);
        Blynk.virtualWrite(V3, Velo_z);
        Blynk.virtualWrite(V4, Velo_x);
        Blynk.virtualWrite(V5, Velo_y);
        Blynk.virtualWrite(V6, Velo_z);
      }
      else if (meas_type == 2)
      {
        Blynk.virtualWrite(V7, 0);
        Blynk.virtualWrite(V8, 0);
        Blynk.virtualWrite(V9, 1);

        Blynk.virtualWrite(V0, Temp);
        Blynk.virtualWrite(V1, Angle_x);
        Blynk.virtualWrite(V2, Angle_y);
        Blynk.virtualWrite(V3, Angle_z);
        Blynk.virtualWrite(V4, Angle_x);
        Blynk.virtualWrite(V5, Angle_y);
        Blynk.virtualWrite(V6, Angle_z);
      }

      Blynk.virtualWrite(V10, 0);  // Display refres is finished
    }

@Gianca am I right in thinking your main loop is doing hundreds of calculations per second? Is this really necessary or could the calculations be called from a timer at intervals.

I don’t like the look of your Blynk_Write() functions. Surely they should include an if statement like this:

BLYNK_WRITE(V7)
{
  int val = param.asInt();
  if (val == 1){
    meas_type = 0;
  }
}

Just checked one of our sketches and maybe you don’t need the IF statements against your BLYNK_WRITE() functions.

Are your buttons set as PUSH or Switch, I am guessing PUSH?

Using your BLYNK_WRITE() functions in one of our sketches the buttons perform as expected. One button shows the time in the LCD and in a value display, another button reads the analogue port and gives us the voltage of the batteries powering the ESP. The buttons are both attached to timers at present (5 and 6 seconds respectively but I will remove the timer and see what they do).

Hi Costas,
yes the button is in push mode and the sketch performs hundreds of calculations per second. Infact in a previous version I put the custom code inside the timer function in order to have a loop() funtion with only Blynk.run() and timer.run(). But I had other issues and so I put the custom code inside the loop function.
I have modified the sketch in accordance to your suggestion but now the program doesn’t work !! (new library ? new app ?). I’m working around …
I understood that you have tried to reply my problem but your program is working fine. Do you confirm?
Best regards,
Giancarlo

Tried to simulate your setup but I can’t replicate the problem. We are using ESP as standalone which works MUCH better than ESP’s as shields.

We have debug switched on to test your scenario and that should slow our system down considerably.

We have just removed the timer so we have one of 2 functions running in the main loop depending which of the 2 buttons (3 in your case) we have pressed. We have also put a for loop in the function to write the details 10 times to the LCD and value displays (to simulate the 10 writes you are doing to different value displays).

Serial Monitor is running like billy ho but we can’t crash the system and the app screen is responding as expected.

Why does it take 3 seconds for your system to respond?

Your problem maybe down to using the ESP as a shield. That said we are running at 115200 baud and you are only using 9600. We wouldn’t recommend shields though.

Dear Blynkers, I was wrong.
I wrote a simple program (see attached) in order to verify my assumption that the simultaneity of reading and writing was an issue and I verified that all is working fine with this test program.
Probably my main program is too much complex or has some other problem.
Only a question: which is the best place to put my custom code? Within the loop() before Blynk.run or inside the timer function ?
Thank you,
Giancarlo

#define BLYNK_PRINT Serial
#define RX 2                // Arduino RX line on pin D2
#define TX 3                // Arduino TX line on pin D3

#include <SoftwareSerial.h>
#include <ESP8266_SoftSer.h>
#include <BlynkSimpleShieldEsp8266_SoftSer.h>
#include <SimpleTimer.h>

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

int analog_val;
int digital_val;

SoftwareSerial esp_8266(RX, TX);

ESP8266 wifi(esp_8266);

SimpleTimer timer;

void setup()
{
  pinMode(7, OUTPUT);
  pinMode(8, INPUT);

  Serial.begin(9600);

  esp_8266.begin(9600);

  Blynk.begin(auth, wifi, ssid, pass);
  
  timer.setInterval(5000, trigger);
}

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

void trigger()
{
  Blynk.virtualWrite(V4, 255);

  analog_val = analogRead(A0);
  Blynk.virtualWrite(V0, analog_val);

  analog_val = analogRead(A1);
  Blynk.virtualWrite(V1, analog_val);

  analog_val = analogRead(A2);
  Blynk.virtualWrite(V2, analog_val);

  analog_val = analogRead(A3);
  Blynk.virtualWrite(V3, analog_val);

  Blynk.virtualWrite(V4, 0);
}

BLYNK_WRITE(V5) // Button activating an active low realy. Feedback on virtual pin V6
{
  digital_val = param.asInt();
  digitalWrite (7, !digital_val);
  
  digital_val = !digitalRead(8);
  Blynk.virtualWrite(V6, digital_val*255);
}

BLYNK_WRITE(V7)  // Timer activating the relay
{
  digital_val = param.asInt();
  digitalWrite (7, !digital_val);
  
  Blynk.virtualWrite(V5, digital_val);
  Blynk.virtualWrite(V6, digital_val*255);
  
  if (digital_val == 1) Blynk.email("g.deviti@gmail.com", "Blynk Test", "Timer ON ... !!");
  else if (digital_val == 0) Blynk.email("g.deviti@gmail.com", "Blynk Test", "Timer OFF ... !!");
}
1 Like

Glad it all checked out ok.

Please explain how frequently you need to do the mass of calculations and then we can advise how best to do it.

Also advise how long it takes to do the calculations as the 3 seconds you referred to sounds a LONG time. Are you launching rockets to Mars?

Hi Costas,
the 3 seconds are the time necessary to refresh the widget of the dashboard. Consider that ESP 8266 exchange data with the nano at 9600 bps and data have to travel from USA to Italy :slight_smile:.
This sketch is for a civil engineer application where is requested to measure vibration and “inclination” of a building.
In your opinion, which is the best place to put my custom code? Within the loop() before the couple Blynk.run() and timer.run() or inside the timer function or in another place ?
Thanks a lot for your attention and availability,
Giancarlo

Do you have all of your value displays set as PUSH FREQUENCY or so many milliseconds?
With PUSH I would expect the 7 value displays and 3 buttons to refresh well under 3 seconds (from USA to Italy).

I wouldn’t do the calcs in the loop.

I would call them at intervals with SimpleTimer. Only you know how frequently you need to do the calculations but as a lay person I wouldn’t have thought vibration and inclination checks need to be dozens of times per second.

You should try to avoid anything in your loop other than run and timer. You mentioned you had some problems when you moved the calculations out of loop before but if you still have them when you move them again we might be able to offer a fix.

Dear Costas,
I’d like to tell you as I have solved the problem .

First of all I agree that the data of vibration and inclination have to be sent not very often and in fact I use a refresh period of 8 sec. But I need to eliminate the static acceleration (gravity acceleration) and so I have coded a high pass filter that, of course, must perform computations very frequently. For this reason I had to put calculation within the loop.

To solve all this I changed completely architecture: one Arduino manages the IMU and perform all the calculation in its loop function and, every 8 sec, transfers data to another Arduino that has only blynk.run and timer within its loop.

Maybe the system is complex but now everything is working fine !!

Have a good night,
Giancarlo

1 Like

Hello Sir, I’m currently doing a project which s exactly the same can you please share the connections …xD

User @Gianca was last seen on the forum on Nov 23, 2017. Tagging him in a post generates an email to his registered email address, so that may prompt him to come back and answer your question.

If someone asked me about a project from 3 years ago, I’m not sure that I’d be able to provide the information you’re asking for. If it’s something that’s still in use today then I think I’d have improved the hardware, code and app over that period of time. If it’s no longer in use then it would have been consigned to the back of drawer.

If you don’t get a response then maybe you should start a new topic about exactly what you’re trying to achieve, and what you’ve done so far.

Pete.

IF that feature is turned on… I leave mine OFF :slight_smile:

Please look at the code before asking… the Serial Shield link is a bog standard RT-TX & TX-RX connection and there are only two other connections for digital pins 7 & 8.

You should be able to figure it out. If not and as already mentioned, please create a current topic full of your project details.