I live in a rural area and the only internet service is Hughesnet satellite. The latency ranges from .50 to 1 second. This causes a problem with Photon connectivity to Particle’s console. For the console to have enough time to record sensor reading a delay needs to be inserted in my code. I believe this is standard for everyone. The lowest value I can use in the delay command to avoid the console from freezing-up is 340. However, when this value is added to the inherent satellite latency it causes my Photon to disconnect from the cloud/console for a few seconds. This connect/disconnect happens every thirty seconds or so. I was hoping there was a work around to solve the problem.
Yes when I remove the code that Is designed to slow down the main loop - delay ( ) - the Photon maintaines connectivity. In other words, for test purposes, I removed the delays from my code while leaving the publish commands. In this state, the code runs too fast for the sensor readings to register on the console log screen but the Photon maintains connectivity.
You should always try to keep dropping out of loop() as quickly as possible.
If you want to slow down your code, rather go for non-blocking approaches like Software Timers or “soft delay”
void loop()
{
static uint32_t msSoftDelay;
if (millis() - msSoftDelay >= 6000)
{ // do this only once in 6 seconds
msSoftDelay = millis();
...
}
}
Or if you have code that needs to run for extended periods of time, regularly call Particle.process() to maintain the cloud connection or use SYSTEM_THREAD(ENABLED) to decouple the cloud connection from your code.
The problem I run into with satellite is its latency. As stated, its average is about .75 of a second. Throw in a delay command and the cloud times out causing the photon to lose connectivity. This happens every 30 seconds or so.
Based on your code snippet above and your advice, I believe I hear you saying that I need to leave the main loop as often as possible. I do this via functions. That said, for the most part my functions are called from the main loop and my publish commands are within the functions’ bodies. I’m not using any “returns” in my functions because I’m using global variables.
This issue is perplexing to me because I need to use some sort of delay to allow the console to accept and display sensor values but when I use the appropriate delay value it adds to the satellite latency causing a disconnect.
Perhaps there is a way to extend the time interval the cloud uses to disconnect. If I could add a few seconds maybe it will fix the problem? I may be way off here but based on my observations I’m thinking it may work. Sure would appreciate any advice, I’m not familiar with the behind the scenes code used.
One thing, when you are calling a function fromloop() you are not leaving loop() but only extend the path through loop(). Leaving loop() as I meant it is dropping out of loop() either via a return statement or by reaching the end of if it.
This is exactly what my code does. Without my code, you would be publishing every iteration of loop() about 1000 times per second, which will violate the publish rate limit of 1/sec. But with my code, you will visit loop() most the time, just to leave it again without doing anything. But every 6th second you will be publishing (or doing whatever else) without violating the rate limit.
And no there is no way to extend the time interval and it's not required either, when you do as said.
So why not just try my code wrapping around your existing body of loop() and remove all the delays and see what happens.
Since we don't know what you're actually doing in your funcitons there might also be other issues burried there.
I added the code you suggested but still having the disconnect issue. I provided my code to give you some additional insight. My next question would be where to insert the Particle.process() commands?
#include "SparkFunMAX17043/SparkFunMAX17043.h"
int tiltPin = D4;
int ledPin = D2;
int counter = 0;
int tiltState = LOW;
int tHour;
int tMin;
int tDay;
int y = 0;
long i = 1;
double voltage = 0; // Variable to keep track of LiPo voltage
double soc = 0; // Variable to keep track of LiPo state-of-charge (SOC)
bool alert; // Variable to keep track of whether alert has been triggered
void setup() {
pinMode(ledPin, OUTPUT);
pinMode(tiltPin, INPUT_PULLDOWN);
publishCheck();
Time.zone(-5);
// Particle.variable("voltage", voltage);
Particle.variable("tilt",tiltState);
// Particle.variable("I",i);
Particle.variable("Per",soc);
// Set up the MAX17043 LiPo fuel gauge:
lipo.begin(); // Initialize the MAX17043 LiPo fuel gauge
// Quick start restarts the MAX17043 in hopes of getting a more accurate
// guess for the SOC.
lipo.quickStart();
// We can set an interrupt to alert when the battery SoC gets too low.
// We can alert at anywhere between 1% - 32%:
lipo.setThreshold(20); // Set alert threshold to 20%.
}
void checkTilt() {
if (tiltState == HIGH) {
digitalWrite(ledPin, HIGH); // determines if tilt is high
counter = 1;
publishCheck();
}
else
if (tiltState == LOW) {
digitalWrite(ledPin, LOW); // determines if tilt is low
counter = 0;
publishCheck(); // check to see if eligible for publish
}
}
void publishCheck() {
if (counter == 1) {
Particle.publish("TiltValue", String(tiltState)); //publish if counter == 1 do not publish for any other value
counter = 2; // this allows for only one publish.
delay(500);
} else {}
}
void putmetoSleep(int y) {
if (y == 1) {
System.sleep(SLEEP_MODE_DEEP,142200); // go to sleep for 39.5 hours
}
else
if (y == 2) {
System.sleep(SLEEP_MODE_DEEP,64800); // go to sleep for 18 hours wake at 9 am.
}
else {}
}
void checkTime() {
y = 0; // resest y to 0 during each loop
tHour = Time.hour(); // populates time and day variables
tMin = Time.minute();
tDay = Time.weekday();
if ((tDay == 7) && (tHour == 17) && (tMin == 30)) { // If Saturday and 5:15 PM shut down until Monday 9am.
y = 1;
putmetoSleep(y);
}
else
if ((tDay != 7) && (tHour == 15)) { //weekday shut down from 3PM to 9am next day.
y = 2;
putmetoSleep(y);
}
else {}
}
void batteryCheck() {
i++;
// lipo.getVoltage() returns a voltage value (e.g. 3.93)
voltage = lipo.getVoltage();
// lipo.getSOC() returns the estimated state of charge (e.g. 79%)
soc = lipo.getSOC();
// lipo.getAlert() returns a 0 or 1 (0=alert not triggered)
alert = lipo.getAlert();
if ((i > 98) && ( i < 100)) {
Particle.publish("Per", String(soc)); // if battery SOC 20% or lower publish
delay(500);
i = 1;
}
else {}
}
void loop() {
static uint32_t msSoftDelay;
if (millis() - msSoftDelay >= 6000) {
msSoftDelay = millis();
}
tiltState = digitalRead(tiltPin);
checkTime();
checkTilt();
batteryCheck();
}
You can also have multiple soft delays or keep less time consuming functions out of the soft delay block - but now the general idea should be clear, or not?
Very clear. What a neat piece of code, it works great now. I even slowed it down to 3000 and it still stays connected. I very much appreciate your time and patience.