No reconnection to the cloud after sleep

@gotopcs Sorry - not sure what I was thinking. I meant just call Spark.connect() as it will call the rest anyway. There is no Cloud.connect();

I corrected my earlier post :smile:

I tried Spark.connect() instead of all the WiFi commands. Sequence is now:
breathing cyan. Send S0 command to switch WiFi off. LED changes to breathing white as soon as Wifi is off. Delay 30 seconds. Spark.connect() is the next command, followed by a 30 second delay. LED continues breathing white forever until reset is pressed.

Now this IS odd. Just measured the current consumption of the beast and it seems to stay with WiFi off even though the WiFi.on() command precedes the Spark.connect() command. Tried again but with the LED under my control - it went through the red - green - blue - yellow sequence, BUT, the current consumption indicated that the WiFi was OFF and didnā€™t come on again!!! How can it respond with true WiFi.ready and true Spark.connected? Something wrong here. Iā€™ll paste the code snippet again to show the actual sequence Iā€™m using.

if (command.startsWith("S"))
{
    int loopout = 60;
    // red LED while WiFi off, then back to whatever
    RGB.color(120, 0, 0);
    RGB.brightness(120);
    WiFi.off();         // reduce power
    solarDelay(300);    // delay 1/2 minute
    RGB.color(0, 120, 0);
    RGB.brightness(120);
    WiFi.on();        //   wifi back on
    //Spark.connect();
    solarDelay(20);    // delay 2 secs
    // connect to local wireless network
    do 
    {
        WiFi.connect();
        if (loopout > 0)
        {
            solarDelay(10);       // delay 1 second, max 1 minute
            if (WiFi.ready() == true)
            {
                break;
            }  
            loopout = loopout - 1;
        }
    }
    while  (WiFi.ready() == false);        // wait until IP address acquired
    RGB.color(0, 0, 120);
    RGB.brightness(120);
    solarDelay(20);    // delay 2 secs
    if (Spark.connected() == false) 
    {
        Spark.connect();
    } 
    solarDelay(300);    // delay 30 secs
    if (Spark.connected() == true) 
    {
    RGB.color(120, 120, 0);
    RGB.brightness(120);
    }
    solarDelay(60);    // delay 6 secs
    
    sprintf(publishString,"Connected to WLAN after %u seconds",loopout);
    Spark.publish("Data1",publishString);
}

@gotopcs Here is a code segment that I use to start the WiFi

//#define ENABLE_SPARK_CLOUD
int _wifistate;
enum {
    WIFI_OFF			= (1),
    WIFI_CONNECTING		= (2),
    WIFI_READY			= (3)
};

int startWiFi() {
    // startup wifi
    switch (_wifistate) {
        case WIFI_OFF:
            WiFi.on();            // Turn on the WiFi radio
            WiFi.connect();       // Start WiFi connection
            _wifistate = WIFI_CONNECTING;
            break;
	case WIFI_CONNECTING:
            // Wait for WiFi DHCP to get setup
            if (!WiFi.connecting() && WiFi.ready())
		_wifistate = WIFI_READY;
	    break;
    }

    return _wifistate;
}

You actually need to return from your loop for some of the WiFi functions to work correctly. You may need to change your logic to a state machine to get this to work correctly.

You can do something like -

if (start_WiFi() == WIFI_READY && command.startsWith("S")) {

Make sure when ever you turn off the WiFi you set

_wifi_state = WIFI_OFF;

OK, but why is that code necessary at all? Why is it necessary to write a wrapper function for WiFi.on() and WiFi.connect()? Is it your experience that WiFi.ready() can ever return true if WiFi.connecting() returns true? And, if so, would this not demonstrate some kind of bug which needs reporting? And some documentation which needs fixing? Too many questions? :smile:

I thought WiFi.connect() calls WiFi.on() if necessary. And that establishing the WiFi connection is blocking - it keeps trying. Can you not replace all of your code with

if( ! Wifi.ready())
  WiFi.connect();

or possibly, if Iā€™m wrong about the blocking,

if( ! Wifi.ready())
  WiFi.connect();
while( ! WiFi.ready())
  delay(100);

and instead of testing your _wifistate you simply test WiFi.ready()?

I ask because I wonder if this is another magic incantation I need store in the armoury of spells for getting things to work on Spark. In other words, I would prefer the long-winded way you describe to be superstition along the lines of the weird way my mother stirs her tea - it may work but it is unnecessary and is not found in the directions on the tea caddy.

Similarly, all that ought be necessary to get connected to the Cloud is this:

if( ! Spark.connected())
  Spark.connect();
// following while possibly unnecessary as Spark.connect() may be blocking
while( ! Spark.connected())
  delay(100);

Because, as has already been pointed out (I think), Spark.connect() will cause the radio to be turned on and the WiFi connection to be established.

Any assertions made above are meant to be understood as questions. It would be good were someone to confirm/deny these assumptions, or were the docs fleshed out a little to make some of this just a little plainer.

Response to old post about pings not working any more: My cores are up to date. They respond to pings. They are in MANUAL mode and not connected to the Cloud but to the WiFi only.

Just checked mine again and none respond to ping requests with the cloud on (i.e. automatic mode). All of my cores are at TI patch level 1.28; it can be difficult to do the TI deep update patch over the airā€“Spark CLI or dfu-util are very easy though. Using the cloud consumes one of the TCP sockets in the core, but otherwise I believe the setup is the same.

I will try to check manual mode.

2 Likes

Well - all I can say is there is some 'magic' that happens outside of the main loop. I have spent some time diving into the core firmware to try and understand what's going on but probably not enough time to try and fix it. (I think I would need to debug the Spark using JTAG - I have the equipment, just not taken the time to setup and get working)

In my experience trying to bring up the network connection from a dead off to working can not happen within one pass of the user loop. That is why I created a state machine to perform the task. (Also blocking and waiting for DHCP negotiation and calling Spark.process() seems like poor application design.)

I have found cases where WiFi.ready() will return true while you don't have a connection you can use, so I added !WiFi.connecting() I could have dug in a bit more to understand it better and maybe discovered it's not needed, but I moved on to address other problems.

I posted a networking test app here - It will let you manually bring up and down things such as WiFi, Cloud and test DNS. It's also a great start as a template to try out your own stuff.

Let me see if I can address another comment you made -

Funny thing about Spark.connect() it likes to manage all of the network operations, for example if you fun SYSTEM_MODE(MANUAL) and manually bring up the WiFi in your setup (which can be done) and then manually try and start the cloud connection with Spark.connect() It blocks and hangs the core. However if you don't bring up the WiFi and just call Spark.connect() in setup everything is happy. And - yes, Spark.connect() blocks until the Cloud connection is up. I've also found is not entirely accurate, you can call Spark.connect() and then immediately try and use a Cloud function such as Spark.syncTime() however it not always successful. So Spark.connect() much like WiFi.ready() are not always 100% accurate representations of the state of the service. The services will be available sometime after, just not immediately 100% of the time.

One of the attractions of programming is that itā€™s not like baking a souffle - sometimes it rises and sometimes it flops and you donā€™t know why. I cannot believe that programming the Spark Core should be as flaky as you experience. Oh, and youā€™re not alone, of course. But I am not having to program in quite the round-the-houses style you seem to need to.

So, as a first step, how is it supposed to work? Thatā€™s when I refer to the documentation. Others, of course, refer to the underlying code.

How about, instead of the definitive docs, some sample programs written by those in the know, that do simple stuff tasks which just work and which, should they not work, would demonstrate a bug? E.g. (a) how is one supposed to bring up the Cloud in MANUAL mode? (b) How is one supposed to turn off the WiFi? Ā© And resurrect it? More generally (d) Is one supposed to wait a while or test after these calls, or do the provided calls do what they say they do, blocking until the task is complete?

I am hoping the answers are (a) Spark.connect(), (b) WiFi.off() and Ā© Wifi.connect(). And (d) something definitive.

OK I just got a chance to check this and a core with deep update (TI patch level 1.28) does not answer pings when booted in automatic mode, but does when booted in manual mode even when you transition back to cloud on. Very strange.

Maybe @mdma can shed some light on this. There is not a driver event for receiving a ping and to the best of my knowledge, ping response is handled completely inside the TI part.

1 Like

I hope I havenā€™t opened too big a can of worms here, if I have, I apologise. The reason for this post is that I had a wee disaster with my Spark core - due to dropping a metallic object in the area, the 12V supply shorted to the Vin pin. Smoke was emitted. I hoped the 5V to 3.3V DC-DC converter had died. I removed same and supplied 3.3V from a DC power supply. No activity from the core, so it is declared dead. I ordered a Photon replacement, so will be off the air for a while until it is delivered and ā€œclaimedā€. Thankyou all for your contributions to my post.
Merry Christmas one and all!

1 Like

See, as an example of one of these programs: Yet another TCPClient example (but this one works!) - Tutorials - Particle

In the recent investigation where you discovered that UDP would work in MANUAL mode if first you pinged something you may remember I suggested that there is a difference between AUTOMATIC and MANUAL modes in the way the Core initialises the TI chip. I still think so and I think this latest aberration reinforces the point. I think several issues might be resolved by investigating what differs in the Coreā€™s initialisation of TI chip in each of the system modes. Someone was going to look at that.

I can say for certain that there is no difference in how the CC3k is initialized for the different modes, since mode-specific behaviour happens only after startup. Pre-startup code only sets flags to indicate the cloud connection after startup. So any difference in behavior has to be internal to the TI chip - possibly timing or resource-usage dependent.

There is some ping handling code in the application layer, so we can at least debug to see if the ping responses are being sent from the cc3000.

1 Like

I think you are seeing the ping sending and reporting code that I put in. I don't know of any ping response code in the driver, but I could be wrong.

Hehe ok, I donā€™t know - we might be talking about the same thing, which code to you mean exactly? Iā€™m thinking of the callback from the cc3k here:

https://github.com/spark/firmware/blob/master/src/spark_wlan.cpp#L317-L321

(I forgot exactly where it was, itā€™s not in the driver - but in the app layer.)

I know nothing about the specifics but by Occamā€™s razor this seems flawed: If there is no difference then why does the TI chip behave differently. The TI chip does not know what mode youā€™re in but in one mode it echos the ping yet in the other it does not.

OK, as I said, I know nothing: if itā€™s not in the initialisation, where is the difference? The Spark Core is not being wilful.

OK, but all that is highlighted by this obviously true remark is that you and I are using "initialise" differently. Something is done (or not done) to the TI chip by the Core when it runs in AUTOMATIC mode which it does not do (or does do) when it runs in MANUAL mode.

Hi @mdma

Yes, I wrote the above and it is for reporting when sending pings if you got success or failure.