Help! Blynk stuck after wifi resets

This is definitely a start, but adding this WiFi.begin line does reconnect the Wifi as expected (resulting in everything working as expected). Thanks for the advice Pete

void reconnectBlynk()
{
  if (!Blynk.connected())
  {
    Serial.println("Lost connection");
    Blynk.disconnect();
    WiFi.begin(ssid, pass);
    Blynk.connect();
    if (Blynk.connect()) Serial.println("Reconnected");
    else Serial.println("Not reconnected");
  }
  else if (Blynk.connected())
  {
    Serial.println("Connected");
  }
}

That’s not really the approach I was suggesting. I’ve just googled the WiFiNINA library methods and they seem to be the same as those for the ESP8266…

Calling WiFi.begin(ssid, pass); just once won’t normally result in a connection. The normal method is to put the WiFi.begin() command in a while loop, which causes the code to wait until a WiFi connection has been established before the code can exit the while loop. However, this isn’t a good approach if you want to be able to use the device in offline mode, say with a physical switch that can turn a relay on/off regardless of whether the device is connected to WiFi and Blynk.
The code in the link above uses this while loop approach.

This is how I limit the number of WiFi connection attempts (uin this case to 20, as defined by the max_wifi_connect_attempts=20; line of code…

bool standalone_mode = true;

void Connect_to_WiFi()
{
   wifi_attempt_count=0;
   max_wifi_connect_attempts=20;
   wait_between_wifi_attempts_millis=500; 
  
  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 ................"));
  }
}

The other issue with your approach is that you are just checking if you have a connection to Blynk…

If you want to operate in stand-alone mode then you need to be doing a check to see if you are connected to WiFi. If you aren’t then you need to try to re-connect.
If you are connected to WiFi but not to Blynk (the Blynk server is down) then each time Blynk.run is encountered the code will attempt to re-connect to Blynk, which will disrupt your stand-alone operation.

Pete.

1 Like

Hi again Pete,

I’ve been reading more into your solution you’ve provided above and trying to understand how I can incorporate it into my project.

I think with the code you added above, I can get it to work the way you’ve suggested. I may add an additional counter to reset the max_wifi_connect_attempts so the device will try to reconnect at a later date/time.

For standalone_mode, is this all done in the void loop (with a check if bool is true) with calls to the same functions that the blynk.timer calls in the void setup? I’m assuming that the blynk.timer function doesn’t work if there is no connection to blynk? If not, how are you using the bool to keep the needed functions running when wifi can’t be established?

Thanks again.

I don’t really understand the question, but this is all too hypothetical without undemanding more about what you are trying to achieve in your particular case.

Incorrect. BlynkTimer does not require a Blynk connection.

Pete.

OK, I think your answer to the second question answers the first question. So, the issue is that the Blynk.run function is blocking (or somewhat blocking) the standalone to continue. I currently call these functions in the setup loop:

timer.setInterval(1000L, checkLevels);
timer.setInterval(5000L, Mix2FinalSet);
timer.setInterval(5000L, RODI2MixSet);
timer.setInterval(5000L, EmergencyStop);
timer.setInterval(300000L, reconnectBlynk);
timer.setInterval(21600000L, FillFinalBin);

And based on what I understand, these will still run on the timer regardless if Blynk is connected. I just need to make sure that I follow the steps you laid out before.
Check for wifi connection
If no wifi connection then reconnect wifi
If connected to wifi then attempt to connect blynk
If connected to Blynk, then blynk.run

Is that right, I’m questioning this last “if” statement? Assuming it looks like this:
if (Blynk.connected())
{Blynk.run();}

This way I would never connect to blynk if I have lost wifi and I could still run all my timer.setinterval functions.

Thanks.

You could do it like that, or check standalone_mode

You should read the “Staggering Timers” section of this tutorial…

Pete.

I’m having an issue now that I lose the Blynk connection and it is not re-established. I’m not sure how to troubleshoot this one as this seems to be part of the Blynk library outputs in the serial monitor.

This is the serial monitor output I’m getting:

[2337649] Heartbeat timeout
[2339652] Connecting to blynk-cloud.com:80

I then get a repeating ouptut “connecting to blynk-cloud”. Any ideas?

For the sections of code that I’m using to re-establish my connections, etc

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;
  }
}
void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  Connect_to_WiFi();
  Blynk.config(auth);
  Blynk.connect();
  timer.setInterval(1000L, checkLevels);
  timer.setInterval(5000L, Mix2FinalSet);
  timer.setInterval(5000L, RODI2MixSet);
  timer.setInterval(5000L, EmergencyStop);
  timer.setInterval(5000L, FillFinalBin);
  pinMode(MIXswitchHIGH, INPUT_PULLUP);
  pinMode(MIXswitchLOW, INPUT_PULLUP);
  pinMode(FINALswitchHIGH, INPUT_PULLUP);
  pinMode(FINALswitchLOW, INPUT_PULLUP);
  pinMode(RODI2MIXrelay, OUTPUT);
  pinMode(MIX2FINALrelay, OUTPUT);
  pinMode(FINALswitchEM, INPUT_PULLUP);
  pinMode(MIXswitchEM, INPUT_PULLUP);
  
}

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();
  }
  //Blynk.run();

}

I’d say that these two are connected.

Pete.

Meaning I’m doing too many things at the same time interval? All my sketches are doing this with other projects, and the same basic re-connect code. I’ll switch the time intervals to occur at different points and test.

I saw one thread that mentioned using the Serial.print while also attempting to use the #define BLYNK_PRINT Serial could also be an issue. Any thoughts?

Which thread was that?

Pete.

I realize they are discussing the D1 mini and ESP01, but at least similar connection issues.

Not relevant to your situation.

Pete.

Is there a way to determine the cause of a wifi connection being lost? I haven’t put anything into my code currently that will detect when it drops, besides that I know the hour when it connects and can check the serial monitor to determine how many times it will reconnect to my wifi and Blynk.

This issue has been plaguing me for some while, and although I can now establish connection after it’s lost, it seems to be lost every minute. Meaning I’m not getting good functionality with time based operations within the code.

Thanks again.

//#define BLYNK_PRINT Serial
//#define BLYNK_DEBUG
#include <Wire.h>
#include <SPI.h>;
#include <WiFiNINA.h>;
#include <BlynkSimpleWiFiNINA.h>;
#include <OneWire.h>
#include <TimeLib.h>
#include <WidgetRTC.h>
#define MIXswitchHIGH 2
#define MIXswitchLOW 3
#define FINALswitchHIGH 4
#define FINALswitchLOW 5
#define RODI2MIXrelay 6
#define MIX2FINALrelay 7
#define MIXswitchEM 8
#define FINALswitchEM 9

int MixLevelHigh = 0;
int FinalLevelHigh = 0;
int MixLevelLow = 0;
int FinalLevelLow = 0;
int MixEmergency = 0;
int FinalEmergency = 0;
int pinValue1 = 0;
int pinValue2 = 0;
int pinValue3 = 0;
int wifi_attempt_count=0;
int max_wifi_connect_attempts=20;
int wait_between_wifi_attempts_millis=500;

// 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[] = "**************";
char pass[] = "*****************";

//Both used for Blynk
BlynkTimer timer;
WidgetRTC rtc;
WidgetLED led1(V5);
WidgetLED led2(V6);

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

void RODIpumpRUN()
{
  digitalWrite (RODI2MIXrelay,HIGH);
}

void RODIpumpIDLE()
{
  digitalWrite (RODI2MIXrelay,LOW);
}

void MIXpumpRUN()
{
  digitalWrite (MIX2FINALrelay,HIGH);
}

void MIXpumpIDLE()
{
  digitalWrite (MIX2FINALrelay,LOW);
}

void checkLevels()
{
  MixLevelHigh = digitalRead(MIXswitchHIGH);
  MixLevelLow = digitalRead(MIXswitchLOW);
  FinalLevelHigh = digitalRead(FINALswitchHIGH);
  FinalLevelLow = digitalRead(FINALswitchLOW);
  FinalEmergency = digitalRead(FINALswitchEM);
  MixEmergency = digitalRead(MIXswitchEM);
  //Serial.print("Low level mix: ");
  //Serial.println(MixLevelLow);
  //Serial.print("High level mix: ");
  //Serial.println(MixLevelHigh);
  //Serial.print("Emergency level mix: ");
  //Serial.println(MixEmergency);
  //Serial.print("Low level final: ");
  //Serial.println(FinalLevelLow);
  //Serial.print("High level final: ");
  //Serial.println(FinalLevelHigh);
  //Serial.print("Emergency level final: ");
  //Serial.println(FinalEmergency);
  
  if (MixLevelLow == HIGH)
  {
    if (MixLevelHigh == LOW)
    {
      led1.on();
      Blynk.setProperty(V5, "color", "#1af002");
    }
  }
  if (MixLevelLow == LOW)
  {
    led1.on();
    Blynk.setProperty(V5, "color", "#f81605");
  }
  if (MixEmergency == HIGH)
  {
    led1.on();
    Blynk.setProperty(V5, "color", "#f81605");
  }
  
  if (FinalLevelLow == HIGH)
  {
    if (FinalLevelHigh == LOW)
    {
      led2.on();
      Blynk.setProperty(V6, "color", "#1af002");
    }
  }
  if (FinalLevelLow == LOW)
  {
    led2.on();
    Blynk.setProperty(V6, "color", "#f81605");
  }
  if (FinalEmergency == HIGH)
  {
    led2.on();
    Blynk.setProperty(V6, "color", "#f81605");
  }
}

BLYNK_WRITE(V1)
{
  pinValue1 = param.asInt();
  Serial.println("Fill Mix Bin");
}



void RODI2MixSet()
{
  //Serial.print("High level switch: ");
  //Serial.println(MixLevelHigh);
  //Serial.println(pinValue1);
    if (MixLevelHigh == HIGH)
    {
      RODIpumpIDLE();
      //pinValue1 = 0;
      Blynk.virtualWrite(V1,0);
      pinValue1 = 0;
      Serial.println("Mix bin is already full, cannot proceed.");
      //Blynk.virtualWrite(V4, "Mix bin full");
    }
    if (MixLevelHigh == LOW & pinValue1 == 1)
    {
      RODIpumpRUN();
      Serial.println("Filling mix bin with RODI water");
      Blynk.virtualWrite(V4, "Filling mix bin");
    }
    if (MixLevelHigh == LOW & pinValue1 == 0)
    {
      RODIpumpIDLE();
      Serial.println("RODI to mix pump idle");
    }
}

BLYNK_WRITE(V2)
{
  pinValue2 = param.asInt();
  Serial.println("Fill Final Bin");
}

void Mix2FinalSet()
{
    
    if (MixLevelLow == LOW)
    {
      MIXpumpIDLE();
      Blynk.virtualWrite(V2,0);
      pinValue2 = 0;
      Serial.println("Mix bin is too low to proceed.");
      Blynk.virtualWrite(V4,"Mix Bin Low");
      Blynk.email("********************@gmail.com", "Mix Bin Low");
    }
    if (FinalLevelHigh == HIGH)
    {
      MIXpumpIDLE();
      Blynk.virtualWrite(V2,0);
      pinValue2 = 0;
      Serial.println("Final bin is already full, cannot proceed.");
      //Blynk.virtualWrite(V4, "Final bin full");
    }  
    if (FinalLevelHigh == LOW & pinValue2 == 1)
    {
      MIXpumpRUN();
      Serial.println("Filling final bin with saltwater");
      Blynk.virtualWrite(V4, "Filling final bin");
    }
    if (FinalLevelHigh == LOW & pinValue2 == 0)
    {
      MIXpumpIDLE();
      Serial.println("Mix to final pump idle");
    }
   
}

void FillFinalBin()
{
    
    if (FinalLevelLow == LOW)
    {
      Serial.println("Final bin is too low.");
      Blynk.virtualWrite(V4,"Final Bin Low");
      Blynk.email("******************@gmail.com", "Final Bin Low");
    }
}

BLYNK_WRITE(V3)
{
  pinValue3 = param.asInt();
  Serial.println("Emergency Shut off");
  Blynk.virtualWrite(V4, "Emergency STOP");
}

void EmergencyStop()
{
    if (pinValue3 == 1)
    {
      MIXpumpIDLE();
      RODIpumpIDLE();
      Blynk.virtualWrite(V1,0);
      pinValue1 = 0;
      Blynk.virtualWrite(V2,0);
      pinValue2 = 0;
      Serial.println("All pumps stopped");
    }
    if (FinalEmergency == HIGH)
    {
      //MIXpumpIDLE();
      RODIpumpIDLE();
      //Blynk.virtualWrite(V1,0);
      //pinValue1 = 0;
      Blynk.virtualWrite(V2,0);
      pinValue2 = 0;
      Serial.println("Final bin emergency high level stop");
    }
    if (MixEmergency == HIGH)
    {
      MIXpumpIDLE();
      //RODIpumpIDLE();
      Blynk.virtualWrite(V1,0);
      pinValue1 = 0;
      //Blynk.virtualWrite(V2,0);
      //pinValue2 = 0;
      Serial.println("Mix bin emergency high level stop");
    }
    if (pinValue3 == 0)
    {
      Blynk.virtualWrite(V4,"Status normal");
    }
}

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 reconnectBlynk()
//{
//  if (!Blynk.connected())
//  {
//    Serial.println("Lost connection");
//    Blynk.disconnect();
//    WiFi.begin(ssid, pass);
//    Blynk.connect();
//    if (Blynk.connect()) Serial.println("Reconnected");
//    else Serial.println("Not reconnected");
//  }
//  else if (Blynk.connected())
//  {
//    Serial.println("Connected");
//  }
//}


void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  Connect_to_WiFi();
  Blynk.config(auth);
  Blynk.connect();
  timer.setInterval(1000L, checkLevels);
  timer.setInterval(5000L, Mix2FinalSet);
  timer.setInterval(6000L, RODI2MixSet);
  timer.setInterval(7000L, EmergencyStop);
  //timer.setInterval(300000L, reconnectBlynk);
  timer.setInterval(8000L, FillFinalBin);
  pinMode(MIXswitchHIGH, INPUT_PULLUP);
  pinMode(MIXswitchLOW, INPUT_PULLUP);
  pinMode(FINALswitchHIGH, INPUT_PULLUP);
  pinMode(FINALswitchLOW, INPUT_PULLUP);
  pinMode(RODI2MIXrelay, OUTPUT);
  pinMode(MIX2FINALrelay, OUTPUT);
  pinMode(FINALswitchEM, INPUT_PULLUP);
  pinMode(MIXswitchEM, INPUT_PULLUP);
  
}

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();
  }
  //Blynk.run();

}
[5312] Connecting to blynk-cloud.com:80
[5470] Ready (ping: 74ms).
[5669] Time sync: OK
Hour: 14
Deep sleep pin value: 0
Deep sleep mode
[75] Connecting to *************
[7307] Connected to WiFi
[7307] IP: 192.168.4.143
[7307]

[5311] Connecting to blynk-cloud.com:80
[5479] Ready (ping: 68ms).
[5698] Time sync: OK
Hour: 14
Deep sleep pin value: 0
Deep sleep mode
[75] Connecting to **************
[5306] Connected to WiFi
[5307] IP: 192.168.4.143
[5307] 

I’m assuming the number in the brackets have some meaning, and could potentially tell me how many times I’m losing connection. These two outputs are not back-to-back, just two separate instances I copied.

Where are these messages coming from?

Pete.

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.