Blynk going offline w/ Timers and not sure why

Hello all, I am not able to figure out connection issues w/ Blynk. My physical application is a flow monitor for my kegerator. I have 1 sensor hooked into a beer line and as I pour I am attempting to count the amount of beer drank and subtract it from the original keg qunatity I set through Blynk (i.e. fill keg, set Blynk gauge at 5 gallons, then drink 5 gallons and track as I drink, repeat…) Below is my code with an exerpt of the serial print I am getting. It seems from an arduino standpoint the calculation makes sense but my Blynk is not updating/responding and keeps going offline.

Below is my serial monitor results from testing the keg1 sensor & associated functions.

        pulse counting
        entered Calc
        1
        1
        3

//after a pause
4
0

This is telling me that the system is counting one pulse, so totalGallons drank is set to 1, so then kegquantity is 3 (THE KEG QUNATITY WAS SET AS 4 gallons to start). So the arduino calculation is working. But then after the pause the kegquantity is reading out as 4 gallons and pulecount 0 (resting state for flow sensor).

So something must not be working w/ my Blynk.virtualWrite that right after calculation it is not updating the kegQuantity and it is syncing back w/ the original kegQuantity since the pin is not being updated. It must be associated w/ my Blynk app going offline every couple seconds. Any thoughts on why this is happening? Thought it was having to many timers in the loop w/ Blynk but when I commented out all but one timer still was getting offline app constantly. Thanks for any help!

FULL CODE (for testing purposes I set the gallon calculation for keg1 to 1pulse=1gallon on pulses counted from the flow sensor so I only need to pour a little beer to make the gauge move, but as you can see in keg2,keg3 functions it takes 3800 pulses in reality to move the gauge a gallon decreased as per manufacturer recommendation). Also, I need to keep the sync function on as I often turn off the arduino board when I am not drinking beer for a couple days, so I want to be able to retrieve the latest keg levels when I turn it back on.

 //All pin settings
#define tempHum_pin D2 //Humidity & top temp location
const int fans = D3;
byte sensorInterrupt1 = D5;
byte sensorPin1       = D5;
byte sensorInterrupt2 = D6;
byte sensorPin2       = D6;
byte sensorInterrupt3 = D7;
byte sensorPin3       = D7;

////Sensors Initialization
#include "DHT.h"
#define DHTTYPE DHT11   // DHT 11
DHT dht(tempHum_pin, DHTTYPE);
//#include <PlainTMP0x.h>
//PlainTMP0x TMP;
const uint32_t _interval = 2000;
int32_t _now, _lastTime;

//////////////////////BLYNK CODE
//#define BLYNK_PRINT Serial 
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
bool isFirstConnect = true;
WidgetTerminal terminal(V13);
#include <SimpleTimer.h>
SimpleTimer timerHum;
SimpleTimer timerKeg1;
SimpleTimer timerKeg2;
SimpleTimer timerKeg3;
const char* ssid = "____";
const char* password = "____";
char auth[] = "___";

//float bottomTemp;
float topTemp;
float humidity;
int emailTime;
int keg1Quantity;
int keg2Quantity;
int keg3Quantity;
volatile byte pulseCount1;
unsigned long totalGallons1;
volatile byte pulseCount2;
unsigned long totalGallons2;
volatile byte pulseCount3;
unsigned long totalGallons3;
int resetKegGal;
// This function will run every time Blynk connection is established
BLYNK_CONNECTED() {
  //if (isFirstConnect) {
//Blynk.syncAll();
terminal.println("synced");
Serial.println(keg1Quantity);
Blynk.syncVirtual(V0);
Blynk.syncVirtual(V1);
Blynk.syncVirtual(V2);
//isFirstConnect = false;  
  //}
}

//Reset Keg Volume
BLYNK_WRITE(V15) {
  switch (param.asInt())
  {
case 1: // Item 1
  keg1Quantity = 5;
  Blynk.virtualWrite(V0, keg1Quantity);
  break;
case 2: // Item 2
  keg2Quantity = 5;
  Blynk.virtualWrite(V1, keg2Quantity); 
  break;
case 3: // Item 3
  keg3Quantity = 5;
  Blynk.virtualWrite(V2, keg3Quantity);
  break;
case 4: // Item 1
  keg1Quantity = 2.5;
  Blynk.virtualWrite(V0, keg1Quantity);
  break;
case 5: // Item 2
  keg2Quantity = 2.5;
  Blynk.virtualWrite(V1, keg2Quantity); 
  break;
case 6: // Item 3
  keg3Quantity = 2.5;
  Blynk.virtualWrite(V2, keg3Quantity);
  break;
case 7: // Item 1
  keg1Quantity = 1;
  Blynk.virtualWrite(V0, keg1Quantity);
  break;
case 8: // Item 2
  keg2Quantity = 1;
  Blynk.virtualWrite(V1, keg2Quantity); 
  break;
case 9: // Item 3
  keg3Quantity = 1;
  Blynk.virtualWrite(V2, keg3Quantity);
  break;
case 10: // Item 1
  keg1Quantity = 2;
  Blynk.virtualWrite(V0, keg1Quantity);
  break;
case 11: // Item 2
  keg2Quantity = 2;
  Blynk.virtualWrite(V1, keg2Quantity); 
  break;
case 12: // Item 3
  keg3Quantity = 2;
  Blynk.virtualWrite(V2, keg3Quantity);
  break;
case 13: // Item 1
  keg1Quantity = 3;
  Blynk.virtualWrite(V0, keg1Quantity);
  break;
case 14: // Item 2
  keg2Quantity = 3;
  Blynk.virtualWrite(V1, keg2Quantity); 
  break;
case 15: // Item 3
  keg3Quantity = 3;
  Blynk.virtualWrite(V2, keg3Quantity);
  break;
case 16: // Item 1
  keg1Quantity = 4;
  Blynk.virtualWrite(V0, keg1Quantity);
  break;
case 17: // Item 2
  keg2Quantity = 4;
  Blynk.virtualWrite(V1, keg2Quantity); 
  break;
case 18: // Item 3
  keg3Quantity = 4;
  Blynk.virtualWrite(V2, keg3Quantity);
  break;
  }
}


// Get Keg Quantity Values From Server
BLYNK_WRITE(V0)
{
  keg1Quantity = param.asInt();
}

BLYNK_WRITE(V1)
{
  keg2Quantity = param.asInt();
}

BLYNK_WRITE(V2)
{
  keg3Quantity = param.asInt();
}


void tempHum(){
  Serial.println(keg1Quantity);
  Serial.println(pulseCount1);
  humidity = dht.readHumidity();
  topTemp = dht.readTemperature(true);
  Blynk.virtualWrite(V11,topTemp);
  Blynk.virtualWrite(V4,humidity);
  
  //do {
//_now = millis();
  //} while ((_now - _lastTime) < _interval);
  //_lastTime = _now;
  //* run measurement */
  //bottomTemp = TMP.Temperature();
  //Blynk.virtualWrite(V3,bottomTemp);
 //if ((abs(bottomTemp - topTemp))> 4) { //controlling keezer fans
  //digitalWrite(fans,HIGH);
  //}
  //else {
  //digitalWrite(fans,LOW);
  //}
 
 if (humidity>90 && ((millis()-emailTime)>86400000)) {
  Blynk.email("phillipmurphy47@gmail.com", "Keezer Issue", "There is high humidity in the keezer, dry out condensation trap");
  emailTime = millis();
  }
}


void keg1(){
terminal.println("timer called");
if (pulseCount1 >0){ 
Serial.println("entered Calc");
terminal.println("Entered calculation");
detachInterrupt(sensorInterrupt1);
totalGallons1=(pulseCount1);
terminal.println(totalGallons1);
terminal.println(pulseCount1);
Serial.println(totalGallons1);
Serial.println(pulseCount1);
keg1Quantity = keg1Quantity - totalGallons1;
Serial.println(keg1Quantity);
Blynk.virtualWrite(V0,keg1Quantity);
pulseCount1 = 0;
attachInterrupt(sensorInterrupt1, pulseCounter1, FALLING);
}
 }

void pulseCounter1(){
  Serial.println("pulse counting");
  pulseCount1++;
}

void keg2(){
if (pulseCount2 >0) {
detachInterrupt(sensorInterrupt2);
totalGallons2 = (pulseCount2/3800);
keg2Quantity = keg2Quantity - totalGallons2;
Blynk.virtualWrite(V1,keg2Quantity);
pulseCount2 = 0;
attachInterrupt(sensorInterrupt2, pulseCounter2, FALLING);
}
  }

void pulseCounter2(){
  pulseCount2++;
}

void keg3(){
if (pulseCount3 > 0){
detachInterrupt(sensorInterrupt3);
totalGallons3 = (pulseCount3/3800);
keg3Quantity = keg3Quantity - totalGallons3;
Blynk.virtualWrite(V2,keg3Quantity);
pulseCount3 = 0;
attachInterrupt(sensorInterrupt3, pulseCounter3, FALLING);
}
  }

void pulseCounter3(){
  pulseCount3++;
}



void setup() 
{
  Serial.begin(115200);
  Blynk.begin(auth,ssid,password);
  timerHum.setInterval(3000, tempHum);
  timerKeg1.setInterval(5, keg1);
  timerKeg2.setInterval(5, keg2);
  timerKeg3.setInterval(5, keg3);
  //TMP.InitializeTMP(TMP_MOD_TMP04,&PORTD, PIND1 , TMP_UNI_FAHRENHEIT, 8);
  _lastTime = millis();
  dht.begin();
  pinMode(sensorPin1, INPUT);
  digitalWrite(sensorPin1, HIGH);
  attachInterrupt(sensorInterrupt1, pulseCounter1, FALLING);
  pinMode(sensorPin2, INPUT);
  digitalWrite(sensorPin2, HIGH);
  attachInterrupt(sensorInterrupt2, pulseCounter2, FALLING);
  pinMode(sensorPin3, INPUT);
  digitalWrite(sensorPin3, HIGH);
  attachInterrupt(sensorInterrupt3, pulseCounter3, FALLING);

}

void loop() 
{
  Blynk.run();
  timerHum.run();
  timerKeg1.run();
  timerKeg2.run();
  timerKeg3.run();
  
}

Hello. Please turn ON debug and post here output.

Having 4 instances of SimpleTimer which covers 40 timers is bad form. You only need 1 instance as each instance covers 10 timers.

3 of your timers are called at 5ms intervals so 60% of the time is spent checking timers with very little time to do anything else like Blynk stuff. Do they need to be at 5ms intervals? In laymans terms what are each of the 5ms timers doing?

ESP’s are quite fussy when it comes to attachInterrupt but I did see at least one dettachInterrupt so you might be ok but it’s probably something for you to check i.e. when the interrupt is called all you can really do is set a flag and then check for the flag outside the interrupt routine.

Are you missing terminal.flush()?

I updated the Simple timer to just one instance, set the interval at 5000 (5 seconds), I may even make it longer if that will help. After these updates it seems to be more stable and Blynk values and widgets are getting updated properly during testing. Some disconnection issues still lingering.

I am using the detach interrupt to try and stabliize it. Terminal flush would probably help.

Here is what the Blynk debug looks like:

Blynk v0.3.4, needs updating to 0.4.4.

You will not really see an improvement by further increasing the 5000ms from your original 5ms.

You MUST flush, or virtualWrite to the terminal.

If you are still seeing regular disconnects after these mods you probably have more debugging to do.

I have updated the Blynk library. The unit seems to be keeping connection now. Another question I had is can I get my gauge widget to display more detailed numbers (i.e. decimal places so 4.8 instead of 5)? I have changed my code so that all variables are “float” and not “int” like before, so I think the arduino itself will now be tracking at a more granular level so I just need to figure out how to display that value in my gauge widget.

Unfortunately at the moment every widget is based on integer inputs so you can’t have a better resolution than whole numbers. (as I have understood it)
What you can do is use bigger numbers for display purposes.

Send every value times 1000 or some other factor that rids you of decimals. So for instance if it was voltages you sent, your 4.5V would be
4500 mV, that is workable in a gauge.

If you have a lot of decimals use the math library and round it after having multiplied it for the gauge.

Hope this could be a solution for you :slight_smile:

Edit: you can send decimal values to widgets, what I ment to say is that when placing a widget in the phone app you can’t set floats as min max values in the input boxes of the widget, to circumvent this do the above.

I myself have a need for a gauge showing my bat. Voltage, I will either go with mVolt 3300-4200 or calculate a percentage 0-100 based on volts. For display purposes

2 Likes
void clockToBlynk()
{
  int hourNow = hour();
  int minuteNow = minute();
  int secondNow = second();

  char currentTimeBuffer[8];
  sprintf(currentTimeBuffer   ,"%02u:%02u:%02u ", hour(), minute(), second() );

  //String currentTime = String(hourStr) + ":" + String(minuteStr) + ":" + String(secondStr);
  String currentDate = String(day()) + "-" + month() + "-" + year();

  //if(debug) { Serial.println("[" + String(millis()) + "] Time: " + currentTime); }
  //if(debug) { Serial.println("[" + String(millis()) + "] Date: " + currentDate); }
  
  Blynk.virtualWrite(V1, String(currentTimeBuffer));
  Blynk.virtualWrite(V2, currentDate);
}

Where V1/2 is just a value display set to Push. You can format it any way you want. Just String() the float value (not nice, I know :smiley: ) but it’ll display correctly. For the gauge I’d just settle for a percentage as @Fettkeewl indicates :slight_smile:

And @philmurp

The Labeled Value display can be set for up to 3 decimal places.

My gauge displays the 1 decimal place that I set it up for, currently 21.8°C.

Every widget supports floats. In fact every message is processed as String. So indeed you can display anything.

1 Like

yea I edited my post, I was refering to the min max settings for a widget not supporting float :slight_smile:

Thanks for all the options, for now I am working w/ the gauge having 1-5 and it just displays the detailed float (i.e. 3.974).

Then using:
char viewKeg1 [4];
dtostrf(keg1Quantity,4, 2, viewKeg1);
Blynk.virtualWrite(V0,viewKeg1);

I can get the gauge to display only two decimal points : 3.97 instead of 3.974

I also am experimenting w/ the LCD widget to see which I like better from a UX point of view.