SYSTEM_THREAD during listen mode?

First the new SYSTEM_THREAD is totally awesome. Just some quick initial tests at it works as advertised. Soooo I am here to ask for more :smile:

Can we continue the multiple threads during listen mode (or maybe it is called setup mode on photon)? I will give you the quick why next.

I am working on an appliance. The appliance may be operating when the user wants to set up Wi-Fi. It would be awesome if it could just keep operating while in setup mode. Also I want the appliance to work even for users who don’t wanna use WiFi. I would like to get rid of the “set-up wifi button.” and just listen for 30 minutes after power up and if I don’t get configured just stop listening and work like a traditional embedded controller. However I can’t just wait 30 minutes until the unit starts operating.

Thoughts?

1 Like

At present the application thread is deliberately blocked from re-entring loop() when listening mode is active since that opens up a lot of untested possibilities.

Technically, if you never exit loop() then your code will continue running even during listening mode, so you could try it and see the results, but I can’t promise it works the way you want, since this is untested and uncharted territory!

For the full release of system threading, we do want to allow application code to execute while in listening mode, but it requires more changes than we had time for in the beta.

@mdma
I assumed you meant while(1) inside the loop() function. This is not work. I encapsulated my test code in the while 1 loop, and forced listen mode with the button, and the test code was blocked. If you have any other ideas, I am all ears.

Is there a time frame on the full release of threading. btw nice job… You guys nailed your “end of September” release on threading.

@jerome, I have been trying to achieve a similar outcome as you, ie remain operating in listen mode. My issue is when there are no credentials loaded, the Photon automatically starts in listening mode and one cannot exit until credentials are set.

My work around to this was to load a dummy set of WiFi credentials which means that the Photon will not enter listening mode automatically. In setup you sit on WaitFor() which will eventually timeout due to no connection. In the mean time the app thread is running. This assumes v0.4.6 and THREADING enabled.

So, at some future time if you want to add a WiFi access point, you just enter listening mode in the usual way.

1 Like

You can avoid having the device automatically enter listening mode if you use this call:

WiFi.connect(WIFI_CONNECT_SKIP_LISTEN);

This means using SEMI_AUTOMATIC mode so that your application is responsible for intializing the WiFI connection if it is not connected.

1 Like

That’s something I didn’t know.

However, I really think I will need to be servicing somethings during listen mode. For our appliance we wanted to have a "flashing LED on the UI indicating we are in WiFi configuration mode. currently our UI is run using a i2c LED display driver. So I don’t understand how to make my appliance appear alive while in listen mode… Any ideas?

What’s wrong with using the blue blink on the Photon (e.g. via the solder pads on the bottom of the Photon)?

Or you could maybe try if you can access your LED display from RGB.onChange().

Interrupts and timers should also be active during Listening Mode.

We wanted a slightly different use case on the LED’s. I think the photon LED is great, for developer but not what we wanted. My worry is calling functions from the ISR. I won’t ussually call an I2C function from an ISR. ussually I would set a flag and call the i2c somewhere in my task handler. But since the listen mode blocks everything else (except interrupts) and timer’s I guess I will have to try.

I’ve not used I2C in RGB.onChange(), but the code that I tried in there did work through most modes and led patterns I tried out - Listening Mode was not one of them, I’m afraid :wink:

1 Like

Just had a test with Listening Mode with my Particle InternetButton and it works, I can even leave Listening Mode again

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

SYSTEM_MODE(SEMI_AUTOMATIC)
//SYSTEM_THREAD(ENABLED)

InternetButton b = InternetButton();

void setup()
{
  RGB.onChange(doRing);
  Particle.function("EnterListen", enterListen);
  b.begin();

  WiFi.connect(WIFI_CONNECT_SKIP_LISTEN);
}

void loop()
{
}

int enterListen(String cmd)
{
  WiFi.listen(); 
  return -1;
}

void doRing(uint8_t R, uint8_t G, uint8_t B)
{
  b.ledOn(1, R, 0, 0);
  b.ledOn(2, 0, G, 0);
  b.ledOn(3, 0, 0, B);
  b.ledOn(6, R, G, B);
  
  if(b.buttonOn(1)) 
    WiFi.listen(!WiFi.listening()); 

  if(b.buttonOn(3))
    if (Particle.connected())
      Particle.disconnect();
    else
      Particle.connect();
}

(Updated code)

1 Like

@mdma, in SEMI_AUTOMATIC mode, I tried

WiFi.connect(WIFI_CONNECT_SKIP_LISTEN);

placing it at the first line within setup(), but it still entered listening mode when I had no WiFi credentials loaded. This is no big deal, just mentioning it for the record.

My experience is, you have to make sure to depower the Photon after you wiped the credentials and then try it again.

If I just wipe the credentials (via button or code) the Photon enters into Listening Mode immediately and will even go there after a reset (button or code).
But when I depower the device (for a few seconds at least), then it will come back blinking green.

When I then call WiFi.listen() (as shown in my code above) the device goes into LM and will also leave LM when calling WiFi.listen(false).

Thanks for sticking with me @ScruffR. I think I finally get it… What I wanted is a thread that always runs (no matter what the mode). So if I Enable threading this works all the time except listen mode. In listen mode I use the RGB.onChange() to call the “thread.” I would call this a work around to a shortcoming in threading, but I just ran some testing and seems to work. My test code is below. myLoop() is intended to be the ever running thread.

#include "application.h"

//globals
bool pin_state = false;
bool pin_state2 = false;
int loop_cnt = 0;
int my_loop_cnt = 0;

SYSTEM_THREAD(ENABLED);
SYSTEM_MODE(MANUAL);

void myLoopWrapper(uint8_t R, uint8_t G, uint8_t B)
{
  if(WiFi.listening()) myLoop2();
  return;
}

void myLoop()
{
  if(pin_state == false) pin_state = true;
  else pin_state = false;
  my_loop_cnt++;
  digitalWrite(D3, pin_state);
}

void setup()
{
  RGB.onChange(myLoop);
  pinMode(D4, OUTPUT);
  pinMode(D3, OUTPUT);
  Particle.connect();
}

void loop()
{
  if(loop_cnt > 120) WiFi.listen();
  myLoop();
  loop_cnt++;
  delay(250);
}
1 Like

Cool, you got it “working” :+1:

I definetly agree this can only be called workaround

@ScruffR, power cycling made no difference to my issue, it still immediately entered listening mode when there is no WiFi credentials stored.

I note that your example does not have SYSTEM_THREADING(ENABLED), whereas my app requires this.

Anyhow, no big deal, I can live with it.

I see @jerome’s workaround, yikes!

Cheers - @UMD

@mdma I saw a lot of gist on the github repo for threading in your next sprint. I did not see anything that addressed the inability to run a thread during listen mode.

To be clear, on my code below both myLoop and loop are halted during listen mode. You seemed to indicate this is unexpected. This functionality is important to me. Please let me know if it is on you agenda (or not).

Thanks for the great product and the help so far.

Jerome

#include "application.h"

//globals
bool pin_state = false;
bool pin_state2 = false;
int loop_cnt = 0;

SYSTEM_THREAD(ENABLED);
SYSTEM_MODE(MANUAL);

void myLoop()
{
  while(true)
  {
    if(pin_state == false) pin_state = true;
    else pin_state = false;

    digitalWrite(D3, pin_state);
    delay(1000);
  }
}

Thread myThread("myThread", myLoop);

void setup()
{
  pinMode(D4, OUTPUT);
  pinMode(D3, OUTPUT);
  Particle.connect();
}

void loop()
{
  if(loop_cnt > 120) WiFi.listen();
  if(pin_state2 == false) pin_state2 = true;
  else pin_state2 = false;
  loop_cnt++;
  digitalWrite(D4, pin_state2);
  delay(500);
}

Yes, the thread priorities were out of whack, so when the system thread enters the listening loop, which busy waits, it’s continually busy and doesn’t give the application thread any scheduling time.

Thanks and noted… Does that mean it is in this sprint? Not trying to be pushy, just trying to understand.

Jerome

Yes, we’re going to release 0.4.7 tomorrow.

2 Likes

Hi, apologies to drag up old skeletons, but can I have confirmation on whether loop() is meant to be running while the photon is in listening mode?

What I have:

SYSTEM_MODE(SEMI_AUTOMATIC);
STARTUP(prepare());
SYSTEM_THREAD(ENABLED);

Since we have a nice soft-ap webserver with customisable endpoints, that provides the opportunity for direct wifi of sorts. So, processing the loop() is important. I’m presuming it will neatly handle the various publish actions in the loop while its offline…