Long delays causing loss of cloud connectivity

If I use a delay over 5 seconds delay(5000), my device goes offline ( I loose cloud connectivity) for a few seconds then goes back online. I’m running a photon on firmware 6.0. I thought this issue was fixed in a previous firmware update. So my question is, how can I run long delays without loosing connection to the cloud? Thanks Paul

@Paul_33, you can do “non blocking” delays using millis(). You can also enable system threading. The delay(5000) shouldn’t cause loss of cloud connectivity but I would need to see your code to advise.

I’m kind of a novice at this, here is my code;

    int de = 56;
    int i;

void setup() {
    pinMode(D0, INPUT);
    pinMode(D7, OUTPUT);
    unsigned long now = millis();
    i = 0;
}

void loop() {
    
    if (digitalRead(D0) == HIGH) {
       Particle.publish("water_alarm",String (de, DEC), 60, PRIVATE); //publish to web hook
       
        while (digitalRead(D0) == HIGH){
            
        digitalWrite(D7,HIGH); // turn on D7
       //
       delay(40000);
        Particle.publish("water_alarm",String (de, DEC), 60, PRIVATE);// send it again after 40 sec
        }
         
        digitalWrite(D7,LOW); // turn off D7
        }
 
    i=i+1;
   
  Particle.publish("water-alarm-CK-OK", String(i), PRIVATE);


    delay(5000);// if over 5 sec I loose  I temp loose cloud connection.

    
    }

sorry for the hard to read code, I guess I don’t know how to copy it correctly.

@Paul_33, whenever you add code, simply add start and end your code with three ` characters:

//I’ll try it again


   >  int de = 56;
>     int i;

> void setup() {
>     pinMode(D0, INPUT);
>     pinMode(D7, OUTPUT);
>     unsigned long now = millis();
>     i = 0;
> }

> void loop() {

>     if (digitalRead(D0) == HIGH) {
>        Particle.publish("water_alarm",String (de, DEC), 60, PRIVATE); //publish to web hook

>         while (digitalRead(D0) == HIGH){

>         digitalWrite(D7,HIGH); // turn on D7
>        //
>        delay(40000);
>         Particle.publish("water_alarm",String (de, DEC), 60, PRIVATE);// send it again after 40 sec
>         }

>         digitalWrite(D7,LOW); // turn off D7
>         }

>     i=i+1;

>   Particle.publish("water-alarm-CK-OK", String(i), PRIVATE);


>     delay(5000);// if over 5 sec I loose  cloud connection.


>     }

@Paul_33, just a few things. If you are trying to publish a “water alarm” condition every 40 seconds, simply test for D0 being high ALONG WITH a non-blocking 40s timer before publishing:

int de = 56;
int i;

unsigned long delay_40s = 0;
unsigned long delay_5s = 0;

void setup() {
	pinMode(D0, INPUT);
	pinMode(D7, OUTPUT);
	i = 0;
}

void loop() {
		
	if (digitalRead(D0) && (millis() - delay_40s >= 40000) {  // Water alarm condition AND 40 seconds has elapsed
		digitalWrite(D7,HIGH);
		delay_40s = millis();
		Particle.publish("water_alarm",String (de, DEC), 60, PRIVATE); //publish to web hook
	}
	else if (!digitalRead(D0)) // if no water alarm, reset the D7 LED
		digitalWrite(D7,LOW); // turn off D7
	}

	if (millis() - delay_5s >= 5000) {	// If 5 seconds have elapsed
		delay_5s = millis();
		i=i+1;
		Particle.publish("water-alarm-CK-OK", String(i), PRIVATE);
	}
}

I’m not sure if I got your logic correctly but each of the if(millis()...) statements creates a non-blocking delay so loop() runs freely which each target time has not elapsed.

Thanks, This seems to be working, I need to study it a little more to understand it fully. Thanks again for your help. Paul

2 Likes

Thanks @peekay123 for the help!

1 Like

@Paul_33, don’t hesitate to ask questions! :wink:

2 Likes

Alas, it is not enough to use non-blocking delays with millis(). I use it everywhere, but despite that I was always loosing cloud connectivity after a while with several such non-blocking functions. After loosing cloud connectivity the Photon did not reconnect by itself and I had to reset it. Enabling the system threading only helps, because during execution of some long or more processing even if in non-blocking functions in the loop() the application thread is blocked anyhow I guess.

@mrkale, there are other ways you application code could affect cloud connectivity. Your statement “after a while” suggests a possible heap fragmentation condition. Seeing your code might help guide our advice.

I’m having the same problem. Here’s my code. Any ideas?

// This #include statement was automatically added by the Particle IDE.
#include "MQTT/MQTT.h"

void callback(char* topic, byte* payload, unsigned int length) {
    // MESSAGE HAS ARRIVED FROM THE THETHINGS.IO
    String text = "";
    for (int i = 0; i < length; i++)
        text.concat((char)payload[i]);
    Serial.println(text);
}

MQTT client("mqtt.thethings.io", 1883, callback);

String TOKEN = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
String TOPIC = "v2/things/"+TOKEN;

const int OzonSensor = A3;

unsigned long ulNowMilli;
unsigned long nextOpenMeasurement = 0;
unsigned long nextReadMeasurement = 0;

unsigned int iCO2;
float fTemperature;
float fRH;
float fVOC;
unsigned int iPM2_5;
int iOzonValue = 0;

void setup() {

    Serial.begin(9600);
    Serial1.begin(9600);
    
    while (!client.connect("photonclient")) {
        Serial.println("Could not subscribe, retrying...");
    }
    open_close_particle_measurement( 2 );
    client.subscribe(TOPIC);            // SUBSCRIBE TO RECEIVE CHANGED VALUES FROM YOUR RESOURCES
}

void loop() {
    ulNowMilli = millis();

    if(ulNowMilli > nextReadMeasurement)
        {
            iOzonValue = analogRead(OzonSensor);
            Serial.print("Ozon = " );                       
            Serial.println(iOzonValue);
            
            read_particle_measuring_results();
            String message = "{\"values\":[{\"key\":\"CO2\",\"value\":"+String(iCO2, DEC)+"},{\"key\":\"Temperature\",\"value\":"+String(fTemperature/10, 1)+"},{\"key\":\"RH\",\"value\":"+String(fRH/10, 1)+"},{\"key\":\"VOC\",\"value\":"+String(fVOC/100, 2)+"},{\"key\":\"PM2.5\",\"value\":"+String(iPM2_5, DEC)+"},{\"key\":\"Ozon\",\"value\":"+String(iOzonValue, DEC)+"}]}";
            client.publish(TOPIC, message);            
            nextReadMeasurement = ulNowMilli + 300000;
        }
        
    if (client.isConnected()) {
        client.loop();
    }
}

void open_close_particle_measurement( byte bCommand )
{
byte response[5];

  Serial1.write(0x11);
  Serial1.write(0x03);
  Serial1.write(0x0C);
  Serial1.write(bCommand);
  Serial1.write(0x1E);
  Serial1.write((byte) (256-(0x11 + 0x03 + 0x0C + bCommand + 0x1E)));
  
  delay(500);
  
  Serial.print("Response = ");
    for (byte i = 0; i < 5; i++)
    {
        response[i] = Serial1.read();
        Serial.print(response[i], HEX);
        Serial.print(" ");
    }
    Serial.println(" ");
    
    
    if(response[3] == 2) Serial.println("Measurement OPEN Status");
    if(response[3] == 1) Serial.println("Measurement CLOSE Status");
}

void read_particle_measuring_results()
{
byte response[14];

  Serial1.write(0x11);
  Serial1.write(0x02);
  Serial1.write(0x01);
  Serial1.write(0x00);
  Serial1.write(0xEC);
  
  delay(200);
  
  Serial.print("Response = ");
    for (byte i = 0; i < 14; i++)
    {
        response[i] = Serial1.read();
        Serial.print(response[i], HEX);
        Serial.print(" ");
    }
  Serial.println("");
  
  iCO2 = response[3]*256 + response[4];
  Serial.print("CO2 = ");
  Serial.println(iCO2,DEC);  
  fTemperature = (response[9]*256 + response[10] -500);
  Serial.print("Temp. = ");
  Serial.println(fTemperature/10,1);
  fRH = (response[7]*256 + response[8]);
  Serial.print("RH = ");
  Serial.println(fRH/10,1);
  fVOC = (response[5]*256 + response[6]);
  Serial.print("VOC = ");
  Serial.println(fVOC/100,2);  
  iPM2_5 = response[11]*256 + response[12];
  Serial.print("PM2.5 = ");
  Serial.println(iPM2_5,DEC);
}

Add SYSTEM_THREAD(ENABLED) and avoid things like this

    while (!client.connect("photonclient")) {
        Serial.println("Could not subscribe, retrying...");
    }

or add Particle.process() in such loops

3 Likes

@ScruffR : I made the changes you proposed and the apllication worked for about 2,5 hour. But after that, no new values are posted to thethings.io. What else can I check?

In your loop() you are checking this

    if (client.isConnected()) {
        client.loop();
    }

but you don’t take any counteractions if client.isConnected() is not true.
In such a case you’d need to reestablish the connection, I’d think.

1 Like

If you wish to analyze my application, it is placed in the Github repository https://github.com/mrkalePhotonApp/thermometer.git and currently running. The code is quite long with many conditional compilation sectiona and publishing to 3 clouds, so that is not suitable to put it here. I would appreciate if you give me some advice to improve the processing flow.

This is great advice. Enabling multithreading in this way means that your user firmware can operate independently of the system firmware that is managing the connection in the background. This makes it far less likely that creating timing sensitive actions in your firmware will impact your devices' network connection.

@ScruffR : adding a reconnect solved my problems. It is running now perfectly. Thanks!

2 Likes