Terminal repeating...and lots of connecting to server messages

My info:
Latest iOS app
Latest Blynk local server
Wemos D1 mini

So I searched and this topic has been discussed before, but I can’t see a resolution:

Issue 1
Whenever I reopen the Blynk app, the terminal text scrolls very fast from the top down to the bottom, and there are always duplicate items (as per the time stamps).

Here is a screenshot showing the issue:

Issue 2
I also notice there are lots of “Connecting/Ready/Time syc” lines, is this normal for the server to reconnect a lot? My device does not seem to go offline.

This might be normal behaviour if you see my below code.

Here is a longer text dump showing the behaviour:

21/3/2019 @ 20:15:49 : System disarm request

[264095896] Time sync: OK

21/3/2019 @ 20:15:52 : System disarmed

21/3/2019 @ 20:15:56 : System arm request

21/3/2019 @ 20:16:16 : System armed

21/3/2019 @ 20:15:49 : System disarm request

[264095896] Time sync: OK

21/3/2019 @ 20:15:52 : System disarmed

21/3/2019 @ 20:15:56 : System arm request

21/3/2019 @ 20:16:16 : System armed

[321457287] Time sync: OK

[321482361] Connecting to 192.168.1.95:8080

[321482374] Ready (ping: 7ms).

[321482513] Time sync: OK

9598] Connecting to 192.168.1.95:8080

[322359610] Ready (ping: 6ms).

[322359749] Time sync: OK

696] Connecting to 192.168.1.95:8080

[323286708] Ready (ping: 7ms).

[323286849] Time sync: OK

[324193858] Connecting to 192.168.1.95:8080

[324193871] Ready (ping: 8ms).

[324194010] Time sync: OK

[324219349] Connecting to 192.168.1.95:8080

[324219361] Ready (ping: 6ms).

[324219500] Time sync: OK

[325095932] Connecting to 192.168.1.95:8080

[325095942] Ready (ping: 4ms).

[325096081] Time sync: OK

[326899928] Connecting to 192.168.1.95:8080

[326899941] Ready (ping: 8ms).

[326900080] Time sync: OK

[326925413] Connecting to 192.168.1.95:8080

[326925425] Ready (ping: 6ms).

[326925563] Time sync: OK

[327832157] Connecting to 192.168.1.95:8080

[327832171] Ready (ping: 8ms).

[327832310] Time sync: OK

[327862205] Connecting to 192.168.1.95:8080

[327862219] Ready (ping: 9ms).

[327862358] Time sync: OK

[328734233] Connecting to 192.168.1.95:8080

[328734246] Ready (ping: 7ms).

[328734385] Time sync: OK

[329636317] Connecting to 192.168.1.95:8080

[329636329] Ready (ping: 6ms).

[329636469] Time sync: OK

[321457287] Time sync: OK

[321482361] Connecting to 192.168.1.95:8080

[321482374] Ready (ping: 7ms).

[321482513] Time sync: OK

9598] Connecting to 192.168.1.95:8080

[322359610] Ready (ping: 6ms).

[322359749] Time sync: OK

696] Connecting to 192.168.1.95:8080

[323286708] Ready (ping: 7ms).

[323286849] Time sync: OK

[324193858] Connecting to 192.168.1.95:8080

[324193871] Ready (ping: 8ms).

[324194010] Time sync: OK

[324219349] Connecting to 192.168.1.95:8080

[324219361] Ready (ping: 6ms).

[324219500] Time sync: OK

[325095932] Connecting to 192.168.1.95:8080

[325095942] Ready (ping: 4ms).

[325096081] Time sync: OK

[326899928] Connecting to 192.168.1.95:8080

[326899941] Ready (ping: 8ms).

[326900080] Time sync: OK

[326925413] Connecting to 192.168.1.95:8080

[326925425] Ready (ping: 6ms).

[326925563] Time sync: OK

[327832157] Connecting to 192.168.1.95:8080

[327832171] Ready (ping: 8ms).

[327832310] Time sync: OK

[327862205] Connecting to 192.168.1.95:8080

[327862219] Ready (ping: 9ms).

[327862358] Time sync: OK

[328734233] Connecting to 192.168.1.95:8080

[328734246] Ready (ping: 7ms).

[328734385] Time sync: OK

[329636317] Connecting to 192.168.1.95:8080

[329636329] Ready (ping: 6ms).

[329636469] Time sync: OK

22/3/2019 @ 14:44:41 : System disarm request

[330623335] Time sync: OK

22/3/2019 @ 14:44:42 : System disarmed

[330658275] Connecting to 192.168.1.95:8080

[330658286] Ready (ping: 5ms).

[330658425] Time sync: OK

[330688779] Connecting to 192.168.1.95:8080

[330688791] Ready (ping: 7ms).

[330688934] Time sync: OK

[327832157] Connecting to 192.168.1.95:8080

[327832171] Ready (ping: 8ms).

[327832310] Time sync: OK

[327862205] Connecting to 192.168.1.95:8080

[327862219] Ready (ping: 9ms).

[327862358] Time sync: OK

[328734233] Connecting to 192.168.1.95:8080

[328734246] Ready (ping: 7ms).

[328734385] Time sync: OK

[329636317] Connecting to 192.168.1.95:8080

[329636329] Ready (ping: 6ms).

[329636469] Time sync: OK

22/3/2019 @ 14:44:41 : System disarm request

[330623335] Time sync: OK

22/3/2019 @ 14:44:42 : System disarmed

[330658275] Connecting to 192.168.1.95:8080

[330658286] Ready (ping: 5ms).

[330658425] Time sync: OK

[330688779] Connecting to 192.168.1.95:8080

[330688791] Ready (ping: 7ms).

[330688934] Time sync: OK

[331558559] Connecting to 192.168.1.95:8080

[331558579] Ready (ping: 13ms).

[331558729] Time sync: OK

[332464186] Connecting to 192.168.1.95:8080

[332464203] Ready (ping: 12ms).

[332464342] Time sync: OK

[332493060] Connecting to 192.168.1.95:8080

[332493071] Ready (ping: 5ms).

[332493212] Time sync: OK

[334293878] Connecting to 192.168.1.95:8080

[334293895] Ready (ping: 12ms).

[334294034] Time sync: OK

[334327255] Connecting to 192.168.1.95:8080

[334327270] Ready (ping: 7ms).

[334327409] Time sync: OK

22/3/2019 @ 15:57:48 : System arm request

[335009449] Time sync: OK

22/3/2019 @ 15:58:8 : System armed

I am guessing that this is because I have this line in my void setup?

setSyncInterval(10 * 60); // Sync Blynk real time clock (RTC) interval in seconds (10 minutes)

and

BLYNK_CONNECTED()
{
  // Synchronize time on connection
  rtc.begin();
}

Why does it print the millis automatically? Can I stop that?

Thank you

Please post your complete code for the sketch :slightly_smiling_face:

Sure, I’m away from my PC at the moment, but here’s a link:

Thanks

timer.setInterval(100L, checkCombined);  //Setup a function to be called every second

Maybe if you did call this every second, instead of 10 times per second, you might have fewer disconnects.
The checkCombined function does quite a lot. Even if you call it less frequently you may still have problems. You could try throwing some Blynk.run() commands in the function to see if that helps.

Pete.

Does this actually work? I mean, why not say (600) instead? :slight_smile:

setSyncInterval(10 * 60); // Sync Blynk real time clock (RTC) interval in seconds (10 minutes)

I use a terminal.flush(); after my text blocks. But can’t remember if that helped for the duplicate string-error or not. Perhaps worth a try?!

Elsewhere in the forum it was suggested that it was due to lag caused by SimpleTimer. I always recommend to ease up on the timers where it’s possible because it seems to be the source of many strange errors.

Some other approaches is found in this thread.

Thanks @PeteKnight

Yes now you mention it is very frequent, I will try a longer timer. I’m not sure how fast the code can be processed to be honest.

I was getting hearbeat timeouts with my old code and disconnects from the server, with this latest code i get no timeouts and it never appears to disconnect in the app. But I’m guessing it must be disconnecting.

How will putting Blink.run in the function help?

Thank you :blush:

@distans yes it does work, I could put 600 as well. I might try 1800 (30mins) in future as surely it can keep time for that long before going out of sync!

I will try terminal.flush as well to see what occurs.

I understand Simpletimer is included in the Blynk library, it could also be that I guess.

Ultimately it’s more of an annoyance than anything, I would like to fix the server the-connecting issue mainly.

Thanks :slight_smile:

It will ensure that the background Blynk processes are fed with processor time.
It works surprisingly well.

Pete.

I’d call it an improved timer library so there is actually no need to use SimpleTimer. Looking thru some of my own code it looks like I only use the BlynkTimer nowadays. Ergo, it must be better! :wink:

BlynkTimer allows you to send data periodically with given intervals not interfering with Blynk library routines

  • When a timer struggles to run multiple times (due to a blocked loop ), it just skips all the missed intervals, and calls your function only once. This differs from SimpleTimer , which could call your function multiple times in this scenario.

A bit more on the idea of putting Blynk.run() in other places within your code (rather than just in the void loop. The documentation says this:

Blynk.run()

This function should be called frequently to process incoming commands and perform housekeeping of Blynk connection. It is usually called in void loop() {} .

This command can be initiated it in other places of your code unless you run out of heap memory (in the cascaded functions with local memory).

For example, it is not recommended to call Blynk.run() inside of the BLYNK_READ and BLYNK_WRITE functions on low-RAM devices.

https://docs.blynk.cc/#blynk-firmware-connection-management-blynkrun

Pete.

@distans you might be onto something there, the SimpleTimer combined with the short interval would cause multiple timer calls it seems, thanks! :slight_smile:

@PeteKnight thanks for the further information, I will read it now and give it a try. I have a second test system running which I will use, then flash it to the ‘live’ system.

It would be interesting to see how much RAM is free on the Wemos, I’m not sure this can be determined remotely. I’ll have a search…

Thanks both! :smile:

Courtesy of @Costas

Blynk.virtualWrite(V1, "\n Free RAM: ", ESP.getFreeHeap());

Pete.

Brilliant thanks @PeteKnight and of course @Costas :smile:

Out of interest I am getting 46240 bytes of free ram reported, which seems pretty good to me.

I’ve also changed to BlynkTimer (I was still using SimpleTimer) and will see how that goes from now.

Thanks guys

1 Like

Update for anyone who might search this in the future.

I have so far:
Moved to BlynkTimer from SimpleTimer
Increased interval of time sync
Increased timers to 500ms (1000ms was a bit laggy)
Check enough free RAM is available
Added terminal.flush code
Swapped all serial.print’s for Blynk.virtualWrite

Ideas left:
Add more Blynk.run commands

And… I’m still getting server reconnecting messages at random times, and terminal repeats as per the following:


23/3/2019 @ 15:37:52 : Server connected

[3504632] Connecting to 192.168.1.95:8080

[3504645] Ready (ping: 8ms).

[3504784] Time sync: OK



23/3/2019 @ 15:52:24 : Server connected

[4376568] Connecting to 192.168.1.95:8080

[4376581] Ready (ping: 7ms).

[4376720] Time sync: OK



23/3/2019 @ 16:7:56 : Server connected

[5308696] Connecting to 192.168.1.95:8080

[5308709] Ready (ping: 8ms).

[5308848] Time sync: OK



23/3/2019 @ 16:8:26 : Server connected

[5338928] Connecting to 192.168.1.95:8080

[5338940] Ready (ping: 7ms).

[5339079] Time sync: OK



23/3/2019 @ 16:53:2 : Server connected

[8014573] Connecting to 192.168.1.95:8080

[8014588] Ready (ping: 10ms).

[8014727] Time sync: OK



23/3/2019 @ 19:33:13 : Server connected

[17625863] Connecting to 192.168.1.95:8080

[17625910] Ready (ping: 41ms).

[17626136] Time sync: OK



23/3/2019 @ 19:33:13 : Server connected

[17625863] Connecting to 192.168.1.95:8080

[17625910] Ready (ping: 41ms).

[17626136] Time sync: OK

I added a time/date stamp and can’t see any pattern. It might be when I am checking the app, I’m not sure.

I’m thinking I may not be able to resolve this, and chalk it up to a terminal bug.

What is your latest code look like? In your last code you had two interval timers both running their respective functions at the exact same time, that could cause issues.

Hi @Gunner

Here’s my latest code, yes the two timers run at the same time interval. I could set them differently i.e. 300 and 500ms, they would still get called at the same time every 5th call though (correct?).

Thanks

//v009 Garage alarm (change from interrupts to polling)
//
//
//Project requirements:
//The alarm panel has two outputs, Armed and Sounder
//Poll these two outputs every 1000ms and write the result to a virtual LED (Blynk app on phone)
//The alarm panel has one input SET which can arm or disarm the system
//When a virtual button is pressed (on phone Blynk app) the alarm is armed or unarmed.
//
//
//Changelog:
//v004 had issues with Blynk server heartbeat timeouts and app disconnecting and sometimes unresponsive
//v005 combines both armed and sounder functions into one, run by one timer
//v006 added serial to terminal code as per this thread https://community.blynk.cc/t/serial-arduino-to-terminal-blynk/31547/4
//v007 added correct serial to terminal code working correctly - needs rx to tx link on device
//v008 added date/time stamp to terminal widget, required rtc widget on app, and added serial prints when states change
//v009 fixes for terminal repeating (used BlynkTimer and increased timer interval. Optional add Blynk.run to function 
//so that more CPU time is allocated for housekeeping. Rewrote serial prints as virtual writes to V1. Search for "v009" to see changes.
//
//Future improvements:
// Change code to Blynk.virtualWrite(vPin, "Random blatherings\n") where required
//


//Optional/not needed? libraries
//#define BLYNK_DEBUG  //optional, enable for debugging to serial 
//#include <ESP8266WiFi.h>  //not needed?
//#include <TimeLib.h> //not needed?

#define BLYNK_PRINT Serial // Defines the object that is used for printing Blynk stuff
#include <BlynkSimpleEsp8266.h>
#include <ESP8266mDNS.h>  //for OTA updates
#include <WiFiUdp.h>     //for OTA updates
#include <ArduinoOTA.h>  //for OTA updates
#include <WidgetRTC.h>   //for clock sync
  

//Blynk credentials
char auth[] = ""; //Enter the Auth code which was send by Blynk
//char auth[] = ""; // v009 TEST Breadboard auth token
//Wifi credentials
char ssid[] = "";  //Enter your WIFI Name
char pass[] = "";  //Enter your WIFI Password
//Server credentials
char server[] = "192.168.1.93"; //LOCAL SERVER ONLY
int port = 8080;  //LOCAL SERVER ONLY


//Support for Blynk terminal
WidgetTerminal terminal(V1); //terminal reads from virtual pin specified

//Support for Blynk real time clock
WidgetRTC rtc;

//SimpleTimer timer; //setup simple timer to call functions on a timed basis from void loop
BlynkTimer timer; // v009 improvement http://docs.blynk.cc/#blynk-firmware-blynktimer 


//Setup constants for the sketch
const byte Armed = D5;    // INPUT - is the panel armed, or un-armed/alarmed? (armed = HIGH/3.3V and Unarmed/alarmed = LOW/0V)
const byte Sounder = D6;  // INPUT - is the sounder on or off? (Sounder on = LOW/0.33V and Sounder off = HIGH/3.3V)
const byte SET = D4;      // OUTPUT - set or unset the alarm (HIGH = unset the alarm,  LOW = set the alarm)

//Setup variables for Armed
int ArmedState = digitalRead(Armed); //reads armed state of the alarm (armed = HIGH/3.3V and Unarmed/alarmed = LOW/0V)
int lastArmedState = ArmedState; // the previous read from the input pin

//Setup variables for Sounder
int SounderState = digitalRead(Sounder); //reads state of sounder i.e on or off (Sounder on = LOW/0.33V and Sounder off = HIGH/3.3V)
int lastSounderState = SounderState; // the previous read from the input pin

//Setup variables for debouncing of inputs
unsigned long lastArmedDebounceTime = 0;    //setup debounce variable for checkArmed function
unsigned long lastSounderDebounceTime = 0;  // setup debounce variable for checkSounder function
unsigned long debounceDelay = 50;           // the global debounce time in ms, increase if debounce issues continue

//Setup variable for Blynk virtual pin
static unsigned long last_interrupt_time = 0;
bool LastVirtualButtonState = 0;  //"0","FALSE","LOW' means exactly the same



void setup()
{
  Serial.begin(9600);
  Blynk.begin(auth, ssid, pass, server, port);  //connects to Wifi and LOCAL Blynk server (running on raspberry pi)
  setSyncInterval(60 * 60); // v009 increase time if needed - Sync Blynk real time clock (RTC) interval in seconds (default 10x60 = 10 minutes)
 
  //OTA stuff (update device from Arduino IDE remotely)
  ArduinoOTA.onError([](ota_error_t error) { ESP.restart(); });
  ArduinoOTA.setHostname("Wemos_no_05_Garage_Alarm");
  //ArduinoOTA.setHostname("Wemos_no_01_TEST_GARAGE_ALARM"); // for testing purposes
  ArduinoOTA.begin();
  
  //Setup the previously assigned constants
  pinMode(Armed, INPUT);       //is the panel armed, or un-armed/alarmed? (armed = HIGH/3.3V and Unarmed/alarmed = LOW/0V)
  pinMode(Sounder, INPUT);     //is the sounder on or off? (Sounder on = LOW/0.33V and Sounder off = HIGH/3.3V)
  pinMode(SET, OUTPUT);        //set or unset the alarm (HIGH = unset the alarm,  LOW = set the alarm)
  digitalWrite(SET, LOW);      //ensures the alarm defaults to SET condition after power loss of Wemos

  //write the current states to the Blynk app
  Blynk.virtualWrite(V5, (ArmedState * 255));      // writes set or unset state of alarm to Blynk virtual LED pin V5
  Blynk.virtualWrite(V6, (!SounderState * 255));   //writes sounder on or off state to Blynk virtual LED pin V6 (inverted logic as sounder is on when at 0V

  //Setup Blynktimers
  timer.setInterval(500L, Sent_serial);  // Timer calls function to send any serial data to terminal - default 100ms  - v009 increase interval if needed
  timer.setInterval(500L, checkCombined);  //Timer calls function to read state of alarm panel - default 100ms  - v009 increase interval if needed

  //Optional print free memory to terminal
  Blynk.virtualWrite(V1, "Free RAM: ", ESP.getFreeHeap(), " bytes\n");    //v009 optional print free RAM each time the function is called
  //Blynk.virtualWrite(V1, "\n" );                                        //starts new line
}



void loop()
{
  Blynk.run();  //This function should be called frequently to process incoming commands and perform housekeeping of Blynk connection.
  timer.run();  //Initiates SimpleTimer to runs timed functions
  ArduinoOTA.handle();  // For OTA
}



BLYNK_CONNECTED()
{
  rtc.begin();  // Synchronize time on connection
  serial_print_date_time();
  Blynk.virtualWrite(V1, "Server connected\n");
  //Blynk.virtualWrite(V1, "\n" );  //starts new line
}



//A function to print current date and time to Blynk terminal widget, gets called from the below functions
void serial_print_date_time()
{
  Blynk.virtualWrite(V1, "\n" );   
  String currentDate = String(day()) + "/" + month() + "/" + year();
  String currentTime = String(hour()) + ":" + minute() + ":" + second();
  Blynk.virtualWrite(V1, currentDate, " @ ", currentTime, " : ");
}



void Sent_serial() //A function which reads the serial monitor output and send to terminal widget (requires tx and rx pins to be connected together on device).
{
  // Sent serial data to Blynk terminal - Unlimited string readed
  String content = "";  //null string constant ( an empty string )
  char character;
  while(Serial.available())
  {
   character = Serial.read();
   content.concat(character);
  }
  if (content != "") 
  {
   Blynk.virtualWrite (V1, content);
   terminal.flush();   // Ensure that data was sent out of device  //added by 877dec v009
  }  
}



void checkCombined()// a combined function to read the "armed" state and the "sounder" state
{
 int readingArmed = digitalRead(Armed); // read the state of "Armed" into a local variable:

  if (readingArmed != lastArmedState)   //has the state changed?
  {
    lastArmedDebounceTime = millis();  // if yes(state has changed), reset the debouncing timer to the current millis
  }


  if ((millis() - lastArmedDebounceTime) > debounceDelay) // whatever readingArmed is at, it's been there for longer than the debounce delay, so take it as the actual current state
  {

    if (readingArmed != ArmedState) // has the armed state has changed?
    {
        ArmedState = readingArmed;  // if yes(state has changed) 
        Blynk.virtualWrite(V5, (ArmedState) * 255); // writes ArmedState to Blnk V5 virtual LED names "Alarm armed?"

        if (ArmedState == LOW)
        {
          serial_print_date_time();
          Blynk.virtualWrite(V1, "System disarmed"); //writes to terminal widget
          terminal.flush();   // Ensure that data was sent out of device
        }

        else
        {
          serial_print_date_time();
          Blynk.virtualWrite(V1, "System armed"); //writes to terminal widget
          terminal.flush();   // Ensure that data was sent out of device
        }
    }
  }
  
  lastArmedState = readingArmed; // save the readingArmed. Next time through the function, it'll be the lastArmedState:

 Blynk.run(); //v009 optional extra Blynk.run to allocate more CPU/RAM to the Blynk process, to remove duplicate terminal issues

 int readingSounder = digitalRead(Sounder); // read the state of "Armed" into a local variable:

  if (readingSounder != lastSounderState)   //has the state changed?
  {
    lastSounderDebounceTime = millis();  // if yes(state has changed), reset the debouncing timer to the current millis
  }


  if ((millis() - lastSounderDebounceTime) > debounceDelay) // whatever readingSounder is at, it's been there for longer than the debounce delay, so take it as the actual current state
  {

    if (readingSounder != SounderState) // has the sounder state has changed?
    {
          SounderState = readingSounder;  // if yes(state has changed) 
          Blynk.virtualWrite(V6, (!SounderState) * 255); // writes SounderState to Blnk V6 virtual LED named "Sounder on?"

          if (SounderState == LOW)
          {
          Blynk.notify("Garage alarm is sounding!");  //only send Blynk app notification when then sounder is ON
          serial_print_date_time();
          Blynk.virtualWrite(V1, "Sounder activated!"); //writes to terminal widget
          terminal.flush();   // Ensure that data was sent out of device
          }

          else
          {
          serial_print_date_time();
          Blynk.virtualWrite(V1, "Sounder deactivated"); //writes to terminal widget
          terminal.flush();   // Ensure that data was sent out of device
          }
        
     }
  }
  
  lastSounderState = readingSounder; // save the readingSounder. Next time through the function, it'll be the lastSounderState:
}



// BLYNK_WRITE is a function called every time the device gets an update of a Virtual Pin value from the server (e.g. Blynk app virtual button is pressed)
// contains "latching" code to stop long hold being registered as repeated presses.
BLYNK_WRITE(V3)
{
  int VirtualButtonState = param.asInt(); // assigning incoming value from pin V3 to a variable

  if ((VirtualButtonState) && (!LastVirtualButtonState)) // "VirtualButtonState" is the Blynk virtual button current state ||||||  this means same as "if ((VirtualButtonState == 1) && (LastVirtualButtonState == 0))"
    //if V3 virtual button is still being pressed, the LastVirtualState is set to 1, and !LastVirtualState will therefore be 0. Hence 1 && 0 condition == 0 and therefore function will not be called.
  {
    digitalWrite(SET, !digitalRead(SET));       //writes the inverse value to the pin  (booleon NOT operator )
    Blynk.virtualWrite(V0, digitalRead(SET) * 255);  // for  information only, writes the state of the keyswitch SET contacts to Blynk virtual LED at V0

    if (digitalRead(SET) == LOW)
    {
     serial_print_date_time();
     Blynk.virtualWrite(V1, "System arm request"); //writes to terminal widget
     terminal.flush();   // Ensure that data was sent out of device
    }

    else
    {
     serial_print_date_time();
     Blynk.virtualWrite(V1, "System disarm request"); //writes to terminal widget
     terminal.flush();   // Ensure that data was sent out of device
    }
  }

  LastVirtualButtonState = VirtualButtonState;  // sets LastVirtualButtonState to the same as pinValue, so if pinValue (V3 button) is high, LastVirtualPinState gets set to high
}

Would it be a sin to,

void setup(void) {
   ...
   timer.setInterval(500L, Sent_serial);
   delay(100);
   timer.setInterval(500L, checkCombined); 
}

This achieves the interval you want and they’ll never be called at the same time.

Yes… but much less frequently if staggered even more, like 435 & 770 etc…

No different then

   timer.setInterval(500L, Sent_serial);
   timer.setInterval(600L, checkCombined);