SOS code - 2 red flashes


#1

Hey all,

I’m working on moving some sketches from photon to my new bluzDKs and immediately upon flashing my firmware I got a crash with SOS followed by 2 red flashes. I don’t see this error code in the docs, can anyone let me know what this error might mean?

Thanks


#2

That error, generically, is used when an action requiring the Nordic SoftDevice is called before the SoftDevice is enabled. That is a bit odd, it shouldn’t happen in the firmware.

Is it possible that you could post your code? That would help identify the issue.


#3

Sure, here it is. This is for a home energy monitoring device ( along the lines of the open energy monitor). I’m pretty new to this type of programming but hopefully this makes some sense

#include "emonlibphoton.h"


EnergyMonitor emon0;    
EnergyMonitor emon1;
EnergyMonitor emon2;
EnergyMonitor emon3;
EnergyMonitor emon4;
EnergyMonitor emon5;


float Irms[6];
float wattage[6];
uint8_t VOLTAGE = 240;

unsigned int step = 180000; //number of milliseconds between measurements 900,000 = 15 minutes
unsigned int currentTime = millis();
unsigned int nextTime = currentTime + step;  
unsigned int lastReading = 0;

float genPower;
float gridPower;
float totalPower;
float energy[] = {0, 0, 0, 0, 0, 0}; //{grid x 3, gen x 3}

float savedGrid[384];
float savedGen[384];
//unsigned int savedTime[384];
unsigned int numSavedReadings = 0;


String deviceId = System.deviceID();


void setup() {
    //set mode for pins for current sensors
    pinMode(A0,INPUT);
    pinMode(A1,INPUT);
    pinMode(A2,INPUT);
    pinMode(A3,INPUT);
    pinMode(A4,INPUT);
    pinMode(A5,INPUT);

    emon0.current(A0, 90.9);  // 100A max current sensors (22 Ohm burden resistors)
    emon1.current(A1, 90.9);
    emon2.current(A2, 90.9);
    emon3.current(A3, 90.9);
    emon4.current(A4, 90.9);
    emon5.current(A5, 90.9);

    Particle.variable("grid", gridPower);
    Particle.variable("gen", genPower);
    Particle.variable("total", totalPower);

}

void loop() {
    
    // Check BLE status to make sure that advertising doesnt go on too long
    BLEState state = BLE.getState();
    if (state == BLE_ADVERTISING) {
        attemptBLEconnect();
    }

    //read values from current sensors
    readCurrentSensors();

//convert to energy through voltage and timestep
    currentTime = millis();
    unsigned int timeStep = (currentTime - lastReading)/1000; //seconds
    lastReading = currentTime;
    for (unsigned int i = 0; i < 6; i++) {
      wattage[i] = Irms[i] * VOLTAGE; //convert current to power
      energy[i] += (timeStep * wattage[i])/(3600); //convert power to energy in Wh
    }

    //set particle variables
    gridPower = wattage[0] + wattage[1] + wattage[2];
    genPower = wattage[3] + wattage[4] + wattage[5];
    totalPower = gridPower + genPower;

    float gridEnergy =  energy[0] + energy[1] + energy[2];
    float genEnergy =  energy[3] + energy[4] + energy[5];

    //Code block to execute when the 15min mark has passed and the next data pack should be sent to the cloud
    if (currentTime >= nextTime) {
        //check the connection state, and attempt to reconnect BLE if necessary
        if (!Particle.connected()) {
            if (attemptBLEconnect()) {
                Particle.connect();
            }
        }
        
        delay(1000);
        
        if (Particle.connected()) {
            returnReadings(gridEnergy, genEnergy);
            resetEnergyCounters();
            // checkSavedReading();
        } else {
            saveReading(gridEnergy, genEnergy);
            resetEnergyCounters();
        }
    }

    delay (3000);

}


//function for using emon objects to get current readings
void readCurrentSensors() {

  Irms[0] = emon0.calcIrms(1480);  //all sensors 100A
  Irms[1] = emon1.calcIrms(1480);
  Irms[2] = emon2.calcIrms(1480);
  Irms[3] = emon3.calcIrms(1480);
  Irms[4] = emon4.calcIrms(1480);
  Irms[5] = emon5.calcIrms(1480);

}

void returnReadings(float grid, float gen) {

    unsigned int numSuccess = 0;
    for (unsigned int i = 0; i < numSavedReadings; i++) {
        
        unsigned int periodsBehind = numSavedReadings - i;
        
        String dataString = String(periodsBehind);
        dataString += "," + String(savedGrid[i]);
        dataString += "," + String(savedGen[i]);
        
        bool success;
        success = Particle.publish("energyReading", dataString, 60, PRIVATE);
        
        if (success) {
            // if the post was received successfully, then we can delete reading
            savedGrid[i] = 0;
            savedGen[i] = 0;
            numSuccess++;
        } else {
            // TODO: handle error here
        }
        
    }

    numSavedReadings = numSavedReadings - numSuccess;
    
    String dataString = "0";
    dataString += "," + String(grid);
    dataString += "," + String(gen);
    
    bool success;
    success = Particle.publish("energyReading", dataString, 60, PRIVATE);
    
    if (!success) {
        saveReading(grid, gen);
    } 
  
}

void saveReading(float grid, float gen) {

    savedGrid[numSavedReadings] = grid;
    savedGen[numSavedReadings] = gen;        
    numSavedReadings++;
    
}

bool attemptBLEconnect() {
    //script to manage connecting the BLE to the hub for a certain amount of time in order to limit
    //power consumption and battery drainage of the device
    BLEState state = BLE.getState();
    
    if (state == BLE_CONNECTED) {
        return true;
    } else {
        BLE.startAdvertising();
        delay(5000);
        BLE.stopAdvertising();
    } 
    
    state = BLE.getState();
    return state == BLE_CONNECTED;
    
}

void resetEnergyCounters() {
      nextTime = nextTime + step;
      for (unsigned int i = 0; i < 6; i++) {
        energy[i] = 0;
      }

}

#4

Found the issue!

After going back and commenting out code until the SOS went away I have discovered that the problem was in the call to System.deviceID( ). Since you mentioned it was a question of the SoftDevice not being enabled yet I tried moving this call into the setup( ) method and now it runs without crashing.

@eric, since I have already posted my code here, could you possibly give me a quick comment about my attemptBLEconnect( ) method? The basic idea is that I’m expecting that my gateway will not always be available and I would like to ensure that the bluz is not endlessly advertising in order to preserve battery life. Does this seem like the correct basic approach to this? Any suggestions would be very welcome.

Thanks!


#5

I think this approach is a very good idea. Just keep in mind that bluz is different than a Photon, for example, where even if you advertise for some period of time, it doesn’t guarantee that you get connected. It looks like you are handling that here, so it shouldn’t be too much of a concern.

If battery consumption is your main concern, then definitely add System.sleep(SLEEP_MODE_CPU); to the loop() function. Also, instead of using delay(), I would use system_time to figure out when to run your loop function. delay() keeps the CPU on, the idea here is to minimize its use as much as possible.