Hallo *
Ich habe ein mir nicht nachvollziehbares Problem bei der Median/Mittelwertberechnung von Messdaten.
Der unten stehende C++ Code(ausschnitt) läuft auf einem ESP8266 / Arduino.
Die Median-Funktion soll das ihr übergeben Array sortieren und dann über die mittelsten 5 Werte den Durchschnitt berechnen.
Dieser Wert wird zurück gegeben und weiter verarbeitet.
(Die Laufzeitausgabe im Fehlerfall steht weiter unten in einem gesonderten Code-Block)
Nun kommt es ab und zu (selten, nicht systematisch, unabhängig von der Größe der Messwerte) zu dem Fall, dass der berechnete Wert viel zu klein ist (als ob ein Wert fehlt).
Das führt natürlich zu sporadischen Ausreissern, die in der Anzeige als hässliche Zacken nach unten zu identifizieren sind.. und natürlich falsch sind.
Ich wende mich an euch, weil mir langsam die Ideen ausgehen, woran es liegen könnte...
Der Gesamtcode liegt im erdfeuchte-Git-Repository im Verzeichnis /sensor
Wer das nachbauen will, muss noch die folgenden Defines/Variablen (global) setzten...
#define MEASURING_INTERVALLS 10
volatile unsigned long counter = 0; // interrupt loop counter
unsigned long soilMoistAveraged;
Hier der sinnvoll gestrippte Kerncode:
/**
* Simple median/average calculation
* ------------------------------------
* Getting array will be sorted and now get the average over the middle values
*/
unsigned long median(unsigned long *values, int arraySize) {
unsigned long tmp = 0; // set to 0, make the compiler happy :-)
const unsigned long relVal = 2; // +- 2 Werte + 1 für die Mittelwertberechnung
for (int i=0; i<arraySize; i++) {
for (int j=arraySize-1; j>i; j--) {
if( values[j] < values[j - 1] ) {
tmp = values[j];
values[j] = values[j - 1];
values[j - 1] = tmp;
}
}
}
for (unsigned long i=arraySize/2-relVal; i<arraySize/2+relVal; tmp +=values[i++]) {}
return tmp/(relVal*2+1);
}
/**
* Interrupt function: increment the counter
*/
void intfunc() {
counter++;
}
/**
* Measure soil moisture and build the average of measurement values
*/
void bodenfeuchtemessung(int gpioPin) {
unsigned long speicherArray[MEASURING_INTERVALLS];
for (int i=0; i<MEASURING_INTERVALLS; i++) {
Serial << F("Measuring No.: ") << i << F(" on GPIO-Pin ") << gpioPin << F(" = ");
counter = 0;
attachInterrupt(gpioPin, intfunc, RISING);
delay(MEASURING_TIME);
detachInterrupt(gpioPin);
speicherArray[i] = counter;
Serial << counter << endl;
}
soilMoistAveraged = median(speicherArray, MEASURING_INTERVALLS);
Serial << F("average frequence: ") << soilMoistAveraged << endl;
}
Alles anzeigen
Und das wird (im Fehlerfall) an der serielle SS angezeigt (83060 ist natürlich Käse... aber wieso ???)
Measuring No.: 0 on GPIO-Pin 5 = 103736
Measuring No.: 1 on GPIO-Pin 5 = 103745
Measuring No.: 2 on GPIO-Pin 5 = 103770
Measuring No.: 3 on GPIO-Pin 5 = 103782
Measuring No.: 4 on GPIO-Pin 5 = 103818
Measuring No.: 5 on GPIO-Pin 5 = 103850
Measuring No.: 6 on GPIO-Pin 5 = 103851
Measuring No.: 7 on GPIO-Pin 5 = 103858
Measuring No.: 8 on GPIO-Pin 5 = 103870
Measuring No.: 9 on GPIO-Pin 5 = 103897
average frequence: 83060
Alles anzeigen
Ich würde mich echt freuen, wenn mir jemand einen Schubs in die Lösungsrichtung geben könnte...
das Zen