Go Down

Topic: Median von 600 Werten (Read 185 times) previous topic - next topic

DaDaVee

Hallo Leute,

ich stehe gerade vor einen Verständnisproblem.

Ich möchte mit dem Arduino Mega Druckdaten aufnehmen.
Nach einer vorgegebenen Zeit soll der Druck mit 1Hz über 10 Minuten aufgezeichnet werden und schließlich daraus der Median gebildet werden. Das ganze soll möglichst schnell ablaufen.

Habe mir jetzt mal die Library RunningMedian.h (http://playground.arduino.cc/Main/RunningMedian) runtergeladen aber diese noch nicht ganz verstanden.
Zum test habe ich einfach ein Poti an A0 angeklemmt und mir das ganze auf ein Display anzeigen lassen. Jedoch wird der Median nicht über 600 Werte genommen sondern von keine Ahnung wie vielen.
Kann mir jemand helfen was ich wo ändern muss, um meinen Median über eine beliebige Anzahl an Werten zu berechnen?

Code: [Select]
#include <RunningMedian.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#define MEDIAN_SIZE 600

LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  // Set the LCD I2C address

RunningMedian samples = RunningMedian(600);


void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  Serial.print("Verstrichene Zeit [s]: ");
  Serial.print("\t");
  Serial.println("Spannung Drucksensor: ");
  lcd.begin(20,4);         // initialize the lcd for 20 chars 4 lines, turn on backlight
  lcd.backlight(); // finish with backlight on

}

float SpDrSe;
float DruckMittel = 0;
float sum = 0;
float DruckArr[10];
float DruckMedian[600];
int k =0;
float p=0;




void loop() {
  for (int k = 0; k < 600; k++) {
    // put your main code here, to run repeatedly:
    float t = millis() / 1000.00;
    int DruckSensor = analogRead(A0);

    SpDrSe = 5.000 * DruckSensor / 1024.000; //Spannung Drucksensor
   

    for (int i = 0; i < 10; i++) {
      DruckArr[i] = 5.000 * analogRead(A0) / 1024.000; // Mittelwert über 10 Werte bilden
      delay(10);                                 // Abtastung mit 10 Hz
    }

    for (int j = 0; j < 10; j++) {
      sum = sum + DruckArr[j];                  // Mittelwert berechnen
    }
    DruckMittel = sum / 10;                     // Mittelwert berechnen
    p= DruckMittel * 41/10;

    // LCD Display
lcd.setCursor(0,0);
lcd.print("Spannung = ");
lcd.setCursor(11,0);
lcd.print(DruckMittel,3);
lcd.setCursor(17,0);
lcd.print("V");

lcd.setCursor(0,1);
lcd.print("Druck: ");
lcd.setCursor(7,1);
lcd.print(p,3);


lcd.setCursor(0,2);
lcd.print("Zeit = ");
lcd.setCursor(7,2);
lcd.print(t);
lcd.setCursor(14,2);
lcd.print("s");



   
    sum = 0;
    samples.add(DruckMittel);
    float m = samples.getMedian();
    DruckMedian[k]=DruckMittel;
   
    Serial.print(t);
    Serial.print("\t");
    Serial.print(DruckMittel, 4);
    Serial.print("\t");
    Serial.println(m,2);
   
   
   
    if (k == 599){
    Serial.println("Median ueber 600 Werte: ");
    Serial.println(DruckMedian [k]);
   
    k=0;
   lcd.clear();
   lcd.setCursor(0,3);
   lcd.print("Median600: ");
   lcd.setCursor(11,3);
   lcd.print(m,2);
    }
    }

  }

DrDiettrich

Du kennst den Unterschied zwischen Mittelwert und Median?

Für den Median brauchst Du einen Arduino mit genügend RAM, um die benötigten Werte zu speichern.

DaDaVee

Ja kenne ich. Und ich benötige aber den Median. Der Mega genügend Ram.

michael_x

Quote from: github.com/RobTillaart
RunningMedian(const uint8_t size);
RunningMedian(600) ist wohl nicht so ganz passend. 
Wird vermutlich effektiv einen RunningMedian(88) ergeben.



Theseus

#4
Jun 13, 2018, 06:29 pm Last Edit: Jun 13, 2018, 06:30 pm by Theseus
Oder mit anderen Worten, die Lib ist nur bis 255 Werte geeignet. Wenn du mehr verarbeiten willst, musst du ausprobieren, ob sie nach ersetzen mit uint16_t wie gewünscht funktioniert. Dann ist die Zahl der Elemente praktisch nur durch die Ram-Größe begrenzt.

Tommy56

600 * 4 Byte = 2400 Byte nur für das Array. Da wird es wohl mindestens ein MEGA werden müssen.

Gruß Tommy
"Wer den schnellen Erfolg sucht, sollte nicht programmieren, sondern Holz hacken." (Quelle unbekannt)

postmaster-ino

Hi

Was heißt 'möglichst schnell' bei einer Wartezeit von 10 Minuten?

Wenn Du nur diese eine Aufzeichnung brauchst und KEINEN runningMedian - reichen Dir 300 Werte im Speicher.

Array mit 300 Elementen nullen
Bei jedem Messwert von der Mitte beginnen und prüfen, ob
- die aktuelle Stelle 0 ist -> Messwert dort eintragen, fertig
- die aktuelle Stelle > dem Messwert ist --> eine Stelle nach unten --> sind wir bereits an Stelle 0, ALLE Stellen 1x nach oben schieben, Messwert an Stelle 0 eintragen
... Gleiches, bei < dem Messwert in entgegen gesetzter Richtung

So 'wandern' die kleinen Messwerte nach links, die Großen nach Rechts.
ALLES, was größer als der 300.ste Messwert ist, wird verworfen, da eh 'zu weit rechts'.

Nach 600 Messwerten sollte der Median an unserer Stelle 300 stehen (bzw. Mittelwert zw. 299 & 300).

Da dir Sortiererei während der Aufnahme geschieht (alle Sekunde), hast Du nach Ende der Messung als einzige Warterei das Auslesen des Wertes an Stelle 300 - sollte man mit leben können.

MfG

Go Up