Particle crashing with SOS-10

hi, i am playing around with particle. i connected a microphone and have some calculations running on it, but when i trigger the Particle.publish()… it crashes after a few seconds with 10 times blinking red after the SOS :frowning:

here is the code:

/*********************************************************
* record microphone, write to serial
**********************************************************/
#include <stdio.h>

 

void apply_filter(double wave[]);
void ifSomeoneWasTalkingSendEvent();

 

void tabelle2();

 

#define FILTER_COUNT 17
#define FILTER_MITTELWERT FILTER_COUNT/2
double filter_value[] = {-0.06871842412524538,
0.030806641388861217,
0.04196636574643017,
0.0596784709979785,
0.08054585311515544,
0.1012312882292675,
0.11862582117408683,
0.13018226286688447,
0.13422859623430416,
0.13018226286688447,
0.11862582117408683,
0.1012312882292675,
0.08054585311515544,
0.0596784709979785,
0.04196636574643017,
0.030806641388861217,
-0.06871842412524538};
const int microphone = A0;

 


const int buttonPin = D5;
const int ledPin = D7;
const int recLength = 8192; // 2 hoch 13, 250 ms
const int abtastrate = recLength;
double wave[recLength];
unsigned long startTime;
unsigned long deltaTime;

 

int speaking = 0;

 

void setup() {
// A0: INPUT is the default pin mode. No config required
    pinMode(buttonPin, INPUT_PULLUP);
    pinMode(ledPin, OUTPUT);
    Particle.variable("speaking", speaking);
    Serial.begin(9600);
}

 

void tabelle2() {
    int summe = 0;
    double min = wave[0];
    double max = wave[0];
    for (int i = 0; i < recLength; i++) {
        summe = summe + wave[i];
        if (wave[i] < min) {
            min = wave[i];
        }
        if (wave[i] > max) {
            max = wave[i];
        }
    }
    double mittelwert = summe / recLength;
    double delta = (max - min) / 2;
    
    for (int i = 0; i < recLength; i++) {
        wave[i] = (wave[i] - mittelwert) / delta;
    }
}

 

//Serial.println(wave[i], 8);

 

void apply_filter() {
    int start = FILTER_MITTELWERT;
    double filtered_value = 0;
    
    for (int i = 0; i < 10; i++) {
        filtered_value = 0;
        if (i < FILTER_MITTELWERT + 1) continue;
        for (int f = FILTER_MITTELWERT + 1; f < FILTER_COUNT; f++) {
            filtered_value = filtered_value + wave[i] * filter_value[f];
        }
        for (int f = FILTER_MITTELWERT; f > 0; f--) {
            filtered_value = filtered_value + wave[i] * filter_value[f];
        }
        wave[i] = filtered_value;
    }
}

 


void loop() {
    
    int tmp = 0;
    
    for (int i = 0; i < recLength; i++) {
        tmp = analogRead(microphone);
        if (tmp < 900) {
            i--;
            continue;
        }
        wave[i] = tmp;
    }
    
    tabelle2();
    apply_filter();
    
    ifSomeoneWasTalkingSendEvent();
    delay(250);

 

}

 

void ifSomeoneWasTalkingSendEvent() {
    
    double x = 0;
    double sum = 0;
    
    //we send the speaking event and return if someone talks
    //if no one talks, we already know that if someone was talking before, we send the stopped speaking event!
    for(int i = 0; i < recLength; i++) {
        x = (wave[i]);
        if(x < 0) x = x * -1;
        sum += x;
    }
    
    double mean = sum / recLength; 
    Serial.printf("Mean: %f\n", mean);
    
    if(speaking == 0) {
        if(mean > 0.23) {
            Particle.publish("speaking", "true");
            speaking = 1;
            delay(750);
            return;
        }
    } 
    
    
    if(speaking == 1) {
        speaking = 0;
        Particle.publish("speaking", "false");
        delay(750);
    }
    
    
}

now its blinking fast blue, and sometimes a red light appears.
is something wrong with the code??
the only way to get it running now again is to use particle dfu and flash tinker

@someOne, which DeviceOS and which device are you using?

Device OS:
1.5.2

Type:
Argon

@someOne, how are you compiling the code - WebIDE, CLI or Particle Workbench? Are you certain you are getting 10 flashes after the SOS code?

Just from looking at the code, I did not test this, but it looks like if there is silence, loop will be blocked. If you do this for too long, the cloud connection will be lost and you’ll go back to fast blinking cyan. The easiest solution is to add:

SYSTEM_THREAD(ENABLED);

In this code:

for (int i = 0; i < recLength; i++) {
        tmp = analogRead(microphone);
        if (tmp < 900) {
            i--;
            continue;
        }
        wave[i] = tmp;
    }

if tmp < 900, then this inner for loop never exits. If you are not using system threading, then the cloud connection will never get serviced since you never return from loop().

I don’t think you’re handing signed values correctly. The analogRead() always returns a value from 0 to 4095 (inclusive) and you store tmp in wave[i] so it will always be 0 to 4095.

But in ifSomeoneWasTalkingSendEvent() you copy wave[i] to x and check if it’s negative. But it will never be negative.

Your microphone probably has a fixed DC offset, so you’ll subtract some constant from wave[i]. Also, based on the mean calculation, it looks like you’re expecting it to be in the range of 0.0 to 1.0, not 0 - 2047. So assuming your microphone outputs a full 0.0 to 3.3V with a 1.65V DC offset, the calculation would be:

x = Math.abs((double)(wave[i] - 2048) / 2048.0);

If your microphone outputs negative voltage, stop using it as the nRF52 ADC does not tolerate negative voltages and can be damaged.

1 Like

i use the web IDE.

it sometimes happen that the value i recieve is < 900, but thats seldom. so i guess that should not block? i added a Serial.println() and it was writing all the time, until the LED started blinking.

the microphone returns an int value with a offset of 900, so i have values in between 900 up to about 1400 in *wave. this wave is later manipulated to a signal and this signal can be negative (apply_filter())

i replaced 8192 with 4096 and also removed all Serial.x calls, it does not blink red anymore.

i counted the red blinking, it was 10 times.