Upgraded to 0.7.0, WiFi does not come on in SEMI_AUTOMATIC mode

Updated Photon from 0.6.3 firmware to 0.7.0 firmware. Compiled code for 0.7.0, and WiFi does not come on, light just sits breathing white. Change 0.7.0 compile option back to 0.6.3, load new code and that runs fine, as it did before. Looks like something is broken when selecting 0.7.0 compile. I can get the 0.7.0 compile to work by commenting out “SYSTEM_MODE(SEMI_AUTOMATIC)”.

How I turn WiFi on is:

while (Particle.connected() == false) {
  Particle.connect();
}

as I said, worked just fine when compiled for 0.6.3.

Is this an issue with my code (that was working fine), or with the new release?

Austin

I think there has been some change as to when (or if) Particle.connect() is blocking. I have to say that I’m confused about what the current state of affairs is with this issue. Hopefully, someone will clarify this. So, if in the new version, Particle.connect() no longer blocks, then the problem you’re seeing is due to the fact that you keep calling Particle.connect() over and over, not giving it a chance to complete.

1 Like

Hi Ric,

Thanks for the reply. I think whether it blocks or not, it would turn WiFi on and connect at some point. But…you got my little doggie mind thinking. I bet the 0.7.0 particle.connect does not turn WiFi on. I will turn WiFi on first, then issue the particle connect and see if that works.

Austin

So…I seem to have fixed it. Looks like two things changed. One, Particle.connect() does not do a WiFi.connect. I added this before I do a Particle.connect:

  WiFi.connect() ;
  while (WiFi.ready() == FALSE) {} // wait for connection status to be OK to use

Second is Particle.connected() does not seem to work, as in, it does not return something other than FALSE when it’s connected. I know this because this loop:

while (Particle.connected() == FALSE) {
  Particle.connect() ;
}

sits forever (which it did not do in the 0.6.3 compiles). It appears that Particle.connect() is blocking, so I removed the while loop and it works fine.

If they are going to change behavior of calls between revisions they need to document these changes AND let people know. Otherwise, it’s a guessing game when code that worked now does not.

Austin

I’ll have to test, but I’m pretty sure Particle.connect() does still perform WiFi.connect() implicitly.
In previous system versions SYSTEM_MODE(SEMI_AUTOMATIC) seemd to have the WiFi module on by default, which (IMO) was not as intended and has now been “fixed”.
Hence WiFi.on() should be issued explicitly by user code whenever WiFi or cloud connection is needed.


Update:
I have now tested the behaviour with a Photon 0.7.0 and this is what I found

  • SYSTEM_MODE(SEMI_AUTOMATIC) does startup with WiFi off (breathing white.
  • WiFi.on() does switch the module on (breathing blue)
  • WiFi.connect() w/o previous WiFi.on() does connect to WiFi (breathing green)
  • Particle.connect() w/o WiFi.on() and WiFi.connect() does connect to the cloud (breathing cyan)

In so far, I can’t reproduce your issue.
This is what my Photon reports with particle serial inspect

PS C:\Particle\Photon> particle serial inspect
Platform: 6 - Photon
Modules
  Bootloader module #0 - version 101, main location, 16384 bytes max size
    Integrity: PASS
    Address Range: PASS
    Platform: PASS
    Dependencies: PASS
  System module #1 - version 207, main location, 262144 bytes max size
    Integrity: PASS
    Address Range: PASS
    Platform: PASS
    Dependencies: PASS
  System module #2 - version 207, main location, 262144 bytes max size
    Integrity: PASS
    Address Range: PASS
    Platform: PASS
    Dependencies: PASS
      System module #1 - version 207
      Bootloader module #0 - version 101
  User module #1 - version 5, main location, 131072 bytes max size
    UUID: 35...4B
    Integrity: PASS
    Address Range: PASS
    Platform: PASS
    Dependencies: PASS
      System module #2 - version 207
  empty - factory location, 131072 bytes max size

That’s my test code, only ever (n)one line of code active in setup()

SYSTEM_MODE(SEMI_AUTOMATIC)

void setup() {
  //WiFi.on();
  //WiFi.connect();
  Particle.connect();
}

void loop() {
    Serial.print('.');
    delay(1000);
}
1 Like

Hi ScruffR,

Thank you for the reply. When compiling using 0.6.3 (and the firmware updated to 0.7.0), this code worked perfectly:

SYSTEM_MODE(SEMI_AUTOMATIC)

loop() {

Particle.connect() ;

System.sleep(SLEEP_MODE_DEEP, sleep_delay) ;

}

But just breaths white when I compile it with 0.7.0 (with 0.7.0 firmware). In 0.7.0 I need to do the following:

// turn WiFi on.
WiFi.connect() ;
while (WiFi.ready() == FALSE) {} // wait for connection status to be OK to use

// bring up cloud.
Particle.connect() ;

Which matches what you said “Particle.connect() w/o WiFi.on() and WiFi.connect() does connect to the cloud (breathing cyan)”. So, I believe you did replicate my issue, unless you meant to have parenthesis around “w/o (WiFi.on() and WiFi.connect())” :slight_smile:

Even at that, there is still some issue. It didn’t run overnight (in fact, not even for 15 minutes), and I have had this same code (less the updates for 0.7.0 as outlined above) running for months on multiple devices, without a single issue. I am guessing if I add while loops to WiFi.connect() and Particle.connect() that would solve the problem, as it may not always do one of those with only one call (may timeout), though with Particle.connected() not working as it did before, using that will not work.

I can also guarantee that in 0.6.3, WiFi was off after System.sleep. No lights, and I am monitoring power consumption on all my modules, and the consumption after sleep was less than 1mA. WiFi could not be on with that low a power consumption.

Are the changes/updates between 0.6.3 and 0.7.0 documented anywhere? Say, release notes?

Best Regards,

Austin

"w/o X and Y" was meant as without any of the two. Otherwise I'd have said "without X but with Y".
Sorry for the confusion.

But I also stated with the test code

Meaning: either none (resulting in breathing white) or only one resulting in the colours mentioned

What do you mean by this?

Does this imply that after System.sleep(SLEEP_MODE_DEEP, sleep_delay) but before the device waking you see the LED on and/or have a current consumption >1mA?

BTW, with this code I see exactly what I expect.

SYSTEM_MODE(SEMI_AUTOMATIC)
int sleep_delay = 30;

void setup() {
  //WiFi.on();
  //WiFi.connect();
  Particle.connect();
}

void loop() {
  delay(1000);
  System.sleep(SLEEP_MODE_DEEP, sleep_delay);
}

The device comes to life, short white, blinks green, blinks cyan, flashes cyan, breathes cyan for a second, goes back to sleep (no lights on at all), wakes after 30sec, rinse, repeat.
The delay(1000) is not required, but only there to have time to see the breathing.

Yes, of course

You need to follow the links provided for the individual RC versions that are gone into 0.7.0

No. It means that with power consumption less than 1mA, there is no chance the WiFi was on until I specifically turned it on. You had said:

I have no idea why you can't replicate the issue I am seeing, but the problem is real here. There clearly is some difference between our systems.

My desktop IDE came up with compiling for 0.7.0 on its' own. I had never selected what firmware to compile for before, and magically clicking on the 0.7.0 gave me the option to change the compile back to 0.6.3. That there was a new release was news to me, and it may be a good idea for Particle to message people that there is a new release available, especially if the tools are going to change things on their own (which they should not IMO). I,silly me, updated the firmware on the development board after noticing the 0.7.0 in the IDE. If I had thought about it some, and know better now, would have made a new branch for 0.7.0, and likely held off updating to 0.7.0 until next release. No blood, just a good bump.

Good news is I have this back working, but not sure if it is reliable. Only time will tell... I'll check GitHub for release notes, thanks.

Best Regards,

Austin

The Particle Firmware Update Thread I linked above is exactly that. Each new release will be announced there and you can subscribe to be notified whenever a new post is added.
The tools don't really change things unsolicited on their own. You can select your a distinct version and the IDE will stick to that or you instruct the IDE to keep going with the default release, and then the IDE will just do that.

It's a bit of a double edge sword. We have been putting out 0.7.0-rc.x releases since mid last year, and it sounds like maybe you haven't tried them? I wonder how we can better inform you of these pre-releases beyond the Particle Firmware Updates Thread and the Particle Tools Changelog (<- definitely subscribe to this one if not to both!)

If we don't create the next default version of firmware, it's very possible developers would be stuck on old buggy system firmware and never realize there are updates. It's not our intention to make breaking changes, but they can happen, and sometimes not because we don't try to keep them from happening. There are lots of different ways to write user firmware and there may be an edge case that just doesn't work as expected between changes.

You can pin your build target to a version so it won't update automatically, and if you leave it on default it will get updates when the roll out. If you have a product, ideally you would be testing pre-releases as they come out to be better prepared for the default release, which you can also make a controlled rollout. For development, usually it's ok to have some stumbling points because you can revert if something goes wrong. If you have remote development devices, I would recommend testing locally first before updating remotely.


Back to your issue, it looks like perhaps this is a case of using an API in a way that appeared to be the expected behavior, and when we fixed the expected behavior to what we originally intended it caused your firmware not to respond the way you wanted.

When adding while loops without a timeout to a single-threaded application, it's a good idea to add Particle.process().

while (Particle.connected() == false) {
  Particle.connect();
  Particle.process(); // I suspect adding this would fix it for your case
}

It's also important to note if Particle.connect() blocked until it could connect (and it could not connect for some reason), with your original code it would hang out there indefinitely.

Another way

void loop() {
  if (Particle.connected() == false) {
    Particle.connect();
  }

  if (Particle.connected()) {
    // run my cloud connected code
  }

  // run my non-cloud connected code
}

There are lots of ways to write this, and many more ways to add retries, timeouts, etc.. to the schema.

3 Likes

@BDub

Could you guys maybe publish the specification document describing how this is all intended to work? I had a pretty rough time parsing this out myself, eventually just going with Particle.connect() and Particle.sleep(3800) to activate and deactivate wifi because it was the only thing that worked completely and reliably (after much trial and error) for me. The documentation is good quality but it is nowhere near complete on detailed issues like this.

Clearly many of the connect and disconnect functions overlap or do similar things and it is not clear at all which one should be used for which situation. Whoever writes this stuff needs to understand that a reader does not already have an internal model of the connection state machine. Finer points like that IMO are not being communicated and are a nightmare to learn by going through the code on GitHub.

Questions that need to be explicitly answered in the documentation:

  • What does the Cloud state machine look like? How do you (from user code) determine which state it is in? What can cause this to change?
  • What does the WiFi (or 3G) state machine look like? How do you (from user code) determine which state that is in? What can cause this to change?
  • What do each of the network calls do to each state machine? Does Particle.connect() call both WiFi.on() and connect to the cloud? Does WiFi.connect() also call WiFi.on()? Which ones are redundant and what do they do explicitly.
  • How do the system events interact with this and inform the user of these state changes? (this is slightly more self-evident, but it needs to be linked to the discussion of the state machines)

Some of this state is hinted at in the description of WiFi.off() vs. Particle.disconnect() and in the section about system events, but IMO that is not an adequate description of what goes on behind the scenes to be able to grok it.

I have been a regular user for about six months and am about to launch. Please take this as an attempt at constructive criticism.. this has been one of the major pain points of building a functional product.

4 Likes

I’ll definitely bring this up internally. Thanks for the feedback!

3 Likes