Create time out for Spark.connect()?

Thanks @ScruffR, just as I thought. So running SEMI_AUTOMATIC seems like the best scenario for user code controlling the Cloud connection. :smiley:

2 Likes

Thanks @ScruffR and @peekay123!

So what it seems like to me is this problem is solved.

If you would like to try connecting without blocking, put the Spark Core in SEMI_AUTOMATIC mode and call Spark.connect() . If you want to cancel it, just wait for millis() or the like and call Spark.disconnect() and/or Wifi.off() .

Did I get it right?

I hope the docs will be updated if there are any inconsistencies.

1 Like

Can we finish this thread with some code that actually compiles.

So should this work? Reminder that I do not have a core I can check this on just yet. If someone could try it that would be useful.

SYSTEM_MODE(SEMI_AUTOMATIC);

int myConnect=0;

void setup() {
   
   pinMode(D7, OUTPUT);  
   Spark.connect();
   
   delay(5000);
   delay(5000);
   delay(5000);
   delay(5000);
   
   if (WiFi.ready()){   
        myConnect = 1;   // means wifi got connected
    } else {
        Spark.disconnect(); 
        WiFi.off();
        myConnect =2;   // means no wifi
        digitalWrite(D7,HIGH);     // D7 high says no wifi but spark working fine.
      }
}

void loop() {
    
    // put generic code here
    
    if (myConnect == 1){   // only put code here that needs wifi
        digitalWrite(D7,HIGH);     // fast blink says Wifi connected
        delay(50);
        digitalWrite(D7,LOW); 
        delay(50);        
    }
    
    
    if (myConnect == 2){   // only put code here that is fine with no wifi

    }
}

@rocksetta, this should work, but there are some things to improve.

  • Why use multiple consecutive delay() statements instead of one big one - even Arduino would allow up to 65535 and the Core 2^32 - 1
  • Have you had a look at the “soft delay”, I’ve used in my sample code? This is the prefered way to do long delays. This way you could keep the delays as short as needed, since you can check for state changes inside the loop.
  • Do you actually mean to let the cloud on, if it’s there? This didn’t seem so in the OP.
  • Are you intending to have more than two states for myConnect - if not I’d go for 0/1 with preset 0 and if(myConnect) ... else
  1. I thought delays over 20 seconds messed up calls to spark.process(), but if not it isn’t a big deal.

  2. Good idea with the soft delays. My code took about 6 minutes to write so it may have a few issues. I still haven’t got confirmation if the code works as my Core is busy with another project. That would be very helpful.

  3. If the core connects to the Cloud, great let it continue. Trying to make the code as simple as possible so that if someone wants to change it they can.

  4. The zero “0” state was for when you do not know yet if there is a connection or not. 1 = Good Cloud connection, 2 = No Cloud connection. Really doesn’t matter either way, I originally wanted to make the myConnect variable boolean, but sometimes when debugging code integers are just easier to work with.

  1. delay() was adapted in a quite early stage to internally call Spark.process() once every second of a long delay.

  2. My code is confirmed to work. Just strip away the interrupt part - since it’s not needed - and put in what you want :wink:

  3. :+1:

  4. You can still print booleans as integers for debugging and I can’t see any real difference between “no cloud yet” (0) and “no cloud later” (2) :wink:

  1. Good to know
  2. Please show your new code as the interrupt and volatile variable show up in about 5 places, and all of this is supposed to be helping beginners.
  3. Actually 0, 1, 2 is needed since 0 and 1 does not prove Wifi has been disconnected and could show a false positive. But seriously we just want working code, let the academics stress about correctness.

Anyway, got tired of waiting for someone to test my code so I thought I would include it in my Rover. Here is the slightly changed code that works:
With Wifi in range, it connects quickly breaths cyan, waits 20 seconds and then flashes D7 fast to show Wifi Cloud connectivity.
Without Wifi nearby it flashes green for 20 seconds then shows solid D7 HIGH and strangely breaths cyan??

Here is the code:

SYSTEM_MODE(SEMI_AUTOMATIC);

int myConnect = 0;      // means neither connected or disconnected yet

void setup() {

   pinMode(D7, OUTPUT);  
   Spark.connect();             // non-blocking attempt to connect to Wifi

   delay(20000);   // wait 20 seconds at startup


   if (WiFi.ready()){   
        myConnect = 1;   // means wifi got connected
    } else {
        Spark.disconnect(); 
        WiFi.off();
        myConnect =2;   // means no wifi cloud connectivity
        digitalWrite(D7,HIGH);     // D7 high says no wifi but spark working fine.
      }
}

void loop() {

    // put your generic code here that works if Wifi connected or not

    if (myConnect == 1){   // only put code here that needs wifi
    
        digitalWrite(D7,HIGH);     // fast blink says Wifi connected
        delay(50);
        digitalWrite(D7,LOW); 
        delay(50);    
        
        // put your code here that needs wifi Cloud connectivity
    }


    if (myConnect == 2){   // only put code here that is fine with no wifi
    
      // put your code here that runs without Wifi Cloud connectivity
      // LED D7 should be HIGH to prove Wifi has been disconnected

    }
}

You can try using this:

void setup(){
  pinMode(led,OUTPUT);
  digitalWrite(led,HIGH);
}

void loop(){
    if(WiFi.ready() && !Spark.connected()){
      Spark.connect();
    }
    else
      WiFi.connect();
  }

  digitalWrite(led,!digitalRead(led));
  delay(1000);
}
2 Likes

Actually not quite :wink:
All of this shoud be helping you to get up to speed and being an advocate of the paradigm to lead people to knowledge rather than chewing it up and pre-thinking it for them, I'd trust you'll be able to work it out :+1:

As the idiomatic saying about teaching how to fish is (most the time) better than handing a fish - as a physics teacher, I'd guess you'd seen from experience, that things your pupils had to work for stuck better in their mind than what was merely presented to them.

I disagree, the Hello World program (which is what we are making) is made to get students started so that they can put time into their own projects. But I am too busy to argue. I will just teach my method and ignore yours. :wink:

@rocksetta, @ScruffR you actually are both vociferously agreeing! You both agree that teaching is important. To that end, both of you champion different but great approaches. Thanks to both of you for taking the time to help, teach and support. :clap:

4 Likes

Actually we are both ridiculous basing our entire argument on SEMI_AUTOMATIC mode having a blocking call to Wifi. Since it is not blocking the code can be much smarter. This new code shows D7 HIGH when not connected. As soon as the core is connected D7 blinks fast, then as you lose connectivity D7 goes HIGH again, but when Wifi is available and connected D7 goes back to blinking.

The docs were confusing but the Spark Core works great with basically no user help. Thanks @kennethlimcp your code was the key,

P.S. @kennethlimcp nice way to blink D7. digitalWrite(D7,!digitalRead(D7));

SYSTEM_MODE(SEMI_AUTOMATIC);

int myConnect = 0;      // means neither connected or disconnected yet

void setup() {

   pinMode(D7, OUTPUT);  
   Spark.connect();
}

void loop() {

    // put your generic code here that works if Wifi connected or not

    if (Spark.connected()){   // only put code here that needs wifi
    
        digitalWrite(D7,HIGH);     // fast blink says Wifi connected
        delay(50);
        digitalWrite(D7,LOW); 
        delay(50);    
        
        // put your code here that needs wifi Cloud connectivity
        
    } else {   // only put code here that is fine with no wifi
       digitalWrite(D7,HIGH);     // fast blink says Wifi connected
      // put your code here that runs without Wifi Cloud connectivity
      // LED D7 should be HIGH to prove Wifi has been disconnected

    }
}
1 Like

I think I finally found a working solution for the blocking Spark.connect call. I’ll post some code later but anyway my idea is the following. I found out that spark.connect would lock up my code when I successfully connected to the WiFi but internet wasn’t working. So what I did before calling Spark.connect was using WiFi.ping to check if I could reach the Spark cloud and if I would get a positive result then I knew I had internet connectivity and I could safely call Spark.connect()… This gives me the ability to have the flexibility I needed for my project and handle the connection in a very safe way without having a locked up core… Hopefully this is helpful to some of you :slight_smile:

3 Likes

About 6 months ago when I first found out about the spark core, a 10 year Arduino veteran said that the spark core was fine until your Wifi was crappy, then the Core became a brick. Whereas his Arduino just works as long as it has power. Until yesterday what he said was basically true. With the code below, the spark core works fine with or without Wifi.

Who is in charge of the DOCS? Please change the following, and include the code as the example instead of the ButtonPressed example that is given for Semi-automatic mode.

Semi-automatic mode

When the user calls Spark.connect(), the user code will be blocked, and the Core will attempt to negotiate a connection. This connection will block until either the Core connects to the Cloud or an interrupt is fired that calls Spark.disconnect().

The above statement is not correct. Please replace the example code with the following

SYSTEM_MODE(SEMI_AUTOMATIC);


void setup() {
   Spark.connect();   // do not miss this line or you can't flash more code
   
   
}

void loop() {


}

The above code flashes green, then connects and breaths cyan. If it does not connect then it breaths blue, as soon as Wifi is nearby it will flash green and then connect and breath cyan. Fully automatic, fully awesome. You either have a cloud connected device or you have something as solid as a regular Arduino.

1 Like

@rocksetta good conclusion for this thread :+1:

Only the above statement was (sort of) true till Oct. 2014 :wink:

As for the doc update, I've already contributed some input for this issue - you can add more to stress the importance :wink:

Just a final note here, I often put a short delay at the start of using semi-automatic or for that mater fully automatic mode. The delay is so that I can re-flash more code if the present code has an immediate problem. The short delay is nothing compared to the pain of resetting your Core and potentially having to use DFU mode (which scares me).

This is only for the Core as the Photon has a new safeguard against this issue.

SYSTEM_MODE(SEMI_AUTOMATIC);

void setup() {
pinMode(D7, OUTPUT);
digitalWrite(D7, HIGH);
Spark.connect(); // do not miss this line or you can't flash more code
delay(25000);
// wait 25 seconds giving time to reflash the code if you screw up
// strangely 20 seconds is not enough
digitalWrite(D7, LOW);

}
void loop() {
}

I’m not sure if this would be of use to anyone since I am a pretty novice programmer, but I’ve gleaned so much from this thread that I would like to contribute back a tiny bit if possible.

I haven’t tested this on my Core but it runs great on my Photon. I call this code if the ISR is hit as well as in the setup function:

Serial.println(".........Connecting......");
Spark.connect();

unsigned long now_millis = millis();
while(millis() - now_millis < 20000){
    Spark.process();
    if (Spark.connected()) break;
}


if (Spark.connected()) {
    Serial.println("Connection Established");
} else {
    Serial.println(".........Turning off WiFi...");
    Serial.println("Continuing Program Disconnected");
    WiFi.off();
}

I did find that if I did not use WiFi.off(); and used Spark.disconnect() instead that the Photon would keep flashing cyan quickly and never connect, even if the wifi signal came back. Instead I opted to use WiFi.on(); when the ISR was triggered and start the whole connection process, shown above, over again. Any thoughts?

1 Like

With a Photon, does the above (and similar statements by @rocksetta, @ScruffR) holds true? In a small test I did it seems to me it does not. With the code below, if I disconnect my router, the D7 pin does not blink anymore...

SYSTEM_MODE(SEMI_AUTOMATIC);
void setup() {
   pinMode(D7, OUTPUT);
   Spark.connect();
}
void loop() {
if (Spark.connected()){
  digitalWrite(D7, true);
  delay(500);
  digitalWrite(D7, false);
  delay(500);
}else{
  digitalWrite(D7, true);
  delay(100);
  digitalWrite(D7, false);
  delay(100);
}
}

Good question! :smile: Alas, presently WiFi.connect() is blocking on the photon. I have multithreading working on the photon, plan to release this in a PR this week. With multithreading, the application code is never blocked by the system.

7 Likes