Messwerte und Zeit in Array speichern und anschließend auslesen

Hallo,

ich lese über einen Analogeingang eine Spannung ein. Diese soll alle 50 ms gespeichert werden. Messung dauert ca. 3 s, also 60 Messwerte.

Ich will hierbei einmal die Zeit und den dazugehörigen Wert speichern.

Bsp.:
0 ms - 2,11 V
50 ms - 2.1 V
100 ms - 2,15 V
150 ms - 2,12 V
.
.
.
2950 ms - 2,16 V
3000 ms - 2,12 V

Da die Messung immer unterschiedlich lang dauert (zwischen 2-3 s), soll immer der Wert bei 70 % der gesamten Messdauer ausgegeben werden.

Bsp.
2550 ms - 2,15 V

Ich stehe hier leider auf dem Schlauch und weiß nicht wie ich es hinbekomme mit den Arrays.

Danke euch!

Hello ardu04

Poste am Besten den aktuellen Sketch mit Kommentaren und in Code-Tags.

Woher weisst Du wie lange die Messung tatsächlich dauert?
Wenn Du das als Vorgabe hast, dann kannst Du aus der Zeit die 70% Grenze errechnen und dann die dazu gehörigen Werte ausgeben lassen.

Wenn die Zeit der Messung aufgrund eines Endwertes errechnet wird, dann kannst Du den Zähler der Messungen direkt verwenden und ausgehend vom letzten Zählerwert die 70% Grenze errechnen.

wozu willst du die "Zeit" erfassen?
Wenn du alle 50ms misst, dann ist die Zeit jeweils um 50ms höher.

Woher hast du einen Zeitstempel für die Zeit?

Wenn das geklärt ist, könntest du dir eine Struktur anlegen.

struct Datapoint
{
  int16_t value;
  uint32_t time;
};
Datapoint datapoint[65];

Wenn die Messwerte stabil sind, dann ist die Messung vorbei. Es handelt sich um einen Temperaturwiderstand der erwärmt wird, von Raumtemperatur auf eine definierte Wassertemperatur (bsp. von 20 Grad auf 50 Grad).
Diese Zeit wird gemessen und ist je nach Temperatursensor unterschiedlich.

Habe leider erst die Zeit nach der Messung und will von dieser dann einen Wert ausgeben.

Die Spannung verringert sich also. Nicht so wie von mir erst beschrieben, dass sie nahezu konstant ist…

Ah......
Das wird dann aber schwieriger.
Denn wenn Dir vorher nicht bekannt ist, wann die Messung allerspätestens zu Ende ist, dann kennst Du auch nicht die tatsächliche Anzahl der aufzunehmenden Werte.

Könnte es Dir - ausgehend von #1 - auch passieren, das die Messung 3,5 Sekunden dauert? Oder gar 4? Oder noch mehr?

Wenn Du das array statisch beschreiben willst, dann musst Du vorher wissen, wie hoch die Anzahl der Elemente sein soll.

Es ginge auch, das die Elemente regelmäßig überschrieben werden. Stichwort: Ringspeicher.
Aber wenn Du auf die Position 70% zugreifen willst, muss auch da sichergestellt sein, das Du immer den Punkt Ende der Messung - 30% nicht verlierst.
Mit steigender Anzahl Messungen, wird das Element immer genauer - und damit steigt auch die Anforderung an den zu merkenden Werten.

Wenn Du 10 Werte hast, ist 70% der Wert 7.
Bei 100 Werten ist es der Wert 70.
Das ist einfach.
Mach das mal für 9 und für 90 Werte.

Was ist "stabil"? Das könnte dann auch begründen das die Zeiten mit aufgenommen werden.
Wenn Du nämlich nur die Temperaturänderungen aufnimmst, dann brauchst Du die Zeit dazu.
Die 70% werden dann anhand der Zeit ermittelt und dann dazu passend aus dem Array das Element in der Näherung gesucht.
Bedingt aber trotzdem, das Du irgendwie vorher weißt, wann (zwangsweise) Schluß ist und die Anzahl der Elemente irgendwie festlegbar ist.

Heißt das, der Sensor befindet sich in der Luft und wird dann ins Wasser getaucht? Und Du willst verschiedene Sensoren bzgl. ihrer Reaktionszeit vergleichen? Wo wird entschieden, dass die Messwerte stabil sind und die Messung vorbei ist? Oder ist das Dein Wunsch an das Arduiono Programm?

Hallo,

dann mach das Array doch groß genug, z.B 150.Elemente dann recht das für 7,5s Letztlich wird sich eine Messkurve ergeben die einer Verzögerung 2. Ordnung ziemlich nahe kommt. Wenn sich die Werte nicht mehr ändern hast Du den stationären Endzustand erreicht. Nun musst Du ausgehend von Anfangs und Endwert Deine 70 % ( vermutlich 63%) ausrechnen und festtellen nach welcher Zeit (index *50ms) die erreicht sind um so die Zeitkonstante des Sensors zu ermitteln.
Und wo ist jetzt das Problem ?

Heinz

// Forensketch Messwerte und Zeiten erfassen und auswerten
// https://forum.arduino.cc/t/messwerte-und-zeit-in-array-speichern-und-anschliessend-auslesen/
/*
   Was dieser Sketch macht:
   Es werden je nach Voreinstellung alle Elemente gefüllt,
   oder nur die Elemente bis keine Änderung mehr.
   Die Ermittlung der Werte erfolgt durch mehrfache Messung und Ermittlung eines Mittelwertes.
   Dabei wird jeweils ein Ausreisser nach oben und nach unten gelöscht.
   Sind alle Elemente gefüllt, bzw. keine Wertänderung mehr, dann Ausgabe

  ungetestet - kompiliert fehlerfrei
*/

#include <Streaming.h>     // https://github.com/janelia-arduino/Streaming

//#define DEBUG              // Wenn aktiviert, werden Zwischenwerte ausgegeben
#define ALLMESS            // Wenn aktiviert, wird jeder Messwert aufgenommen, bis array voll

#ifdef DEBUG
#define DBG_PRINTLN(...) Serial << __VA_ARGS__ << endl
#else
#define DBG_PRINTLN(...)
#endif

constexpr uint8_t analogInPin = A0;                            // Hier wird gemessen
constexpr uint8_t messIntervall = 50;                          // Zeiten in ms
constexpr uint16_t maxMessZeit = 5000;                         //
constexpr uint8_t numElemente = maxMessZeit / messIntervall;   // Berechnung der maximalen Anzahl Elemente
struct Messung                                                 // Es gehört zusammen
{
  uint32_t messZeit;
  uint16_t messWert;
} messung[numElemente];                                        // Array festlegen
uint32_t lastMessung;                                          // letzte Messzeit
uint8_t messElement = 0;                                       // Zähler

void setup()
{
  Serial.begin(115200);
#if (defined(ARDUINO_AVR_MEGA) || defined(ARDUINO_AVR_MEGA2650)) // https://github.com/arduino/Arduino/issues/10764
  delay(300);
#endif
  Serial << (F("\r\nStart...\r\n")) << endl;
  DBG_PRINTLN(__FILE__);
  DBG_PRINTLN( __TIMESTAMP__);
  digitalWrite(LED_BUILTIN, LOW);                              // onBoard-LED zur Kontrolle
  pinMode(LED_BUILTIN, OUTPUT);                                // aktivieren
  lastMessung = millis();                                      // vorbelegen
}

void loop()
{
  messen(messIntervall);
  if ((messElement >= numElemente) ||                                         // Array ist voll ODER
      (messElement != 0 && millis() - messung[0].messZeit >= maxMessZeit) ||  // maximale Messzeit erreicht ODER
      ((millis() - messung[messElement - 1].messZeit) / messIntervall > 10))  // Messungen ohne Veränderung ODER
  {
    auswerten();                                                              // ausgeben
  }
  heartbeat(1000);                                                            // Kontrolle ob der noch läuft...
}

void auswerten()
{
  Serial << (F("Ausgabe aller " )) << messElement << (F(" erfassten Werte")) << endl;
  for (byte b = 0; b < messElement; b++)
  {
    Serial << _WIDTH(b + 1, 5);                                               // Elementnummer
  }
  Serial.println();
  for (byte b = 0; b < messElement; b++)
  {
    Serial << _WIDTH(messung[b].messZeit - messung[0].messZeit, 5);           // Messzeit Abstand
  }
  Serial.println();
  for (byte b = 0; b < messElement; b++)
  {
    Serial << _WIDTH(messung[b].messWert, 5);                                 // Messwert
  }
  Serial.println();
  uint16_t lastElement = messElement - 1;
  uint32_t grenzTime = (messung[lastElement].messZeit - messung[0].messZeit) * 70 / 100;
  DBG_PRINTLN (F("gesamte Messzeit: ") << messung[lastElement].messZeit - messung[0].messZeit << " ms ");
  DBG_PRINTLN(F("70 Prozent: ") << grenzTime << " ms" << endl);
  for (byte b = 0; b < messElement; b++)
  {
    if (messung[b].messZeit - messung[0].messZeit > grenzTime)
    {
      Serial << F("oberer 70 Prozent Grenzwert bei Element ") << b << ": " << messung[b].messWert << endl;
      if (b != 0)
      {
        Serial << F("unterer 70 Prozent Grenzwert bei Element ") << b - 1 << ": " << messung[b - 1].messWert << endl;
      }
      b = messElement;
    }
  }
  messElement = 0;
}

uint16_t findValue(uint8_t anzahl)                          // ermittelt den Analogwert aus Anzahl Messungen
{
  uint16_t minWert = 1024;                                  // Für Ermittlung von Ausreisser nach unten
  uint16_t maxWert = 0;                                     // ... nach oben
  uint16_t myValue = 0;                                     //
  for (uint8_t b = 0; b < anzahl; b++)                      //
  {
    uint16_t readValue = analogRead(analogInPin);           // Messwert aufnehmen
    if (readValue > maxWert) maxWert = readValue;           // Oberen Messwert erfassen
    if (readValue < minWert) minWert = readValue;           // Unteren Messwert erfassen
    myValue += readValue;                                   // Messwert aufsummieren
  }
  if (anzahl > 2)                                           // Nur wenn ...
  {
    myValue -= (minWert + maxWert);                         // oberen und unteren "Ausreisser" abziehen
    anzahl -= 2;                                            // berichtigen
  }
  return (myValue / anzahl);                                // errechnen und zurück geben
}

void messen(const uint32_t intervall)                       //
{
  uint16_t value = 0;
  bool isNew = false;
  const byte valueNumbers = 12;
  if (millis() - lastMessung >= intervall)                  // Zeit abgelaufen?
  {
    messElement == 0 ? lastMessung = millis() : lastMessung += intervall; // Merker setzen
    value = findValue(valueNumbers);                        // Messwert ermitteln mit Anzahl der Messungen
#ifdef ALLMESS                                              // Wenn das define oben gesetzt
    // Variante A: - Jeder Messwert wird aufgenommen
    isNew = true;
#else                                                       // Wenn nicht gesetzt
    // Variante B: - Messwert wird nur aufgenommen, wenn geändert
    if ((messElement == 0) ||                               // Erstes Element wird zwingend gefüllt
        (messung[messElement - 1].messWert != value))       // Letzter Eintrag unterscheidet sich?
    {
      isNew = true;
    }
#endif
  }
  if (isNew)                                                // Wenn neuer Wert erkannt wurde
  {
    messung[messElement].messZeit = millis();               // aktuelle Zeit aufnehmen
    messung[messElement].messWert = value;                  // Messwert
    DBG_PRINTLN(messElement << " " << messung[messElement].messZeit << " " << messung[messElement].messWert);
    messElement++;                                          // nächstes Element aktivieren
  }
}

void heartbeat(const uint32_t blinkTime)
{
  static uint32_t lastblink = 0;
  if (digitalRead(LED_BUILTIN) &&
      (millis() - lastblink > blinkTime / 2))
  {
    digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
  }
  else if (millis() - lastblink > blinkTime)
  {
    digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
    lastblink = millis();
  }
}

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.