Help! Blynk stuck after wifi resets

Sorry. I copied in the wrong code. I’m using the same method across multiple projects. Here is the code that shows my device that is battery powered and uses deep sleep.


#include <Wire.h>
#include <ESP8266WiFi.h>;
#include <BlynkSimpleEsp8266.h>;
#include <OneWire.h>
#include <TimeLib.h>
#include <WidgetRTC.h>

//V0: 
//V1: Used for table
//V2: User input to store angle and specific gravity value
//V3: Output of averaged angle from V5
//V4: Specific gravity input from user
//V5: Start Reading: used to set array for averaging angle 
//V6: Request for temperature from user
//V7: temperature output
//V8: Battery voltage
//V9: Time from the Blynk RTC
//V10: Date from the Blynk RTC
//V11: Sleep ON/OFF

//Variables for voltage measurement
unsigned int raw = 0;
float volt = 0.0;

//Starting OneWire for communication on pin D6
OneWire ds(D6);

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

// Your WiFi credentials.
// Set password to "" for open networks.
char ssid[] = "******************8";
char pass[] = "**********************";

//Both used for Blynk
BlynkTimer timer;
WidgetRTC rtc;

/*MPU-6050 gives you 16 bits data so you have to create some 16int constants
 * to store the data for accelerations and gyro*/

int16_t Acc_rawX, Acc_rawY, Acc_rawZ,Gyr_rawX, Gyr_rawY, Gyr_rawZ;

//Variables used for measuring angle
float Acceleration_angle[2];
float Gyro_angle[2];
float Total_angle[2];
float averageAngle;

float elapsedTime;
float time_;
float timePrev;
int i;  //used for settling loop
float rad_to_deg = 180/3.141592654;
float celsius, fahrenheit;

const int numReadings = 10;  //Number of data points, after settling angle data, to average
float readings[numReadings];
int readIndex = 0;
float total = 0;  //sum of all angle data points before averaging
float average = 0;  //end result of averaging angle data points
float SG = 1.000;  //Specific gravity calculated from angle
int settleIterations = 1000;  //Number of iterations to read data to let data point of angle settle to a steady value
int delay_time = 20;  //time delay after each angle reading
int deepSleepHours = 1;  //how many hours to deep sleep
int pinValue3 = 1;  //value used to determine if deep sleep should stop/continue

float userSG;
const int arrayLen = 31;
float SGvalue[arrayLen] = {1.000, 1.001, 1.002, 1.003, 1.004, 1.005, 1.006, 1.007, 1.008, 1.009, 1.010, 1.011, 1.012, 1.013, 1.014, 1.015, 1.016, 1.017, 1.018, 1.019, 1.020, 1.021, 1.022, 1.023, 1.024, 1.025, 1.026, 1.027, 1.028, 1.029, 1.030};
float angleValue[arrayLen];
float tempValue[arrayLen];

int wifi_attempt_count=0;
int max_wifi_connect_attempts=20;
int wait_between_wifi_attempts_millis=500;


void clockDisplay()
{
  String currentTime = String(hour()) + ":" + minute() + ":" + second();
  String currentDate = String(month()) + "/" + day() + "/" + year();
  int rtcSeconds = hour() * 3600 + minute() * 60 + second();
  //Serial.print("Current time: ");
  //Serial.print(currentDate);
  //Serial.print(" ");
  //Serial.println(currentTime);
  Blynk.virtualWrite(V9, currentTime);
  Blynk.virtualWrite(V10, currentDate);
}

void averaging_angle()
{
  Serial.println("begin settling process");
  readIndex = 0;
  total = 0;
  average = 0;

  //Loop to read angle values, let the values settle before averaging the last set of values
  for (int i = 0; i <= settleIterations; i++)
  {
    timePrev = time_;  // the previous time is stored before the actual time read
    time_ = millis();  // actual time read
    elapsedTime = (time_ - timePrev) / 1000; 
    
/////////////////////////////I M U/////////////////////////////////////
  
  /*The timeStep is the time that elapsed since the previous loop. 
   * This is the value that we will use in the formulas as "elapsedTime" 
   * in seconds. We work in ms so we haveto divide the value by 1000 
   to obtain seconds*/

  /*Reed the values that the accelerometre gives.
   * We know that the slave adress for this IMU is 0x68 in
   * hexadecimal. For that in the RequestFrom and the 
   * begin functions we have to put this value.*/
   
     Wire.beginTransmission(0x68);
     Wire.write(0x3B); //Ask for the 0x3B register- correspond to AcX
     Wire.endTransmission(false);
     Wire.requestFrom(0x68,6,true); 
   
   /*We have asked for the 0x3B register. The IMU will send a brust of register.
    * The amount of register to read is specify in the requestFrom function.
    * In this case we request 6 registers. Each value of acceleration is made out of
    * two 8bits registers, low values and high values. For that we request the 6 of them  
    * and just make then sum of each pair. For that we shift to the left the high values 
    * register (<<) and make an or (|) operation to add the low values.*/
    
     Acc_rawX=Wire.read()<<8|Wire.read(); //each value needs two registres
     Acc_rawY=Wire.read()<<8|Wire.read();
     Acc_rawZ=Wire.read()<<8|Wire.read();

     
    /* Now we can apply the Euler formula. The atan will calculate the arctangent. The
     *  pow(a,b) will elevate the a value to the b power. And finnaly sqrt function
     *  will calculate the rooth square.*/
     /*---X---*/
     Acceleration_angle[0] = atan((Acc_rawY/16384.0)/sqrt(pow((Acc_rawX/16384.0),2) + pow((Acc_rawZ/16384.0),2)))*rad_to_deg;
     /*---Y---*/
     Acceleration_angle[1] = atan(-1*(Acc_rawX/16384.0)/sqrt(pow((Acc_rawY/16384.0),2) + pow((Acc_rawZ/16384.0),2)))*rad_to_deg;
    
   Wire.beginTransmission(0x68);
   Wire.write(0x43); //Gyro data first adress
   Wire.endTransmission(false);
   Wire.requestFrom(0x68,4,true); //Just 4 registers
   
   Gyr_rawX=Wire.read()<<8|Wire.read(); //Once again we shift and sum
   Gyr_rawY=Wire.read()<<8|Wire.read();
 
   /*Now in order to obtain the gyro data in degrees/seconds we have to divide first
   the raw value by 131 because that's the value that the datasheet gives us*/

   /*---X---*/
   Gyro_angle[0] = Gyr_rawX/131.0; 
   /*---Y---*/
   Gyro_angle[1] = Gyr_rawY/131.0;

      /*---X axis angle---*/
   //Total_angle[0] = 0.98 *(Total_angle[0] + Gyro_angle[0]*elapsedTime) + 0.02*Acceleration_angle[0];
   Total_angle[0] = 0.98 *(Total_angle[0] + Gyro_angle[0]*elapsedTime) + 0.02*Acceleration_angle[0]; // responds faster to changes, no shift over time observed...
   /*---Y axis angle---*/
   //Total_angle[1] = 0.98 *(Total_angle[1] + Gyro_angle[1]*elapsedTime) + 0.02*Acceleration_angle[1];
    Total_angle[1] = 0.98 *(Total_angle[1] + Gyro_angle[1]*elapsedTime) + 0.02*Acceleration_angle[1];
   
   /*Now we have our angles in degree and values from -10º0 to 100º aprox*/
    //Serial.println(Total_angle[1]);
    
    //Serial.print("X axis angle : "); Serial.print("\t"); Serial.print("\t"); Serial.print("Y axis angle : ");
    //Serial.println();
    Serial.print(Total_angle[0]);Serial.print("\t"); Serial.print("\t"); Serial.print("\t"); Serial.print(Total_angle[1]);
    Serial.println();

    /* left for historic and debugging reasons
    Serial.print("Acc_rawX: "); Serial.print("\t"); Serial.print("Acc_rawY: ");Serial.print("\t"); Serial.println("Acc_rawZ: ");
    Serial.print(Acc_rawX); Serial.print("\t"); Serial.print("\t"); Serial.print(Acc_rawY);Serial.print("\t"); Serial.print("\t"); Serial.println(Acc_rawZ);
    Serial.print("Gyr_rawX: "); Serial.print("\t"); Serial.println("Gyr_rawY: ");
    Serial.print(Gyr_rawX); Serial.print("\t"); Serial.print("\t"); Serial.println(Gyr_rawY);
    Serial.println("------------------------------------------------------------------------------");    
*/

  //Serial.print("iteration: ");
  //Serial.println(i);

  //method to only average the last set of values
  if ( i > settleIterations - numReadings)
  {
  
  // read angle:
  readings[readIndex] = Total_angle[0];
  // add the reading to the total:
  total = total + readings[readIndex];
  //Serial.print("total:");
  //Serial.println(total);
  // advance to the next position in the array:
  readIndex = readIndex + 1;

  // if we're at the end of the array...
  if (readIndex >= numReadings) {
    // ...wrap around to the beginning:
    readIndex = 0;
  }

  // calculate the average:
  average = total / numReadings;
  // send it to the computer as ASCII digits
  
  delay(1);        // delay in between reads for stability
  }

  //keep the delay (loop time) low to minimize the discrete error
  delay(delay_time); // around 50 ms loop time
  }
  Serial.print("Average: ");
  average = 90 - average;
  Serial.println(average);
  SG = 0.000001*average*average*average+(-0.000131373)*average*average+0.006967952*average+0.901451941;
  //SG = (SG,3);
  Serial.print("SG: ");
  Serial.println(SG);
  timer.setInterval(3000L, write2blynk);  //call the function that writes the values
}



BLYNK_WRITE(V3)  //function used to determine, if while in deep sleep, if the user has requested that deep sleep be cancelled after the device wakes up
{
  averageAngle = param.asFloat();
}
//BLYNK_WRITE(V4)  //function used to determine, if while in deep sleep, if the user has requested that deep sleep be cancelled after the device wakes up
//{
//  userSG = param.asFloat();
//}


BLYNK_WRITE(V5)  //Blynk button that starts the averaging function
//Also in turn starts the write2blynk function
{
  int pinValue = param.asInt();
  if (pinValue = 1);
  {
    Blynk.virtualWrite(V3,0);
    Blynk.virtualWrite(V2,0);
    Serial.println("Starting averaging of angle");
    averaging_angle();
    //int timer_length = settleIterations * delay_time + 1000;
    
    Blynk.virtualWrite(V3, average);
    Blynk.virtualWrite(V2, SG);
  }
}

void getTempData()
{
  Serial.println("Gathering Temp");


    byte i;
    byte present = 0;
    byte type_s;
    byte data[12];
    byte addr[8];

 
    if ( !ds.search(addr)) 
    {
      ds.reset_search();
      delay(250);
      return;
    }
 
 
    if (OneWire::crc8(addr, 7) != addr[7]) 
    {
      Serial.println("CRC is not valid!");
      return;
    }
    Serial.println();
 
    // the first ROM byte indicates which chip
    switch (addr[0]) 
    {
      case 0x10:
        type_s = 1;
        break;
      case 0x28:
        type_s = 0;
        break;
      case 0x22:
        type_s = 0;
        break;
      default:
      Serial.println("Device is not a DS18x20 family device.");
      return;
    } 
 
    ds.reset();
    ds.select(addr);
    ds.write(0x44, 1);        // start conversion, with parasite power on at the end  
    delay(1000);
    present = ds.reset();
    ds.select(addr);    
    ds.write(0xBE);         // Read Scratchpad
 
    for ( i = 0; i < 9; i++) 
    {           
      data[i] = ds.read();
    }
 
    // Convert the data to actual temperature
    int16_t raw = (data[1] << 8) | data[0];
    if (type_s) {
      raw = raw << 3; // 9 bit resolution default
      if (data[7] == 0x10) 
      {
        raw = (raw & 0xFFF0) + 12 - data[6];
      }
    } 
    else 
    {
      byte cfg = (data[4] & 0x60);
      if (cfg == 0x00) raw = raw & ~7;  // 9 bit resolution, 93.75 ms
      else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms
      else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms
 
    }
    celsius = (float)raw / 16.0;
    fahrenheit = celsius * 1.8 + 32.0;
    fahrenheit = fahrenheit - 2;  //Calibration
    Serial.print("  Temperature = ");
    Serial.print(celsius);
    Serial.print(" Celsius, ");
    Serial.print(fahrenheit);
    Serial.println(" Fahrenheit");

    Blynk.virtualWrite(V7, fahrenheit);
}

void getVolts()
{
    Serial.println("Determining battery voltage");
    raw = analogRead(A0);
    volt = raw/1023.0;
    volt = volt * 5.5;
    Blynk.virtualWrite(V8, volt);

    if (volt < 2.8)
    {
      Blynk.email("************************@gmail.com", volt, "Charge Aqua Spindle");
      Serial.println("Email sent");
    }
    if (volt < 2.5)
    {
      ESP.deepSleep(48*60*60*1000*1000); //Sleep for 48 hour if battery is dangerously low
    }
}

BLYNK_WRITE(V6)  //Blynk button that will pull temp and voltage data
{
  int pinValue2 = param.asInt();
  if (pinValue2 = 1)
  {
    getTempData();
    
    getVolts();
    

  }
}

BLYNK_WRITE(V11)  //function used to determine, if while in deep sleep, if the user has requested that deep sleep be cancelled after the device wakes up
{
  pinValue3 = param.asInt();
}

void AwakenFromSleep()
{
  clockDisplay();
  Serial.print("Hour: ");
  Serial.println(hour());
    if (hour() == 1)
    {
      getVolts();
      getTempData();
      averaging_angle();
      Blynk.virtualWrite(V3, average);
      Blynk.virtualWrite(V2, SG);
      String SGstring = "";
      SGstring.concat(SG);
      String voltstring = "";
      voltstring.concat(volt);
      String tempstring = "";
      tempstring.concat(fahrenheit);      
      String emailData = String("SG: " + SGstring + ", Temp: " + tempstring + ", Voltage: " + voltstring);
      Blynk.email("***********************@gmail.com", emailData, "Aqua Spindle Daily Update");
    }
    else
    {
      deepSleepNow();
    }
  }


void deepSleepNow()
{
  Serial.print("Deep sleep pin value: ");
  Serial.println(pinValue3);
  if (pinValue3 == 0)
  {
    //if (hour()>=0 && hour()<=1)
    //{
      Serial.println("Deep sleep mode");

      //50*60*1000*1000 = 50 miutes of sleep
      //12*60*60*1000*1000 = 12 hours of sleep
      //deepSleepHours*60*60*1000*1000 = *deepSleepHours* hours of sleep
      ESP.deepSleep(60*1000*1000); //1000x1000 = 1 second
      //ESP.deepSleep(deepSleepHours*60*60*1000*1000);
      delay(100);
    //}
  }
  else
  {
    Serial.println("Deep sleep mode is disabled by user");
  }
}

BLYNK_CONNECTED()
{
  rtc.begin();
  Blynk.syncVirtual(V11);
}

void write2blynk()
{
  Blynk.virtualWrite(V3, average);
  Blynk.virtualWrite(V5,0);
  //average = 0
}

bool standalone_mode = true;

void Connect_to_WiFi()
{
 
  
  Serial.println(F("Connecting to WiFi..."));
  if (WiFi.status() != WL_CONNECTED)
  {
      WiFi.begin(ssid, pass); // connect to the network
  }

  while (WiFi.status() != WL_CONNECTED  && wifi_attempt_count < max_wifi_connect_attempts) // Loop until we've connected, or reached the maximum number of attemps allowed
  {
    delay(wait_between_wifi_attempts_millis);
    wifi_attempt_count++;   
    Serial.print(F("WiFi connection - attempt # "));
    Serial.print(wifi_attempt_count);
    Serial.print(F(" of "));
    Serial.println(max_wifi_connect_attempts);       
  }

  // we get to this point when either we're connected to Wi-Fi, or we've tried too many times. We need to do differnet things, depending which it is...
 
  if (WiFi.status() == WL_CONNECTED)
  {
    //WiFi.mode(WIFI_STA);
    Serial.println(F("WiFi CONNECTED"));
    Serial.println();
  }
  else
  {  
    // we get here if we tried multiple times, but can't connect to WiFi. We need to go into stand-alone mode and wait a while before re-trying...
    standalone_mode = true;                     // We can't be in connected mode if no wifi
    Serial.println();
    Serial.println(F("................ In Stand-alone mode ................"));
    timer.setInterval(1000*60*60,delayedWIFIconnect);
  }
}

void delayedWIFIconnect()
{
  if (standalone_mode = true)
  {
    wifi_attempt_count=0;
    Connect_to_WiFi();
  }
}

void setup() 
{

  //delay(5000); // Wait until start. Last chance to upload new sketch!!!
  Wire.begin(0,2); //begin the wire comunication
  Wire.beginTransmission(0x68); // 0x68 is the i2c address of MPU6050
  Wire.write(0x6B);
  Wire.write(0);
  Wire.endTransmission(true);
  Serial.begin(115200); //

  time_ = millis(); //Start counting time in milliseconds

  Serial.println("IMU check starting...");

    for (int thisReading = 0; thisReading < numReadings; thisReading++)
  {
    readings[thisReading] = 0;
  }
  //rtc.begin;
  Blynk.begin(auth, ssid, pass);
  AwakenFromSleep();
  //timer.setInterval(60000L, clockDisplay);
  //60*10*1000 = 600000 = 10 minutes of awake time
  //timer.setInterval(50000L, getVolts);
  timer.setInterval(10000L, deepSleepNow);  //time interval between checking if sleep should stop from app, doesn't account for additive sleep time
  pinMode (A0, INPUT);
  //averaging_angle();
  
  Serial.println("Ready");
  
  //Blynk.virtualWrite(V4, 0.000);
  
}//end of setup void

void loop() 
{
  timer.run();
  if (WiFi.status() != WL_CONNECTED)
  {
    Connect_to_WiFi();
    
  }
  if (WiFi.status() == WL_CONNECTED)
  {
    if (!Blynk.connected())
    {
      Blynk.connect();
    }
  }
  if (Blynk.connected()) 
  {
    Blynk.run();
  }
   
}//end of loop void

The output you mentioned is the device going to deep sleep, which I then use a Blynk command to later tell the device on the next wake up if I want it to come out of deep sleep mode until the Blynk command is turned back off. This way, I can save battery most of the time, but if I need to get information repeated to check my saltwater salinity level, I can keep the device out of deep sleep for a period of time.

You’re putting your device into deep sleep every minute, and that will obviously turn off the WiFi and put the device into a mode where only the internal timer is running, allowing it to know when to reboot itself at the end of the sleep period.

Pete.

Hey Pete,

I see now that it was working as expected, just user error on my end, since I didn’t have pinValue3 set to 1 in the app. I’ll make this change and see how often it disconnects now. I’m able to see in the app the last time the device connects (for my other two projects, not using deepsleep) and it is always within a few hours. So, I’m assuming that means it disconnected and reconnected a few hours before I checked the app. I’d obviously like to find a way to have a consistently stable connection.

If you want assistance with that then you’ll need to accurately describe the problem, post the correct code, describe your hardware in accurate detail and post the relevant serial monitor output that shows the disconnections.

TBH, you’d be better doing this in a new topic, as this one is now so messy and disjointed that it’s becoming impossible to follow.

However, before you do that, I’d suggest that you try a very simple sketch on your problematic hardware, and see if you still suffer frequent disconnections. If that is okay then start to add-in pieces of your existing sketch until you once again start to experience problems.

Pete.