Status LED flashing blue?

I’m getting a Blue flash of death now. I understand this is supposed to indicate that the core is waiting for WiFi credentials in smart-config mode, but this happens randomly, about once a week. Last night I noticed one core that was running for about the last 10 days on its own network was BFOD this morning, but so was a core i’d left powered on on my desk, which is connected to a different network, running different code. Was it just concidence? The only thing in common, other than sharing the same mains power in my house, is that they are both connected to the spark cloud.

1 Like

Yep, happened to me just now. Waited for 10 minutes and had to reset the device to get it running again.

Edit : Sorry, please ignore my post. I was getting a Green Flash. However it happened again for 40 min this time before reset.

@dermotos Have you continued to see this problem? We’re getting a few more people recently who are reporting this bug. No immediate obvious culprits, but if it continues to be an issue for people, I’ll request to add more of our developer resources to fixing it during our next sprint planning meeting.

1 Like

@will, I am seeing this problem on one of two Cores.
Both are running the same firmware and are placed on one breadboard with one power supply and both connected to the same network.
It’s always the same Core that goes into blue flashing (after a day or so), the other one runs stable for more than a week now.

Hmm that is weird. I’ll be sure to bring it up tomorrow morning for prioritization at our Sprint Planning meeting for the next two weeks. Thanks for raising this issue and helping us characterize it! Will provide feedback to this channel when I have an update.

Long live :spark:.

Yes, its happening a lot more often now (~24 hours).

What’s your code? and firmware 1 or 2?

Would like to help replicate it :smiley:

I haven’t been keeping up to date with different firmwares for about 2 weeks. I’ve just updated to the latest firmware via the cloud IDE, so will see how it goes and report back.

Info: The sketch runs 24/7 controlling my blinds. It runs on a dedicated WiFi network with no other devices. This is created by an Airport Extreme guest network feature. Pretty solid internet connection in my home, never have any issues. ~15Mb/sec

What’s your factory reset firmware?

One way to know is, when you are in listening mode, and using USB, does it ask you for wifi security type?

Or your date of purchase would give and idea.

Would be nice to see your code and what caused it

This happened again last night, after being stable 24/7 for a few weeks. @kennethlimcp I had this core before Christmas, one of the first batches. The USB WiFi setup doesn’t ask what type of security i’m using though.

Here’s the code that’s running on it. It controls 4 blind motors and is controlled by an app that puts the blinds in one of 9 states (center two blinds open, outer ones closed; blinds half open, etc…).

I know, it’s due a tidy up!. The TCP/UDP stuff isn’t being used at the minute. Currently commands go through the spark cloud.

/* 
 ==============================================================================================================
 ==============================================================================================================
 ======================================== Blind Controller Sketch =============================================
 ==============================================================================================================
 ==============================================================================================================
 */
   
/*

 Pin Setup
 ---------
 The Core has 8 PWM pins: A0, A1, A4, A5, A6, A7, D0 and D1.
 Blind 0: A0 + A1
 Blind 1: A4 + A5
 Blind 2: A6 + A7
 Blind 3: D0 + D1
 
 Onboard LED: D7
 */

  


#define EOM '\n' 
#define KEEP_ALIVE '|' 

const int OPENING = 1;
const int CLOSING = -1;
const int STOPPED = 0;

const unsigned long FULL_OPEN_TIME = 56000;
const unsigned long FULL_CLOSE_TIME = 41000;
const unsigned long HALF_CLOSE_TIME = 26000;
const unsigned long QUARTER_OPEN_TIME = 13000;

const int SERVER_PORT = 9999;
const byte SERVER_ADDRESS[] = {10,0,0,5};


//EthernetClient centralControl; 
TCPClient centralControl;

int currentMode = 0;
int motorState[4] = {
  STOPPED,STOPPED,STOPPED,STOPPED}; //Current motor state. -1 = closing, 0 = stopped, 1 = opening

unsigned long timer0 = 0;
unsigned long timer1 = 0;
unsigned long timer2 = 0;
bool timer0Enabled = false;
bool timer1Enabled = false;
bool timer2Enabled = false;
int timer0State[4] = {
  STOPPED,STOPPED,STOPPED,STOPPED};
int timer1State[4] = {
  STOPPED,STOPPED,STOPPED,STOPPED};
int timer2State[4] = {
  STOPPED,STOPPED,STOPPED,STOPPED};
  
 int setMode(String args);
 int getStatus(String args);

char charBuffer;
String stringBuffer = "";

UDP udp;

// byte mac[] = {  
//   0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
// IPAddress ip(10,0,0,212);

void setup() {
  //Ethernet.begin(mac,ip);
  pinMode(D0,OUTPUT);
  pinMode(D1,OUTPUT);
  
  pinMode(D2,OUTPUT);
  pinMode(D3,OUTPUT);
  
  pinMode(D4,OUTPUT);
  pinMode(D5,OUTPUT);
  
  pinMode(D6,OUTPUT);
  pinMode(D7,OUTPUT);
  
  //debugTest();
  
  


  Serial.begin(9600);
  //RGB.control(true);
  
  //TODO: Add UDP support.
  Spark.function("setMode", setMode);
  Spark.function("getStatus", getStatus);
  
  //udp.begin(9999);
  
  
  
  //RGB.color(255, 0, 0);
  
  delay(1000);
  //connect();
  //RGB.color(0,255, 0);
//  RGB.color(0,1,1);
  //RGB.control(false);
  
  updateMotorState(STOPPED, STOPPED, STOPPED, STOPPED);

}



void loop() {
  //checkNetwork();
  checkTimers();
  delay(100);
}

void debugTest(){
    updateMotorState(CLOSING, CLOSING, CLOSING, CLOSING);
    delay(4000);
    
    updateMotorState(OPENING, STOPPED, STOPPED, STOPPED);
    delay(2000);
    updateMotorState(CLOSING, STOPPED, STOPPED, STOPPED);
    delay(2000);
    
    updateMotorState(STOPPED, OPENING, STOPPED, STOPPED);
    delay(2000);
    updateMotorState(STOPPED, CLOSING, STOPPED, STOPPED);
    delay(2000);
    
    updateMotorState(STOPPED, STOPPED, OPENING, STOPPED);
    delay(2000);
    updateMotorState(STOPPED, STOPPED, CLOSING, STOPPED);
    delay(2000);
    
    updateMotorState(STOPPED, STOPPED, STOPPED, OPENING);
    delay(2000);
    updateMotorState(STOPPED, STOPPED, STOPPED, CLOSING);
    delay(2000);
    
    updateMotorState(STOPPED, STOPPED, STOPPED, STOPPED);
    delay(3000);
    updateMotorState(OPENING, OPENING, OPENING, OPENING);
    delay(5000);
    updateMotorState(STOPPED, STOPPED, STOPPED, STOPPED);
    
}

int setMode(String args)
{
    char newModeChar[args.length() + 1];
    args.toCharArray(newModeChar, sizeof(newModeChar));
    int mode = atoi(newModeChar);
    changeMode(mode);   
    return currentMode;
}

int getStatus(String args)
{
  return currentMode;
}


void checkTimers()
{
  if(timer0Enabled){
    if(timer0 < millis()){
      //Serial.println("Timer 0 fired!");
      updateMotorState(timer0State[0],timer0State[1],timer0State[2],timer0State[3]);
      timer0State[0] = STOPPED;
      timer0State[1] = STOPPED;
      timer0State[2] = STOPPED;
      timer0State[3] = STOPPED;
      timer0Enabled = false;
      timer0 = 0;
    }
  }

  if(timer1Enabled){
    if(timer1 < millis()){
      updateMotorState(timer1State[0],timer1State[1],timer1State[2],timer1State[3]);
      timer1State[0] = STOPPED;
      timer1State[1] = STOPPED;
      timer1State[2] = STOPPED;
      timer1State[3] = STOPPED;
      timer1Enabled = false;
      timer1 = 0;
    }
  }

  if(timer2Enabled){
    if(timer2 < millis()){
      //Serial.println("Timer 2 fired!");
      updateMotorState(timer2State[0],timer2State[1],timer2State[2],timer2State[3]);
      timer2State[0] = STOPPED;
      timer2State[1] = STOPPED;
      timer2State[2] = STOPPED;
      timer2State[3] = STOPPED;
      timer2Enabled = false;
      timer2 = 0;
    }
  }
}

void checkNetwork(){
  verifyConnection();
  if(centralControl.available()){
    charBuffer = centralControl.read();

    if(charBuffer == EOM){
       Serial.println("End of message detected " + stringBuffer);
      processMessage();
      stringBuffer = "";
    }
    else{
      stringBuffer += charBuffer;
      Serial.println("Not end of message " + stringBuffer);
    }
  }
}

void processMessage(){
  if(stringBuffer == "status")
  {

    String response = "mode=";
    response += currentMode;
    response += "&busy=";
    if(timer0Enabled || timer1Enabled || timer2Enabled)
      response += "true";
    else
      response += "false";
    response += "\n";
    centralControl.print(response);
  }
  else if(stringBuffer.startsWith("mode"))
  {
    String value = getValue(stringBuffer, '=',1);
    char newModeChar[value.length() + 1];
    value.toCharArray(newModeChar, sizeof(newModeChar));
    int mode = atoi(newModeChar);
    changeMode(mode);
  }
}



void verifyConnection(){
  int bytesWritten = centralControl.write(KEEP_ALIVE);
  Serial.print(bytesWritten);
  Serial.println(" bytes written.");
  if(bytesWritten == -1){
    //centralControl.stop();
    Serial.println("Not connected.");
    connect();
  }
  else{
    Serial.println("Seems connected.");
  
  }
}

String getValue(String data, char separator, int index)
{
  int found = 0;
  int strIndex[] = {
    0, -1  };
  int maxIndex = data.length()-1;

  for(int i=0; i<=maxIndex && found<=index; i++){
    if(data.charAt(i)==separator || i==maxIndex){
      found++;
      strIndex[0] = strIndex[1]+1;
      strIndex[1] = (i == maxIndex) ? i+1 : i;
    }
  }

  return found>index ? data.substring(strIndex[0], strIndex[1]) : "";
}

void connect(){
  centralControl.stop();
  do{
    Serial.println("Connecting...");
    centralControl.connect(SERVER_ADDRESS,SERVER_PORT);
    if(!centralControl.connected()){
        Serial.println("Connection failed. Trying again in a moement...");
        delay(1000);
    }
      
    else{
      Serial.println("Connected!");
      centralControl.print("registration?type=blind&name=blindController\n");
    }
  }
  while(!centralControl.connected());

}


void changeMode(int mode)
{
  
  if(mode != 0 && mode == currentMode)
    return;

  resetTimers();
  int previousMode = currentMode;
  currentMode = mode;
  switch(mode)
  {
  case 0: // Stop motors whatever their current position
    {
      updateMotorState(STOPPED,STOPPED,STOPPED,STOPPED);
    }
    break;

  case 1: // Full open
    {
      updateMotorState(OPENING,OPENING,OPENING,OPENING);
      //Wait 40 seconds and stop all motors:
      timer0 = millis() + FULL_OPEN_TIME;
      timer0Enabled = true;
      timer0State[0] = STOPPED;//Stop all motors when the timer expires
      timer0State[1] = STOPPED;
      timer0State[2] = STOPPED;
      timer0State[3] = STOPPED;
    }
    break;

  case 2: // Half open (no line of sight to bedroom)
    {
      if(previousMode == 1)
      {
        //If blinds are already open, start closing and stop about 15 seconds later
        updateMotorState(CLOSING,CLOSING,CLOSING,CLOSING);
        //In 15 seconds from now, stop the motors
        timer0 = millis() + HALF_CLOSE_TIME;
        timer0Enabled = true;
        timer0State[0] = STOPPED;
        timer0State[1] = STOPPED;
        timer0State[2] = STOPPED;
        timer0State[3] = STOPPED;
      }
      else
      {
        //Otherwise, open fully, then close for 15 seconds, then stop.
        updateMotorState(OPENING,OPENING,OPENING,OPENING);
        //in 40 seconds, start closing:
        timer0 = millis() + FULL_OPEN_TIME;
        timer0Enabled = true;
        timer0State[0] = CLOSING;
        timer0State[1] = CLOSING;
        timer0State[2] = CLOSING;
        timer0State[3] = CLOSING;
        //in 40 + about 15 seconds, stop the motors
        timer1 = millis() + FULL_OPEN_TIME + HALF_CLOSE_TIME;
        timer1Enabled = true;
        timer1State[0] = STOPPED;
        timer1State[1] = STOPPED;
        timer1State[2] = STOPPED;
        timer1State[3] = STOPPED;
      }
    }
    break;

  case 3: // 3/4 closed
    {
      if(previousMode == 4)
      {
        //Already closed, just open them for about 5 seconds, then stop
        updateMotorState(OPENING,OPENING,OPENING,OPENING);
        //in 5 seconds, start closing:
        timer0 = millis() + QUARTER_OPEN_TIME;
        timer0Enabled = true;
        timer0State[0] = STOPPED;
        timer0State[1] = STOPPED;
        timer0State[2] = STOPPED;
        timer0State[3] = STOPPED;
      }
      else
      {
        //Close fully, then open for 5 seconds, then stop
        updateMotorState(CLOSING,CLOSING,CLOSING,CLOSING);
        //in 30 seconds, start opening:
        timer0 = millis() + FULL_CLOSE_TIME;
        timer0Enabled = true;
        timer0State[0] = OPENING;
        timer0State[1] = OPENING;
        timer0State[2] = OPENING;
        timer0State[3] = OPENING;
        //in 30 + 5 seconds, stop the motors
        timer1 = millis() + FULL_CLOSE_TIME + QUARTER_OPEN_TIME;
        timer1Enabled = true;
        timer1State[0] = STOPPED;
        timer1State[1] = STOPPED;
        timer1State[2] = STOPPED;
        timer1State[3] = STOPPED;
      }
    }

    break;

  case 4: // Fully closed
    {
      //Fully close blinds
      updateMotorState(CLOSING,CLOSING,CLOSING,CLOSING);
      //Wait 30 seconds and stop all motors:
      timer0 = millis() + FULL_CLOSE_TIME;
      timer0Enabled = true;
      timer0State[0] = STOPPED;//Stop all motors when the timer expires
      timer0State[1] = STOPPED;
      timer0State[2] = STOPPED;
      timer0State[3] = STOPPED;
    }
    break;

  case 5: // closed, right center open
    {
      updateMotorState(CLOSING,CLOSING,OPENING,CLOSING);
      //Wait 40 seconds and stop all motors:
      timer0 = millis() + FULL_OPEN_TIME; // at least one blind is opening, so allow for it
      timer0Enabled = true;
      timer0State[0] = STOPPED;//Stop all motors when the timer expires
      timer0State[1] = STOPPED;
      timer0State[2] = STOPPED;
      timer0State[3] = STOPPED;
    }
    break;

  case 6: // closed, both center open
    {
      updateMotorState(CLOSING,OPENING,OPENING,CLOSING);
      //Wait 40 seconds and stop all motors:
      timer0 = millis() + FULL_OPEN_TIME; // at least one blind is opening, so allow for it
      timer0Enabled = true;
      timer0State[0] = STOPPED;//Stop all motors when the timer expires
      timer0State[1] = STOPPED;
      timer0State[2] = STOPPED;
      timer0State[3] = STOPPED;
     
    }
    break;

  case 7: // Closed, left center open
    {
      updateMotorState(CLOSING,OPENING,CLOSING,CLOSING);
      //Wait 40 seconds and stop all motors:
      timer0 = millis() + FULL_OPEN_TIME; // at least one blind is opening, so allow for it
      timer0Enabled = true;
      timer0State[0] = STOPPED;//Stop all motors when the timer expires
      timer0State[1] = STOPPED;
      timer0State[2] = STOPPED;
      timer0State[3] = STOPPED;
    }
    break;
  case 8: // Left two blinds open, right two closed ("tv mode")
    {
      updateMotorState(OPENING,OPENING,CLOSING,CLOSING);
      //Wait 40 seconds and stop all motors:
      timer0 = millis() + FULL_OPEN_TIME; // at least one blind is opening, so allow for it
      timer0Enabled = true;
      timer0State[0] = STOPPED;//Stop all motors when the timer expires
      timer0State[1] = STOPPED;
      timer0State[2] = STOPPED;
      timer0State[3] = STOPPED;
    }
    break;
    
    case 9: // Center two blinds 3/4 closed, outer two blinds fully closed.
    {
        if(previousMode == 4)
        {
          //BLinds already closed. Open two center ones a bit
          updateMotorState(STOPPED,OPENING,OPENING,STOPPED);
          //Wait the quarter open time and stop all motors:
          timer0 = millis() + QUARTER_OPEN_TIME; 
          timer0Enabled = true;
          timer0State[0] = STOPPED;//Stop all motors when the timer expires
          timer0State[1] = STOPPED;
          timer0State[2] = STOPPED;
          timer0State[3] = STOPPED;    
        }
        else 
        {
            //Close all first, then open center two for quarter open time.
            updateMotorState(CLOSING,CLOSING,CLOSING,CLOSING);
            //after full close time, start opening center two
            timer0 = millis() + FULL_CLOSE_TIME;
            timer0Enabled = true;
            timer0State[0] = STOPPED;
            timer0State[1] = OPENING;
            timer0State[2] = OPENING;
            timer0State[3] = STOPPED;
            //in quarter open time, stop all motors
            timer1 = millis() + FULL_CLOSE_TIME + QUARTER_OPEN_TIME;
            timer1Enabled = true;
            timer1State[0] = STOPPED;
            timer1State[1] = STOPPED;
            timer1State[2] = STOPPED;
            timer1State[3] = STOPPED;
        }
        
         
    }
    break;
  }
}

void resetTimers()
{
  timer0 = 0;
  timer1 = 0;
  timer2 = 0;

  timer0Enabled = false;
  timer1Enabled = false;
  timer2Enabled = false;

  timer0State[0] = STOPPED;
  timer0State[1] = STOPPED;
  timer0State[2] = STOPPED;
  timer0State[3] = STOPPED;

  timer1State[0] = STOPPED;
  timer1State[1] = STOPPED;
  timer1State[2] = STOPPED;
  timer1State[3] = STOPPED;

  timer2State[0] = STOPPED;
  timer2State[1] = STOPPED;
  timer2State[2] = STOPPED;
  timer2State[3] = STOPPED;
}

void updateMotorState(int motor0, int motor1, int motor2, int motor3){
  updateMotorState(0,motor0);
  updateMotorState(1,motor1);
  updateMotorState(2,motor2);
  updateMotorState(3,motor3);
}

void updateMotorState(int blindIndex, int newState) {
  if(newState == motorState[blindIndex])
    return; //Blind motor is in correct state already. 
  motorState[blindIndex] = newState;
  resetMotor(blindIndex);
  
//   Serial.print("Setting motor ");
//   Serial.print(blindIndex);
//   Serial.print(" to ");
//   Serial.println(newState);
  
  int pin0 = D0;
  int pin1 = D1;
  
  //TODO: Fill in correct pin numbers for each blind motor relay
  switch(blindIndex)
  {
    case 0:
    pin0 = D0;
    pin1 = D1;
    break;
    
    case 1:
    pin0 = D2;
    pin1 = D3;
    break;
    
    case 2:
    pin0 = D4;
    pin1 = D5;
    break;
    
    case 3:
    pin0 = D6;
    pin1 = D7;
    break;

 
  }

  if(newState == OPENING){
    digitalWrite(pin0,HIGH);
    digitalWrite(pin1,LOW);
  }
  else if(newState == CLOSING){
    digitalWrite(pin0,LOW);
    digitalWrite(pin1,HIGH);
  }
  else if(newState == STOPPED){
    digitalWrite(pin0,LOW);
    digitalWrite(pin1,LOW);
  }
}

void resetMotor(int index){
  Serial.print("resetting motor ");
  Serial.println(index);
  if(index == 0){
    digitalWrite(D0,LOW);
    digitalWrite(D1,LOW);
  }
  else if(index == 1){
    digitalWrite(D2,LOW);
    digitalWrite(D3,LOW);
  }
  else if(index == 2){
    digitalWrite(D4,LOW);
    digitalWrite(D5,LOW);
  }
  else if(index == 3){
    digitalWrite(D6,LOW);
    digitalWrite(D7,LOW);
  }

  delay(100);
}

@dermotos,

the :spark: team is aware of the problem and we have managed to reproduce the issue.

It’s a behavior that was planned during their development where the core would indeed go to Smart-config after some time.

That’s gonna be changed such that the core will just scan around the wifi-profiles stored and attempt to connect.

There’s a commit being pushed and you can see our discussion @

Should be fixed next Sprint! :dancer:

Please do post back if it continues to behave that way after the official changes are made to the Cloud IDE.

I’ll also do a test on my side when they push the changes and report back as well :smiley:

1 Like