Mittelwert von meinen Sensorwerten

Super danke jurs. Mit deinen Ideen hab ich jetzt neue Funktionen erstellt, um die Eingabe sozusagen zu verarbeiten und den Mittelwert zu bilden. Zum Schluss wird es dann ausgegeben. Hatte außerdem vergessen meinen Zähler auf 0 zu setzen, nachdem es die maximalen Durchläufe durchhatte.

Teste jetzt gerade, wie meine Werte sich innerhalb von paar Stunden verändern.

Vielen Dank soweit klappt es :slight_smile:

Ich würde jetzt etwas anderes testen wollen.
Und zwar würde ich gerne für 3 Stunden 6 Werte messen wollen. Also alle 30 Minuten einen Druckwert.
Von diesen 6 ausgegebenen Werten möchte ich den Mittelwert bilden, um zu gucken ob mein Druckwert in dem Toleranzbereich liegt. Die könnte man später natürlich auf 24h usw. hinauszögern aber ich würde erstmal für 3h testen wollen.

Um meine ausgegebenen Werte zu merken, dachte ich mir, dass ich auf dem EEPROM Speicher zugreife.
Also alle 30 Minuten soll ein Wert in den EEPROM Speicher eingeschrieben werden.

Wenn ich falsch liege korrigiert mich bitte, aber ich habe das so verstanden, dass ich nur byteweise speichern kann. Also müsste ich meine Werte in binär umwandeln und dann anschließend von bin in byte ?

Bevor ich einen Fehler mache und irgendwelche Daten speichere und lösche (man kann soweit ich weiß nur ca. 100.000 mal löschen und speichern), wollte ich mich mal hier informieren.

Ich habe folgenden Code aus dem internationalen Forum von "A||SySt3msG0" gefunden, mit dem man beliebige Werte umformatieren und einspeichern kann:

//This function will write a 2 byte integer to the eeprom at the specified address and address + 1
void EEPROMWriteInt(int p_address, int p_value)
	{
	byte lowByte = ((p_value >> 0) & 0xFF);
	byte highByte = ((p_value >> 8) & 0xFF);

	EEPROM.write(p_address, lowByte);
	EEPROM.write(p_address + 1, highByte);
	}

//This function will read a 2 byte integer from the eeprom at the specified address and address + 1
unsigned int EEPROMReadInt(int p_address)
	{
	byte lowByte = EEPROM.read(p_address);
	byte highByte = EEPROM.read(p_address + 1);

	return ((lowByte << 0) & 0xFF) + ((highByte << 8) & 0xFF00);
	}

void setup()
	{
	Serial.begin(9600);

	EEPROMWriteInt(0, 0xABCD);

	Serial.print("Read the following int at the eeprom address 0: ");
	Serial.println(EEPROMReadInt(0), HEX);
	}

void loop()
	{
	}

Wie kann ich das so realisieren, dass jede 30. Minute mein Wert in den EEPROM speicher geschrieben wird ?
Kann ich wieder eine "Zeitscheibe" definieren und und sagen, wenn die Zeit exakt 1800s beträgt, dass dann mein Wert dann im EEPROM eingeschrieben wird ?

Also:

static unsigned long   Zeitscheibe = 0;
 if (millis() - Zeitscheibe == 1800000) {    // Zeitscheibe wird alle 1800000ms aufgerufen
    Zeitscheibe_1  = millis();
....
}

Ich arbeite ehrlich gesagt zum ersten mal mit den EEPROMs und dem Abspeichern, und habe echt Probleme, meinen ausgegebenen Wert im EEPROM abzuspiechern.
Bin noch ein richtiger Anfänger in dem Thema.
Wäre für jede Hilfe dankbar.

Wenn Du immer an die gleiche(n) Stelle(n) im EEPROM aller 30 Minuten speicherst, kommst Du mit den 100000 Schreibzyklen etwa auf 5,7 Jahre. Das sollte erst mal ausreichen.
Wenn DU was dauerhafteres willst, solltest Du über FRAM nachdenken (z.B. FM64C64B = 664 KBit = 8 KByte). Die behalten ihre Daten auch ohne Spannung weiter (lt. Hersteller 150 Jahre, was wohl nicht praktisch erprobt wurde) und können theoretisch beliebig oft geschrieben werden. Außerdem sind sie schneller, als EEPROM. Die gibt es auch als I2C-Ansteuerung.

Funktionen dazu mit Schreiben/Lesen beliebiger Datentypen, ohne dass Du Dich um den Aufbau kümmern mußt.
Die letzte Version steht im Beitrag #22. Beispiele in #10.

Gruß Tommy

Für EEProm gibt es eine Library in der IDE mit Beispielen.
Aber das EEProm ist für Messwerterfassung eher ungeeignet. Besser ist da eine SD-Karte (braucht aber Arduino Mega oder größer)

Aber wenns denn das EEPROM sein muss, dann nimm die Beispiele aus der Library und arbeite die durch.

Simulink20:
Wie kann ich das so realisieren, dass jede 30. Minute mein Wert in den EEPROM speicher geschrieben wird ?
Kann ich wieder eine "Zeitscheibe" definieren und und sagen, wenn die Zeit exakt 1800s beträgt, dass dann mein Wert dann im EEPROM eingeschrieben wird ?

Wenn das nur als Entwicklungsteste gedacht ist, um mal zu sehen, wie dein System arbeitet, dann lass dir doch die Werte auf den Seriellen Monitor ausgeben.
die kannst du da einfach ins Excel kopieren und dort grafisch, statistisch oder wie auch immer sonst auswerten.
Das ist viel aussagekräftiger als alle 30min einen zufälligen Wert abzuspeichern.

@Tommy56 vielen Dank ! Ich gucke mir die Beispiele einmal genauer an.

@jurs Du bist auch der einzige, der hier die ganze Zeit rummeckert und nicht verstehen will, was gemeint ist. Ich habe denke ich genug Informationen zu meinem Problem geliefert, um meine Nachfrage auch zu verstehen. Versprichst viel von dir, die du nicht selber halten willst. Die andern haben meine Frage auch verstanden und konnten all meine Informationen richtig interpretieren. Also brauchst du den Fehler nicht bei mir zu suchen, sondern bei dir. Anscheinend ließt du die Beiträge alle NICHT richtig ! Wenn du nicht Antworten willst, dann antworte einfach nicht; niemand zwingt dich zu etwas. Habe im Forum mehrere Beiträge von dir gelesen und überall bist du am Meckern. Setz dich hin und gönn dir nen Snickers.

@gunterb vielen Dank für die Rückmeldung. Ich arbeite leider gerade mit nem Arduino Uno.
Das ganze ist eher dafür Gedacht um die Kontrolle bestimmter Behälter im Auge zu behalten.

zB wenn ich nen aufblasbaren Pool benutze möchte ich, dass der Druck konstant bleibt. Wenn dadrin Kinder schwimmen könnten sie ja dagegen treten usw, wodurch sich mein Druck ändert. Über nen längeren Zeitraum kann man sich vorstellen, dass der Druck immer weiter sinkt.
Wenn ich den Mittelwert über einen längeren Zeitraum nehme und +/- 5 bar als Toleranzgrenze setze, könnte ich ja meiner Pumpe sagen, dass sie es weiter auffüllen sollen, bis man den gewünschten Wert wieder erreicht. Sonst über Excel wär das kein Problem :slight_smile:

Am besten würde ich den gleitenden Mittelwert vom Druck alle 30 Minuten im EEPROM abspeichern für 3h und mit den Werten dann meinen Mittelwert bilden, aber die Frage ist nur, wie ich die Ausgabe von der 30.Minute zB bzw alle 30 Minuten im EEPROM abspeichern kann.

Ja ein EEPROM hat zwar die write(); bzw die put(); Funktion aber ich wüsste nicht, wie ich die alle 30 Minuten die Daten hier abspeichern kann.
Ich hoffe ich konnte mich richtig ausdrücken :slight_smile:

Simulink20:
Ja ein EEPROM hat zwar die write(); bzw die put(); Funktion aber ich wüsste nicht, wie ich die alle 30 Minuten die Daten hier abspeichern kann.
Ich hoffe ich konnte mich richtig ausdrücken :slight_smile:

Naja, so wie du es oben beschrieben hast: in einer 30min Zeitscheibe.

Oder du lagerst die Zeitbedingung in die Funktion mit aus:

void EEpromschreiben(float wert){
  static unsigned long lasttime = 0;
  if (millis()-lasttime < 30 * 60* 1000) return;   // wenn die Zeit nicht erreicht ist, abbrechen.
  lasttime = millis();

  // prozedur zum EEProm schreiben
}

oder, wenn es dir wirklich nur um die Erkennung einer langsamen Druckänderung geht:
bilde einfach einen gleitenden Mittelwert mit einem Tau von 30min.
du kannst die Funktion aus antwort #3 ja einfach nochmal aufrufen:
Filtern(Mittelwert_30min, Drucksignal_raw, 900); // wird alle 2sek aufgerufen

Du könntest sogar das gefilterte Signal als Eingang für den nächsten Filter nehmen....

viele Wege führen nach Rom...

Vielen Dank gunterb,
das führt mich schonmal zum richtigen Weg.
Aber mit der Funktion würde das ab der 30. Minute Dauerbeschreiben oder nicht ? Dann hätte ich ja zu der 31,32,33,34....Minute auch meinen Speicher beschrieben. Möchte ja eher 30,60,90,120...

Simulink20:
Vielen Dank gunterb,
das führt mich schonmal zum richtigen Weg.
Aber mit der Funktion würde das ab der 30. Minute Dauerbeschreiben oder nicht ? Dann hätte ich ja zu der 31,32,33,34....Minute auch meinen Speicher beschrieben. Möchte ja eher 30,60,90,120...

Ich hatte das als alternative Szenarien skizziert, daher jeweils das oder dazwischen...

Simulink20:
wenn ich nen aufblasbaren Pool benutze möchte ich, dass der Druck konstant bleibt. Wenn dadrin Kinder schwimmen könnten sie ja dagegen treten usw, wodurch sich mein Druck ändert. Über nen längeren Zeitraum kann man sich vorstellen, dass der Druck immer weiter sinkt.
Wenn ich den Mittelwert über einen längeren Zeitraum nehme ...

Das habe ich so verstanden, dass du einen langsamen Durchschnittswert brauchst, der dir Druckänderungen über Stunden hinweg anzeigt.

Mein Vorschlag:
Löse dich von der Arduino-Ebene. Vergiss das programmieren.
denke einfach mal drüber nach, was genau du tun willst.

  • Welche Signale messen.
  • Wie bearbeiten?
  • Wann soll was aufgrund welcher Bedingung passieren?

Mir scheint du bist so in den Details der programmierung verfangen, dass du den Überblick darüber verlierst, was du eigentlich erreichen willst.

z.B.: wenn du den Druckabfall eines Planschbeckens voller tobender Kinder erfassen willst, warum willst du dann den Mittelwert über 8 Messungen?

static unsigned long lasttime = 0; wird nur beim ersten Aufruf der Funktion mit 0 initialisiert. Danach bleibt der in der Funktiopn gesetzte Wert erhalten.

Das static kannst Du Dir ungefähr so vorstellen, wie eine globale Variable, die nur in der Funktion sichtbar ist.

Gruß Tommy

Danke, Tommy.
Den Teil der Frage hatte ich nicht verstanden..... :confused:

@Tommy vielen Dank :slight_smile:

@guntherb:

Ich will meine Druckwerte messen.

Über eine längere Zeit, würde sich aber trotzdem mein Innendruck verändern. Nicht nur durch Stöße, sondern auch durch Sonneneinstrahlungen (Temperaturveränderungen - siehe ideales Gasgesetz).

Somit könnte ich einen krassen Temperaturauf- und abstieg haben.
Deswegen würde ich über einen längeren Zeitraum meinen Druck messen.

Ich will jedoch nicht kontinuierlich mit dem Drucksensor messen (Strom sparen) sondern hier in dem Beispiel jede 30.Minute, da meine Messungen auch Tage dauern können.
Sagen wir mal in der 30.Minute liegt mein Druck bei 30bar, 60.Minute bei 28bar, 90.Minute (jemand tritt dagegen) 50bar, 120.Minute bei 27bar und 180.Minute bei 25 bar. Mein Mittelwert würde somit bei 32bar liegen.

Jetzt kann ich gucken, ob mein Druck in der Toleranzgrenze liegt. Optimal wäre 30bar +/- 5bar. Wenn also mein Druck unter 25bar liegt, soll mein Arduino wissen, okay Druck nachfüllen. Wenn über 35bar, Druck rauslassen.

Das war mein Sinn und Zweck, warum ich den Mittelwert brauche.

ok, aber ob du alle 30min misst, oder alle 2 sec ist dem Arduino völlig egal.
Es ist genau das gleiche Prinzip
if (millis() - letzteMessung > Abstand).....
ob Abstand 30 min oder 30ms ist, macht doch keinen Unterschied!

Du hast doch weiter oben einen Sketch, der in Abständen Messungen macht und die Messungen mittelt.
Ich versteh' dein Problem nicht.

Simulink20:
Ich will jedoch nicht kontinuierlich mit dem Drucksensor messen (Strom sparen)

Wenn du Strom sparen willst, dann musst du nicht den den Sensor abschalten, sondern den Arduino. Aber das erfordert höhere Programmierkünste, und ist ein anderes Thema.

Achja, noch was:
wenn du ein stark schwankendes Signal hast (tobende Kinder) und einen langfristigen Mittelwert haben willst, reicht es nicht sporadisch zu messen, sondern du musst kontinuierlich messen, so dass du möglichst viele Messwerte hast um daraus dann einen vernünftigen Mittelwert zu bekommen.

Um das klarer zu machen:
eine stark streuenden Größe wird gemessen (blau). Der mathematische Mittelwert ist bei 27, Schwankung maximal +/-2.
daraus wird mit obiger Funktion ein Mittelwert gebildet (FF=100) (gelb). Man sieht gut, dass er recht gut der Mittellinie folgt.
Zusätzlich wird alle 30 zyklen ein Wert genommen. Man kann gut sehen, dass es wirklich zufällig ist, wie das Signal an dieser Stelle grad ist. Aus diesen Messwerten wird dann (jeweils aus den letzten acht) ein Mittelwert gerechnet.


Klar ersichtlich: der "Mittelwert" aus den sporadischen Messungen hat mit der realität nichts zu tun.