SOS Mode after flashing firmware

When I flash a certain piece of code, my photon will enter SOS mode, and I’ll have to completely reset it. Any idea what kind of code in firmware will cause the photon to behave this way? Thanks!

What code, what SOS, and what reset? A bit more information would go a long way :wink:

2 Likes

As said - lots of possible coding errors can cause such behaviour, but you know your code, we don’t - unless you show your code!

1 Like

Thanks! This is what causes the Photon to SOS. I just get random red blinking - there’s no order to it. I will reset all the keys/update firmware/play around with it to get it to start working again.

/*
 *  This firmware will run a TCPServer on Photon, and stream acoustic and accerlation data to client.
 *  For now, this version multiplexes the TCP packets by tagging the very first 2 bytes with data type flag.
 *
 *  0x00 = Sound Data,
 *  0x01 = Accelerometer Data.
 *
 *  For sound, the sampling rate sits at 8000Hz, and for accelerometer, the sampling rate sits at 3000Hz.
 *  Both datatypes use 2-byte resolution (Sound = 16bit, and accelerometer = 10bits to be exact)
 *  Accelerometer data is recorded in triplets; X, Y, and Z data are put in order.
*/


#define MICROPHONE_PIN A0
#define AUDIO_BUFFER_MAX 8192
#define ACCEL_BUFFER_MAX 9216 //3072*3
#define DATA_INFO_TAG 4
#define DEVICE (0x53) // ADXL Device address

int audioIdx = 0;
int accelIdx = 0;
uint16_t audioBuffer[AUDIO_BUFFER_MAX];

// version without timers
unsigned long lastMicRead = micros();
unsigned long lastAccelRead = micros();
char myIpAddress[24];
TCPServer photonServer = TCPServer(3443);

TCPClient photonClient;
TCPClient checkClient;

// The data can definitely be negative, but we're dealing with bytestream.
// Assume this as simple array of 16bit binary values.
uint16_t accelBuffer[ACCEL_BUFFER_MAX];

uint16_t txBuffer[AUDIO_BUFFER_MAX+ACCEL_BUFFER_MAX+DATA_INFO_TAG];

// Buffer used for I2C.
byte _buff[6];

// Register addresses for ADXL345
char POWER_CTL = 0x2D;  //Power Control Register
char DATA_FORMAT = 0x31;
char DATAX0 = 0x32; //X-Axis Data 0
char DATAX1 = 0x33; //X-Axis Data 1
char DATAY0 = 0x34; //Y-Axis Data 0
char DATAY1 = 0x35; //Y-Axis Data 1
char DATAZ0 = 0x36; //Z-Axis Data 0
char DATAZ1 = 0x37; //Z-Axis Data 1

int CS = 10;

void setup() {
    Serial.begin(115200);
    pinMode(MICROPHONE_PIN, INPUT);
    
    // so we know where to connect, try:
    // particle get MY_DEVICE_NAME ipAddress
    
    Spark.variable("ipAddress", myIpAddress, STRING);
    IPAddress myIp = WiFi.localIP();
    sprintf(myIpAddress, "%d.%d.%d.%d", myIp[0], myIp[1], myIp[2], myIp[3]);
    
    // 1/8000th of a second is 125 microseconds
    photonServer.begin();
    
    // Start i2c
    Wire.begin();
    
    pinMode(CS, OUTPUT);
    //Before communication starts, the Chip Select pin needs to be set high.
    digitalWrite(CS, HIGH);
    
    //Put the ADXL345 into +/- 4G range by writing the value 0x01 to the DATA_FORMAT register.
    writeTo(DATA_FORMAT, 0x03);
    //Put the ADXL345 into Measurement Mode by writing 0x08 to the POWER_CTL register.
    writeTo(POWER_CTL, 0x08);
    
    lastMicRead = micros();
    lastAccelRead = micros();
}

void loop() {
    checkClient = photonServer.available();
    if (checkClient.connected()) {
        photonClient = checkClient; 
    }
    
    //listen for 1 second, taking samples, then send to client
    //may need to fix this value if delay starts overlapping.
    listenAndSend(1000);
}

void listenAndSend(unsigned int delayAmount) {
    unsigned long startedListening = millis();
    
    while ((millis() - startedListening) < delayAmount) {
        unsigned long time = micros();
        
        // update the mark in case time wrapped
        if (lastMicRead > time) {
            lastMicRead = time;
        }
        if (lastAccelRead > time){
            lastAccelRead = time;
        }
        
        //125 microseconds is 1/8000th of a second
        if ((time - lastMicRead) > 125) {
            lastMicRead = time;
            readMic();
        }
        //333 microseconds is 1/3000th of a second
        if ((time - lastAccelRead) > 333) {
            lastAccelRead = time;
            readAccel();
        }
    }
    // These function calls must be separate.
    // They use same transmission buffer for TCP.
    sendData();

    // Wait for 100ms after the function call completion
    // To make sure that we have no WiFi module activity during data collection
    delay(100);
}

 
// Callbacks for Timer 1
void readMic(void) {
    uint16_t value = analogRead(MICROPHONE_PIN);
    audioBuffer[audioIdx++] = value;
}

void readAccel(void) {
    uint8_t howManyBytesToRead = 6;
    readFrom( DATAX0, howManyBytesToRead, _buff); //read the acceleration data from the ADXL345

    // each axis reading comes in 10 bit resolution, ie 2 bytes.
    // thus we are converting both bytes in to one int
    int x = (((int)_buff[0]) << 8) | _buff[1];   
    int y = (((int)_buff[2]) << 8) | _buff[3];
    int z = (((int)_buff[4]) << 8) | _buff[5];
    
      // Negative overflow
    if (x > 60000) {
      x -= 65536;
    }
    if (y > 60000) {
      y -= 65536;
    }
    if (z > 60000) {
      z -= 65536;
    } 
    Serial.println(x);
    Serial.println(y);
    Serial.println(z);
    // Put X,Y, and Z output in order, for TCP trasmission
    accelBuffer[accelIdx++] = x;
    accelBuffer[accelIdx++] = y;
    accelBuffer[accelIdx++] = z;
}

void copyData(uint16_t *bufferPtr){
    // Report the audio/accel data sizes
    bufferPtr[0] = audioIdx;
    bufferPtr[1] = accelIdx;

    // Start after the data info tag field
    int txIdx = DATA_INFO_TAG;
    for (int i=0; i<audioIdx; i++){
        bufferPtr[txIdx++] = audioBuffer[i];
    }
    for (int i=0; i<accelIdx; i++){
        bufferPtr[txIdx++] = accelBuffer[i];
    }

    // Mark end of data
    bufferPtr[txIdx] = -1;

    // Reset the data indices
    audioIdx = 0;
    accelIdx = 0;
}

void sendData(void) {
    copyData(txBuffer);

    int i=0;
    uint16_t val = 0;
    
    if (photonClient.connected()) {
       write_socket(photonClient, txBuffer);
    }
    else {
        while( (val = txBuffer[i++]) < 65535 ) {
            Serial.print(val);
            Serial.print(',');
        }
        Serial.println("DONE");
    }
}


// audio and accel sample is 16bit, we need to convert it to bytes for sending over the network
void write_socket(TCPClient socket, uint16_t *buffer) {
    int i=0;
    uint16_t val = 0;
    int tcpIdx = 0;
    uint8_t tcpBuffer[1024];
    
    while( (val = buffer[i++]) < 65535 ) {
        if ((tcpIdx+1) >= 1024) {
            socket.write(tcpBuffer, tcpIdx);
            tcpIdx = 0;
        }
        
        tcpBuffer[tcpIdx] = val & 0xff;
        tcpBuffer[tcpIdx+1] = (val >> 8);
        tcpIdx += 2;
    }
    
    // any leftovers?
    if (tcpIdx > 2) {
        socket.write(tcpBuffer, tcpIdx);
    }
}

// ADXL Write Function
void writeTo(byte address, byte val) {
    Wire.beginTransmission(DEVICE); // start transmission to device 
    Wire.write(address);             // send register address
    Wire.write(val);                 // send value to write
    Wire.endTransmission();         // end transmission
}

// ADXL Read Function
// Reads num bytes starting from address register on device in to _buff array
void readFrom(byte address, int num, byte _buff[]) {
    Wire.beginTransmission(DEVICE); // start transmission to device 
    Wire.write(address);             // sends address to read from
    Wire.endTransmission();         // end transmission
    
    Wire.beginTransmission(DEVICE); // start transmission to device
    Wire.requestFrom(DEVICE, num);    // request 6 bytes from device
    
    int i = 0;
    while(Wire.available())         // device may send less than requested (abnormal)
    { 
        _buff[i] = Wire.read();    // receive a byte
        i++;
    }
    Wire.endTransmission();         // end transmission
}
1 Like

Heya @jrexthetrex,

Nice to see some of my “sending sound” code in there! :slight_smile:

An SOS is usually a “dit-dit-dit dah-dah-dah dit-dit-dit”, followed by a number of blinks to indicate the fault.

I’m guessing you’re maybe spilling over the end of one of your buffers. The "< 65535"s checks might not work as expected, I’d add some code to check your index to make sure it’s less than your buffer max, just to be safe?

I hope that helps!

Thanks,
David

1 Like

Thank you so much! And thanks for your sound code haha. I’ll try that.

1 Like