Array für gleitenden Mittelwert vor-initialisierten

Hallo!

Ich möchte einen Temperaturwert gleitend mitteln, und habe dafür ein Array gebaut. Grundsätzlich funktioniert es so, allerdings benötigt die Lösung ca. die Länge des Arrays an Messungen, um in die Nähe des Mittelwerts zu gelangen weil das Array zunächst mit Nullen gefüllt ist. In anderen Umgebungen würde ich es mit NaNs initialisieren, das funktioniert hier aber nicht. Ich habe versucht, im setup() den Sensor auszulesen und diesen ersten (zufälligen) Wert zum Initialisiern zu verwenden. In dem Fall wird allerdings - aus mir gerade unverständlichen Gründen - der Mittelwert nicht korrekt gebildet. Was ist der Grund dafür und wie bekomme ich ein zu Beginn besser initialisiertes Array?

#include <OneWire.h>
#include <DallasTemperature.h>
#define ONE_WIRE_BUS 9               
OneWire oneWire(ONE_WIRE_BUS);        
DallasTemperature sensors(&oneWire); 

const int numReadings = 10;      // array length

float readings[numReadings];      // the readings from the input
int readIndex = 0;                       // the index of the current reading
float total = 0;                             // the running total
float average = 0;                       // the average


void setup() {

  Serial.begin(9600);
  sensors.begin();
  
  // initialize array
  sensors.requestTemperatures();
  float start_val=sensors.getTempCByIndex(0);

  for (int thisReading = 0; thisReading < numReadings; thisReading++) {
    readings[thisReading] = start_val;
  }
}

void loop() {    
  sensors.requestTemperatures(); // Send the command to get temperatures

  // subtract the last reading:
  total = total - readings[readIndex];
  
  // read from the sensor:
  readings[readIndex] = sensors.getTempCByIndex(0);
  
  // add the reading to the total:
  total = total + readings[readIndex];
  
  readIndex = readIndex+1;

  if (readIndex >= numReadings) {
    readIndex = 0;
  }
  
  // calculate the average:
  average = total / numReadings;
  
  // serial
  Serial.print(sensors.getTempCByIndex(0));Serial.print("\t");

  for(int i=0;i<numReadings;i++){
  Serial.print(readings[i]);Serial.print("|");
  }
  
  Serial.print("\t");Serial.print(total);
  Serial.print("\t");Serial.println(average);
  
  delay(1000);
}

Nimm den ersten Meßwert und schreibe ihn ins ganze Array ein.

Hast Du als Meßwert eine Null?
Wenn nicht, machst Du den Mittelwert nur über die Werte die nicht null sind.
Falls Du null als Meßwert haben kannst mußt Du Dir eine andere Zahl finden, die nie als Meßwert erfaßt wird und das Array am Anfang damit füllen. Dann den Mitelwert ohne diesen wert berechnen.
Grüße Uwe

Du kannst auch mitzählen wieviele Werte Du ins Array geschrieben hast und falls das Array nicht voll ist nur über die geschriebenen Werte den Mmittelwert bilden.
Grüße Uwe

Hi
@DrDiettrich

  for (int thisReading = 0; thisReading < numReadings; thisReading++) {
    readings[thisReading] = start_val;
  }

Sieht eigentlich schon genau so aus.

@TO
Du solltest Dein ‘total’ aber ebenfalls auf diesen Wert setzen.

MfG

im setup() den Sensor auszulesen und diesen ersten (zufälligen) Wert zum Initialisiern zu verwenden. In dem Fall wird allerdings - aus mir gerade unverständlichen Gründen - der Mittelwert nicht korrekt gebildet. Was ist der Grund dafür und wie bekomme ich ein zu Beginn besser initialisiertes Array?

Das Problem ist, dass du

float total = 0;                             // the running total
float average = 0;                       // the average

Nicht in setup() mit korrekten Werten initialisierst!
Dann tuts das auch.

Hier mal ein Alternativvorschlag, aus meiner Wühlkiste:
(leicht für deine Zwecke angepasst)

#include <OneWire.h>
#include <DallasTemperature.h>


// ------------

    
template<typename DatenType> 
class GleitenderMittelwert   // eher Tiefpassfilter
{
 private:
  const double factor;
  double       mittelwert;
  
 public:
   GleitenderMittelwert(const double factor):factor(factor),mittelwert(0){}
   
   void setInitial(double value)
   {
      mittelwert = value;
   }
   
   DatenType doValue(DatenType value) // neuen Wert verarbeiten
   {
      mittelwert *= 1.0 - factor;
      mittelwert += factor * value;
      return  mittelwert;
   }
   
   DatenType operator= (DatenType value)
   {
      return doValue(value);       
   }
   
   DatenType operator() (DatenType value)
   {
      return doValue(value);       
   }
   
   DatenType operator() () const
   {
      return mittelwert;       
   }

   operator DatenType() const
   {
     return mittelwert;
   }  
};


// ------------

#define ONE_WIRE_BUS 9               
OneWire oneWire(ONE_WIRE_BUS);       
DallasTemperature sensors(&oneWire);

// 1.0/10.0 entspricht in etwa einem Array mit 10 Zellen fuer die Berechnung des Mittelwertes
GleitenderMittelwert<float> tiefPass(1.0/10.0);  

// ------------
  

void setup() 
{

  Serial.begin(9600);
  sensors.begin();
 
  sensors.requestTemperatures();
  tiefPass.setInitial(sensors.getTempCByIndex(0));
}

void loop() 
{   
  sensors.requestTemperatures(); // Send the command to get temperatures
  float value      = sensors.getTempCByIndex(0);
  float geglaettet = tiefPass(value);

  Serial.print("Gelesener Wert: ") ;Serial.print(value)     ;Serial.print("\t");
  Serial.print("Geglaetter Wert: ");Serial.print(geglaettet);Serial.println();

 
  delay(1000);
}

postmaster-ino:
@TO
Du solltest Dein 'total' aber ebenfalls auf diesen Wert setzen.

Aah, na klar! Vielen Dank, auch @combie! Und die Variante von @uwefed werde ich bei dieser Gelegenheit auch gleich mal versuchen.