Connect and disconnect - timer problem?

Hi all,

Having fairly major problems with staying connected to my local blynk server, my project is using a GSM connection. I was having no trouble at all when I had only 1-2 sensors and read/write virtual pins enabled but now ive added a third sensor and relavent code (with the ambition to add a forth in the near future) I’m getting it successfully connecting to my local server and a second later it disconnects. It goes on like this for a minute then hangs.

One thing I’ve noticed is even with 1-2 sensors running, if I was to tap a button or move a slider on the app too close to another command it would also cause a disconnect to the server.

My guess is it is something to do with my timers. I’m not sure how I can improve this any more? I have it running sections of code for a second with interupts between the timers to stagger them. Can anyone solve my connection problem?

Code below:

    // Hardware definitions
    #define BLYNK_PRINT Serial
#define TINY_GSM_MODEM_SIM800
/********************************************************************/
// First we include the libraries
#include <TinyGsmClient.h>
#include <BlynkSimpleSIM800.h>
#include <DallasTemperature.h>
#include <OneWire.h>
#include <INA226.h>
/********************************************************************/
// Hardware input to board 
#define ONE_WIRE_BUS 4  // Temperature sensor on digital pin 4
#define TURB_READ A0    // Turbidity sensor on analog pin 0
#define PH_READ A1      // pH sensor on analog pin 1
/********************************************************************/
// Setup a oneWire instance to communicate with any OneWire devices  
// (not just Maxim/Dallas temperature ICs) 
OneWire oneWire(ONE_WIRE_BUS);
/********************************************************************/
// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);
/********************************************************************/ 

int sendTimer1, sendTimer2, sendTimer3, sendTimer4, sendTimer5;

// Alert messages
char alertTemp_MessageLow[] = "Temperature is LOW!";
char alertTemp_MessageHigh[] = "Temperature is HIGH!";
char alertTurb_MessageHigh[] = "Turbidity is HIGH!";
char alertTurb_MessageHighHigh[] = "Turbidity is HIGH HIGH!";
char alertpH_MessageLow[] = "pH is LOW!";
char alertpH_MessageHigh[] = "pH is HIGH!";

float alertTempLow;                // Temperature at/below which alerts will be sent
float alertTempHigh;                 // Temperature above which alerts will be sent
float alertTurbHigh;               // Turbidity at/above which alerts will be sent
float alertTurbHighHigh;           // Turbidity above which alerts will be sent
float alertpHLow;                // Temperature at/below which alerts will be sent
float alertpHHigh;                 // Temperature above which alerts will be sent

boolean lowAlertOn_Temp = false;      // flag to show that low alert message has been sent via Blynk 
boolean highAlertOn_Temp = false;     // flag to show that highalert message has been sent via Blynk
boolean highAlertOn_Turb = false;     // flag to show that low alert message has been sent via Blynk 
boolean highhighAlertOn_Turb = false; // flag to show that highalert message has been sent via Blynk
boolean lowAlertOn_pH = false;     // flag to show that low alert message has been sent via Blynk 
boolean highAlertOn_pH = false; // flag to show that highalert message has been sent via Blynk

// Minimum and maximum temperatures are set to out of range values that will be
// overridden the first time the actual values are read.

float minTemp = 10000.0;
float maxTemp = -10000.0;
float minTurb = 10000.0;
float maxTurb = -10000.0;
float minpH = 10000.0;
float maxpH = -10000.0;

float currentTemp;                                // Current temperature reading
float currentTurb;                                // Current turbidity reading
float currentpH;                                  // Current pH reading

// pH Buffer and Calibration factors
float calibrationpH = 21.40;
int sensorValue = 0; 
unsigned long int avgValue; 
float b;
int buf[10],temp;

#define ALERT_HYSTERESIS 1                        // Hysteresis for alerts
// Widget colors for alerts
#define ALERT_COLOR_OK   "#23C48E"                // Green
#define ALERT_COLOR_LOW  "#5F7CD8"                // Dark Blue
#define ALERT_COLOR_HIGH "#D3435C"                // Red

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

BlynkTimer timer;

/********************************************************************/
//GPRS credentials
char apn[]  = "internet"; // General apn being used for GPRS to connect to public internet
char user[] = "";
char pass[] = "";
char auth[] = ""; // Local server project authorisation code
char server[] = "xxx.onmypc.net"; // DDNS server pointed to home WAN IP
int port = 8080; // Port being forwarded via home router to Raspberry Pi

#include <SoftwareSerial.h>
SoftwareSerial SerialAT(2, 3); // RX, TX

TinyGsm modem(SerialAT);



void setup()
{
  // Debug console
  Serial.begin(19200); // Start debugging if needed
  
  sensors.begin(); // Calls for Temperature sensor to start from library
   // Set GSM module baud rate
  SerialAT.begin(19200);
  delay(3000);
  modem.restart();
  Blynk.begin(auth, modem, apn, user, pass, server, port); // Local server credentials and server connection details called
  // Setup the functions every second
  timer.setTimeout(200, []() {
sendTimer1 = timer.setInterval(1000, TempSensorRead);
});

timer.setTimeout(400, []() {
sendTimer2 = timer.setInterval(1000, TurbiditySensorRead);
});

timer.setTimeout(600, []() {
sendTimer3 = timer.setInterval(1000, pHSensorRead);
});

//timer.setTimeout(800, []() {
//sendTimer4 = timer.setInterval(1000, ChlorineSensorRead);
//});
/********************************************************************/
// Temperature sensor begin
/********************************************************************/
void TempSensorRead(){
  sensors.requestTemperatures();
  currentTemp = sensors.getTempCByIndex(0);
  Blynk.virtualWrite(V0, currentTemp);

// Low temperature alerts
if ((currentTemp <= alertTempLow) && !lowAlertOn_Temp) {
  Blynk.setProperty(V0, "color", ALERT_COLOR_LOW);
  Blynk.notify(alertTemp_MessageLow);
  lowAlertOn_Temp = true;
}
else if (lowAlertOn_Temp && (currentTemp > alertTempLow + ALERT_HYSTERESIS)) {
  Blynk.setProperty(V0, "color", ALERT_COLOR_OK);
  lowAlertOn_Temp = false;
}
// High temperature alerts
if ((currentTemp >= alertTempHigh) && !highAlertOn_Temp) {
  Blynk.setProperty(V0, "color", ALERT_COLOR_HIGH);
  Blynk.notify(alertTemp_MessageHigh);
  highAlertOn_Temp = true;
}
else if (highAlertOn_Temp && (currentTemp < alertTempHigh - ALERT_HYSTERESIS)) {
  Blynk.setProperty(V0, "color", ALERT_COLOR_OK);
  highAlertOn_Temp = false;
}

// Minimum and maximum temperatures
if (currentTemp < minTemp) {
  minTemp = currentTemp;
  Blynk.virtualWrite(V5, currentTemp);
}
if (currentTemp > maxTemp) {
  maxTemp = currentTemp;
  Blynk.virtualWrite(V6, currentTemp);
}

}

// Set low alert temperature
BLYNK_WRITE(V1) {
  alertTempLow = param.asFloat();
  Blynk.virtualWrite(V2, alertTempLow);
}

// Set high alert temperature
BLYNK_WRITE(V3) {
  alertTempHigh = param.asFloat();
  Blynk.virtualWrite(V4, alertTempHigh);
}

// Reset minimum and maximum temperatures
BLYNK_WRITE(V7) {
minTemp = maxTemp = currentTemp;
Blynk.virtualWrite(V5, currentTemp);
Blynk.virtualWrite(V6, currentTemp);
}
/********************************************************************/
// Temperature sensor end
/********************************************************************/
/********************************************************************/
// Turbidity sensor begin
/********************************************************************/
float fmapTurb(float x, float in_min, float in_max, float out_min, float out_max) // Scaling routine
{
 return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}

void TurbiditySensorRead(){
  //int RawTurbValue = analogRead(TURB_READ); // This line and the following allow for raw sensor data gathering for calibration   
  //Blynk.virtualWrite(V8, RawTurbValue);
  int RawTurbValue = analogRead(TURB_READ); // Analog data is read from A0
  float currentTurb = fmapTurb(RawTurbValue, 0, 685, 5.0, 0.0); // Mapping routine for scaling raw data to engineering units
  Blynk.virtualWrite(V8, currentTurb);

// High turbidity alerts
if ((currentTurb <= alertTurbHigh) && !highAlertOn_Turb) {
  Blynk.setProperty(V8, "color", ALERT_COLOR_HIGH);
  Blynk.notify(alertTurb_MessageHigh);
  highAlertOn_Turb = true;
}
else if (highAlertOn_Turb && (currentTurb > alertTurbHigh + ALERT_HYSTERESIS)) {
  Blynk.setProperty(V8, "color", ALERT_COLOR_OK);
  highAlertOn_Turb = false;
}
// High High turbidity alerts
if ((currentTurb >= alertTurbHighHigh) && !highhighAlertOn_Turb) {
  Blynk.setProperty(V8, "color", ALERT_COLOR_HIGH);
  Blynk.notify(alertTurb_MessageHighHigh);
  highhighAlertOn_Turb = true;
}
else if (highhighAlertOn_Turb && (currentTurb < alertTurbHighHigh - ALERT_HYSTERESIS)) {
  Blynk.setProperty(V8, "color", ALERT_COLOR_OK);
  highhighAlertOn_Turb = false;
}

// Minimum and maximum turbidity
if (currentTurb < minTurb) {
  minTurb = currentTurb;
  Blynk.virtualWrite(V13, currentTurb);
}
if (currentTurb > maxTurb) {
  maxTurb = currentTurb;
  Blynk.virtualWrite(V14, currentTurb);
}

}

// Set low alert turbidity
BLYNK_WRITE(V9) {
  alertTurbHigh = param.asFloat();
  Blynk.virtualWrite(V10, alertTurbHigh);
}

// Set high alert turbidity
BLYNK_WRITE(V11) {
  alertTurbHighHigh = param.asFloat();
  Blynk.virtualWrite(V12, alertTurbHighHigh);
}

// Reset minimum and maximum turbidity
BLYNK_WRITE(V15) {
minTurb = maxTurb = currentTurb;
Blynk.virtualWrite(V13, currentTurb);
Blynk.virtualWrite(V14, currentTurb);
}
/********************************************************************/
// Turbidity sensor end
/********************************************************************/
/********************************************************************/
// pH sensor begin
/********************************************************************/
void pHSensorRead(){
  for(int i=0;i<10;i++) 
 { 
 buf[i]=analogRead(A1);
 delay(30);
 }
 for(int i=0;i<9;i++)
 {
 for(int j=i+1;j<10;j++)
 {
 if(buf[i]>buf[j])
 {
 temp=buf[i];
 buf[i]=buf[j];
 buf[j]=temp;
 }
 }
 }
 avgValue=0;
 for(int i=2;i<8;i++)
 avgValue+=buf[i];
 float pHVol=(float)avgValue*5.0/1024/6;
 float currentpH = -5.70 * pHVol + calibrationpH;
 Blynk.virtualWrite(V16, currentpH);

// Low pH alerts
if ((currentpH <= alertpHLow) && !lowAlertOn_pH) {
  Blynk.setProperty(V16, "color", ALERT_COLOR_LOW);
  Blynk.notify(alertpH_MessageLow);
  lowAlertOn_pH = true;
}
else if (lowAlertOn_pH && (currentpH > alertpHLow + ALERT_HYSTERESIS)) {
  Blynk.setProperty(V16, "color", ALERT_COLOR_OK);
  lowAlertOn_pH = false;
}
// High pH alerts
if ((currentpH >= alertpHHigh) && !highAlertOn_pH) {
  Blynk.setProperty(V16, "color", ALERT_COLOR_HIGH);
  Blynk.notify(alertpH_MessageHigh);
  highAlertOn_pH = true;
}
else if (highAlertOn_pH && (currentpH < alertpHHigh - ALERT_HYSTERESIS)) {
  Blynk.setProperty(V16, "color", ALERT_COLOR_OK);
  highAlertOn_pH = false;
}

// Minimum and maximum pH
if (currentpH < minpH) {
  minpH = currentpH;
  Blynk.virtualWrite(V21, currentpH);
}
if (currentpH > maxpH) {
  maxpH = currentpH;
  Blynk.virtualWrite(V22, currentpH);
}

}

// Set low alert pH
BLYNK_WRITE(V17) {
  alertpHLow = param.asFloat();
  Blynk.virtualWrite(V18, alertpHLow);
}

// Set high alert pH
BLYNK_WRITE(V19) {
  alertpHHigh = param.asFloat();
  Blynk.virtualWrite(V20, alertpHHigh);
}

// Reset minimum and maximum temperatures
BLYNK_WRITE(V23) {
minpH = maxpH = currentpH;
Blynk.virtualWrite(V21, currentpH);
Blynk.virtualWrite(V22, currentpH);
}
/********************************************************************/
// pH sensor end
/********************************************************************/
void loop() {
  Blynk.run();
  timer.run(); // Initiates BlynkTimer
}

All your timers use 1000 ms !
You don’t need to use timer.setTimeout

You have just to stage your timers.

You have three timers that are all set up to run their respective functions at exactly the same time.
You’ve added three short lambda timeout timers before each timer in void setup, and I’m not sure if this is an attempt to ensure that the diners don’t actually coincide. Unfortunately these timeout timers are non-blocking, so don’t achieve that separation.

Pete.

2 Likes

Your sketch should be :

Blynk.begin(auth, modem, apn, user, pass, server, port); // Local server credentials and server connection details called
  // Setup the functions every second
timer.setInterval(1000,TempSensorRead);
timer.setInterval(1200,TurbiditySensorRead);
timer.setInterval(1400, pHSensorRead);
1 Like

Thanks guys. Will give that a go.

1 Like

I still am getting the same problem. :neutral_face: Any further ideas?

I have to ask, why do you feel the need to take Temperature, Turbidity and PH readings every second?

Pete.

1 Like

Its a water sampling project im after live readings. Do you think 5 seconds would do? I really dont want to dampen incoming values thats all.

Do you realise that if you’re planning on using Superchart to record the results then the minimum granularity is 1 minute?

Pete.

2 Likes

No I didn’t realise this. However I could run a seperate 1 minute timed function to call values for my superchart.

If all I was interested in was labels, buttons and sliders could I still use 1 second timers without an issue?

I think the problem is that some of the functions you’re calling every second involve quite a bit of processing, on top of the time it takes to read each of the sensors.

If your intention is to display those readings on labelled value widgets then it’s unlikely that the person viewing the data will really be able to make use of data that refreshed any faster than every 5 seconds.

I think the Superchart live screen will show live data, but data written to the database, which is displayed on the other Superchart screens is averaged over a 1 minute period before being committed to the database.

I think you’d be better-off taking a realistic approach to how frequently you really need readings to be taken then structure your code accordingly.

Pete.

2 Likes