Manual system mode not functioning?

Am I misunderstanding manual mode or is it not functioning as advertised? When I call Spark.connect when wifi is connected, it stays breathing green and never even flashes cyan. It’s as though it never even tries to connect to the server.

According to the docs, the following code should work:

#include "application.h"
SYSTEM_MODE(MANUAL);

void setup()
{
    Serial.begin(115200);    
    
    WiFi.connect();
    Serial.print("Connecting to WiFi...");
    while (!WiFi.ready());
    Serial.println(" connected.");

    Spark.connect();
    Serial.print("Connecting to server...");
    while (!Spark.connected());
    Serial.println(" connected.");
}

void loop()
{
    Serial.println("loop");
}

Spark.connected() is never true.

The only reason that I’m not using automatic is that I want to control exactly when Spark.process is called during the loop. The server connection is purely for OTA updates and doesn’t need to run more than once every ten seconds.

@jnm2, in manual mode, you have to call Spark.process() regularly otherwise the “background” process will not run to create and maintain the cloud connection :smiley:

As @peekay123 pointed out in MANUAL mode you've to do it all manually, as the docs (you linked) state here
http://docs.spark.io/firmware/#system-modes-manual-mode

As a side note Spark.connect() does take care of WiFi.connect() too, if it's not already there.
The easiest way to try this mode is by using the provided sample in the docs above, and adapt it for your needs.
I guess your sample is only for demonstration of the "misbehaviour", since doing all that in setup() somehow defeats the purpose of manual mode :wink:

As for this

In this case you might have troubles getting the timing right to trigger your OTA update near enough to your one call of Spark.process() per 10sec. At least this is what I experience when doing things via Web IDE and having a loop() pushing close to the 10sec limit, even in automatic mode.

If you've got physical access to your Core, I'd go for a button to trigger a tight loop which calls Spark.process() - possibly with a timeout.


But if you want to get your code above running anyhow, apart from calling Spark.process() regularly, you might also want to try this little alteration

  ...
  while (!WiFi.ready())
    SPARK_WLAN_Loop();
  ...
  while (!Spark.connected())
    SPARK_WLAN_Loop();
  ...

And what does your serial monitor tell you, where your code got stuck before?

I had also tried putting Spark.process inside the loop that waits for Spark.connected(), but Spark.connected() never happens. The serial monitor shows that. Also, the WiFi does not connect without me putting the top code in. Try it; can you get it to work the way you expect?

Yep, at least last time I tried with my IoT-PS/2-Mouse project, but I can try to flash your code an tweak it till it works.

Meanwhile, could you try SPARK_WLAN_Loop()?


Tried it as suggested and it works.
I don’t understand why it’s always easier to argue that our suggestions won’t work instead of just trying them out :unamused:

4 Likes

Hey! I just got back and saw this. This is the first time I’m physically back with the Spark! This isn’t supposed to be an argument. :frowning:

I asked you to try the sample that I posted that is documented to work which doesn’t work. Maybe SPARK_WLAN_Loop should be included in the documentation?

I solved the problem for now by staying in automatic mode and running an inner while loop inside the loop method, and exiting the while loop every ten seconds. Works like a charm. I feel safer with documented functions.

Can you provide a link to that very documentation where you got that code from.
If we know where, we might be able to correct the docs.

I can't find it. I can only find this at the link you provided

SYSTEM_MODE(MANUAL);

void setup() {
  // This will run automatically
}

void loop() {
  if (buttonIsPressed()) {
    Spark.connect();
  }
  if (Spark.connected()) {
    Spark.process();
    doOtherStuff();
  }
}

And this works like documented.
As for SPARK_WLAN_Loop(), it is frequently used in connection with tight while() loops used in samples in the docs (OK, in connection with Serial.available(), but even so ;-)).

Have you tried the other suggestion to let Spark.connect() do the WiFi.connect() implicitly?

That is the documentation I was referring to. The only difference between the exact doc code and the code I posted seems to be that I was trying to connect inside setup instead of loop. That suggests that there is something going on behind the scenes with loop after all, even though it’s in manual mode, contrary to the documentation. Maybe it’s SPARK_WLAN_Loop, the missing link?

Yes, I did try that. Like I said, if you take the wifi lines out of my example, Spark.connect() doesn’t connect the wifi. I feel like it shouldn’t matter whether you are connecting from loop or from setup if you are in manual mode.

Ok, actually doing it in setup() instead of loop() is not the only difference.

One of which and the biggest troublemaker in this is your tight while() loop.
There is nothing spooky going on behind the scenes, it’s the timing that makes the difference.

And Spark.connect() does even call WiFi.on() and WiFi.connect() if required - apart from having it seen in the source and in the docs you can even try it with this stripped down version of your code that does work on my Core.

SYSTEM_MODE(MANUAL);

void setup()
{
    WiFi.off();   // now it's definetly off
    delay(1000);
    Serial.begin(115200);    

/*
    // this can be done, but there is no need
    // since it's done implicitly with Spark.connect()
    
    WiFi.connect();
    Serial.print("Connecting to WiFi...");
    while (!WiFi.ready())
      delay(100);
    Serial.println(" connected.");
*/
    Spark.connect();
    Serial.print("Connecting to server...");
    while (!Spark.connected())
        delay(100);     // give it some time
    Serial.println(" connected.");
}

void loop()
{
    Spark.process();
    delay(500);
}

So I’d guess it’s less the wrong documentation but rather misunderstanding and misinterpretation of symptoms.

2 Likes

You are right, of course, about the misinterpretation of symptoms. Thank you. So the only thing I was missing was the delay call. I would not have guessed that without documentation.

Now, in my mind, it doesn’t make sense that a delay is mandatory- does that mean delay is actually doing work besides just blocking?

No, not really.
It is true, that - at the moment - delays greater that 1000ms do implicitly call SPARK_WLAN_Loop(); and some other things to avoid loosing cloud connection, but that's not the case here.

Delay just gives the Core time to breathe, but maybe @mdma can explain a bit better why your tight while (!Spark.connected()); did prevent the Core to actually connect, while a little delay made it work.

Ah, individual delay() calls accumulate the delay, and when this is over 1000ms it will call the background loop. So even a delay of 1ms will eventually run the background loop.

Without the delay, the background loop is never run which is why the device couldn’t connect.

Using delays to run the background loop is a bit of a hack since the background loop execution is a side-affect and not the primary purpose of the function. It’s better instead to call the background loop directly:

while (!Spark.connected()) {
   SPARK_WLAN_Loop();
}

In the 0.4.x line of firmware, the background loop is part of the public API, via

Spark.process()

2 Likes

Some ideas…this simple code works fine at my first Pc, but it is not working at the other…seems ignoring SYSTEM_MODE(MANUAL); trying to connect at router…

#include “application.h”

SYSTEM_MODE(MANUAL);
byte mac[6];
/* executes once at startup */
void setup() {
Serial.begin(9600);
}

/* executes continuously after setup() runs */
void loop() {
LED_Off(LED_RGB);LED_On(LED_RGB);
LED_SetRGBColor(RGB_COLOR_RED);
LED_Off(LED_RGB);LED_On(LED_RGB);
LED_SetRGBColor(RGB_COLOR_BLUE);
LED_Off(LED_RGB);LED_On(LED_RGB);
LED_SetRGBColor(RGB_COLOR_RED);
}

or…seems ignoring make of application contaning the code.
Code has been build and uploaded…"${OUTPUT_PATH}"dfu-util -d 2b04:d006 -a 0 -s 0x80a0000:leave -D C:\photon043_1\firmware-photon_043\build\target\user-part\platform-6-m\Blank.bin

Hi @yianmar, The unit that isn’t running the code, have you already connected it to the cloud? If not, please install the latest system firmware, since that’s required to run applications.

With that installed, you should be up and running :smile:

Already done, but not working.

I am Not sure about the uploading procedure
is it?
dfu-util -d 2b04:d006 -a 0 -s 0x8020000 -D system-part1-0.4.3-photon.bin
dfu-util -d 2b04:d006 -a 0 -s 0x8060000:leave -D system-part2-0.4.3-photon.bin
dfu-util -d 2b04:d006 -a 0 -s 0x80a0000:leave -D Blank.bin

even if it is working at my first PC, I wonder what could interacts beyond this.

Try adding some delay() calls between changing the LED to make the changes visible. (And please consider using the RGB led library.)

Those DFU commands are correct. (You don’t need :leave in the second command, but it will do no harm other than you have to put the photon back in DFU mode to flash the application file.)

thanks for your time spend to help me.
At my first Pc I do not have this library, but works fine.
And something more, I am working locally using Netbeans, how I can use the library?

It’s built into the system firmware. All you need is to add:

void loop()
{
    RGB.control(true);
    RGB.color(RGB_COLOR_RED);
    delay(500);
    RGB.color(RGB_COLOR_BLUE);
    delay(500);
}

Since it’s working on your first device I know this isn’t a fix for your problem, but it’s better to code using the RGB support rather than the low-level LED functions.