Software timers don't work on electron (fixed: don't use particle.publish in timer)

I’ve been developing some code on photon and everything has been working great. I’m now starting to run it on Electron but immediately faced weird problems with software timers. All in all it’s a long piece of code but I simplified it down a bit and this works:

void doPing() {
  //make ping attempt
  Serial.println("doing ping");
  Particle.publish("doing ping");
}

void setup() 
{
}

void loop() { 
   doPing();
    delay(3000);
    }

but this doesn’t:

Timer pingTimer(3000, doPing); 
void doPing() {
 //make ping attempt
 Serial.println("doing ping");
 Particle.publish("doing ping");
  }

void setup() {
    pingTimer.start();
} 

void loop() { 
   }

With the software timer example end result is that it does one ping and then electron keeps just breathing cyan as if everything was fine. However if any kind of action from cloud is tried (OTA flash or function call or anything) Electron just flashes several times red and then restarts itself. I’ve tried with both beta and production electron and both have 0.5.1 flashed. Any ideas? Can anyone else replicate this?

You can’t call Particle.publish() from a software timer. Yes, I realize it mostly works on a Photon, and it should be better documented. The problem is that software timers run in a separate thread. Particle.publish can’t be called from a thread other than the main loop thread.

2 Likes

Hmm ok. That definately should be documented somewhere. So I guess I’ll have to use some flags to work around it. Are there any reasons why in the upcoming versions Particle.publish can’t be made to work inside timer functions?

1 Like

Flags or just timing using millis() in loop is the way to go. While Particle.publish I suppose could be made thread safe, it’s also a blocking call, and you shouldn’t run blocking code in a software timer, anyway.

I’m just trying to avoid using any millis so I don’t need to do all the overflow checks. Otherwise millis would be great.I’ll work around with the flags then.

Rollover of mills seems scary at first, but one you know the trick it's really easy:

Not so much about being scary but just trying to cut down on using things which might break at some poing if not coded correctly. Also much less code that way (:

Here you have a solution.

Related question so I thought I’d add to the exiting post …
Do software timers execute while a particle.pubish call is executing?

I am collecting data and publishing it via Azure integration … I don’t want to miss events during this publish.

I think so. Software timers run on the System Thread, so they can execute while a Particle.publish() is executing.

EDIT: See @rickkas7's correct answer below.

Software timers run on their own dedicated thread, separate from the system and user threads. All of the timers run off a single thread, however, so if you block in a timer callback, it will block other timers.

Also, the software timers run with a much smaller stack than the user thread, so it’s best to avoid doing anything significant in a software timer callback.

1 Like

Hooray! I was having this problem and it drove me crazy for many hours with failed publishes, stack overflow, and server connection kills. I am so happy I found this thread! </me dances around>
I used the timer to raise a flag which triggers the publish in the main loop. Simple fix! Thanks!

Timer timer(60*1000, timedPublish, false);
bool pubFlag;
void setup() {
Particle.function("Test", Test); 
} 

void loop() {
 if (pubFlag) {
   char pubString[] = "Some Data";
   Particle.publish("TimedEvent", pubString); 
   pubFlag = false;
 }  
}

void timedPublish(){
  pubFlag = true; 
} 

int Test(String command){
   bool success = timer.start();
   return success;
}