- fchao-Sinus-Wechselrichter AliExpress         
Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 10 von 14

Thema: Gleitender Mittelwert Arduino

  1. #1

    Gleitender Mittelwert Arduino

    Anzeige

    Praxistest und DIY Projekte
    Hallo,

    ich möchte mit dem Arduino den gleitenden Mittelwert einer Datenreihe mithilfe von einem Array ausrechnen.
    Es sind ca. 6000 Werte, wobei immer der Durchschnitt der letzten 255 Werte berechnet werden soll.
    Da ich mich mit Arrays nicht so auskenne, bräuchte ich auch den Code dazu.

    Vielen Dank für eure Hilfe.

    Grüße
    TobiasE

  2. #2
    So,
    hab es jetzt n paar Stündchen probiert und bin auf folgendes gekommen:

    int werte[254];
    int i,j = 0;
    int summe;

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

    void loop() {
    werte[i] = analogRead(0);
    i++;
    if(i = 255) {
    i = 0;
    }
    delay(100);
    durchschnitt();
    summe = 0;
    j = 0;

    }

    void durchschnitt() {
    while(j < 255) {
    summe += werte[j];
    j++;
    }
    Serial.println(summe / 255);
    }

    Es gibt aber falsche Werte aus, die unmöglich stimmen können.
    Wo ist der Fehler?

    thx

  3. #3
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    27.08.2013
    Ort
    Region Basel
    Alter
    66
    Beiträge
    2.435
    Hallo,

    int werte[254];

    Hat 254 Plätze, es sollten aber 255 sein!
    In werte[255] steht ein Zufallswert.
    Also
    int werte[255];

    Angesprochen wird das Array dann mit werte[0] bis werte[254]

    Beim ersten Aufruf von durchschnitt() steht in summe auch ein Zufallswert.

    Tipp:
    Code:
    #define BUFFER_SIZE 255
    int werte[BUFFER_SIZE];
    
    
    for (j=0; j < BUFFER_SIZE; j++)
    {
      // mach was
    }
    Variante:
    Code:
    int werte[255];
    #define BUFFER_SIZE (sizeof(werte) / sizeof(werte[0]) )
    
    // sizeof(werte) liefert den Speicherplatz für das ganze Array in Bytes
    // sizeof(werte[0]) liefert den Speicherplatz für ein einzelnes Array-Element in Bytes
    
    // Die Klammer um den ganzen Ausdruck ist prinzipiell nicht nötig, kann aber schwer zu findende Bugs verhindern.
    // z.B.
    // #define BUFFER_SIZE sizeof(werte) / sizeof(werte[0])
    // ++BUFFER_SIZE
    // würde der Compiler nach
    // (sizeof(werte)+1) / sizeof(werte[0]) 
    // auflösen und eben nicht nach
    // (sizeof(werte) / sizeof(werte[0]))+1
    Das passt dann immer, auch wenn du die Array-Grösse mal ändern willst

    MfG Peter(TOO)
    Geändert von Peter(TOO) (29.02.2016 um 01:09 Uhr) Grund: tippfehler im Code
    Manchmal frage ich mich, wieso meine Generation Geräte ohne Simulation entwickeln konnte?

  4. #4
    Neuer Benutzer Öfters hier
    Registriert seit
    11.10.2013
    Beiträge
    11
    ...und du solltest auf deine "summe" Obacht geben.
    Die ist bei dir wohl vom Type int, somit kann die auf den normalen Arduinos nur rund 32000 groß werden.
    Deine summe kann aber bis zu 1023 * 255 = 260865 groß werden!
    Dann halt lieber unsigned long für die summe nehmen, dann hat das Platz!

  5. #5
    HaWe
    Gast
    außer, sein Arduino hat einen ARM Prozessor (Zero, Due), dann hat int von vornherein die Größe 32-bit. 8-)

  6. #6
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    13.01.2014
    Beiträge
    454
    Blog-Einträge
    3
    Und noch ein Klassiker im Code:
    Code:
    if(i = 255) { i=0; }
    Es ist wohl gemeint:
    Code:
    if(i == 255) ...
    Dieser Fehler verursacht, dass i erstmal auf 255 gesetzt wird. Damit ist i ungleich null, somit der Ausdruck in der Klammer wahr, und der Code i=0 wird ausgeführt. i ist also nachher immer null.
    Tipp:
    Bei 256 Werten ein Byte als Typ benutzen. Wenn der Wert dann 255 ist und um eins erhöht wird, fängts automatisch wieder bei null an.

  7. #7
    Erstmal vielen Dank für die Hilfe.
    Das ist der fertige Code:

    int werte[255];
    int i,j = 0;
    unsigned long summe;

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

    void loop() {
    werte[i] = analogRead(0);
    i++;
    if(i == 255) {
    i = 0;
    }
    delay(100);
    durchschnitt();
    }

    void durchschnitt() {
    summe = 0;
    j = 0;
    while(j < 255) {
    summe += werte[j];
    j++;
    }
    float schnitt = summe / 255;
    Serial.println(schnitt);
    }

    Klappt alles wie es soll!
    Nach 25,5 Sekunden wird dann der korrekte Mittelwert angezeigt.
    Danke nochmal

    TobiasE

  8. #8
    HaWe
    Gast
    warum delay(100) ? wenn das so sein muss, ok!
    aber sonst: analogRead braucht nur ca. 1ms zum auslesen, und dafür wartet es von alleine!


    - HaWe

    - - - Aktualisiert - - -

    ps
    ein "gleitender Durchschnitt" geht aber anders ... und schneller.... und ganz ohne Arrays...!

  9. #9
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    27.08.2013
    Ort
    Region Basel
    Alter
    66
    Beiträge
    2.435
    Hallo,
    Zitat Zitat von HaWe Beitrag anzeigen
    ein "gleitender Durchschnitt" geht aber anders ... und schneller.... und ganz ohne Arrays...!
    Ohne Array?
    Ich habe das immer mit einem Ringbuffer gemacht.


    Pseudo Code:
    Summe -= ringbuffer[oldest];
    Summe += new_data;

    ringbuffer[oldest] = new_data;
    ringbuffer_index++;


    MfG Peter(TOO)
    Manchmal frage ich mich, wieso meine Generation Geräte ohne Simulation entwickeln konnte?

  10. #10
    HaWe
    Gast
    ja, Ringpuffer ist natürlich perfekt und auch perfekt auf die Stichprobengröße angepasst.

    Angenähert geht es aber auch mit dem gleitenden Mittelwert per Lowpass-Filter, damit bekommt man bis auf ein paar unerhebliche Nachkommastellen das gleiche Ergebnis:

    float ETA=0.95; // ETA anfangs festlegen, ggf. noch justieren, kann auch bei 0.90 oder 0.99 liegen=> rumprobieren!
    Mittelwert = ETA*(Messwert) + (1-ETA)*Mittelwert;

    Dann spart man sich die extrem langsamen Array-Operationen und den Speicher dafür. Allerdings sind es dann nicht exakt 255 Werte, die gemittelt werden, sondern nur größenordnungsmäßig was in der Art.
    Aber:
    man kann ja auch die obige Formel benutzen, und dabei bis 255 zählen,
    dann den Mittelwert ablesen,
    und dann wieder neu starten.
    Aber: er gleitet, mit minimalem Aufwand.
    Geändert von HaWe (01.03.2016 um 09:50 Uhr) Grund: blödsinnige Tippfehler

Seite 1 von 2 12 LetzteLetzte

Ähnliche Themen

  1. RMS - Mittelwert?
    Von BlackDevil im Forum Elektronik
    Antworten: 10
    Letzter Beitrag: 27.06.2008, 20:27
  2. mittelwert von 24V pulsen = 18V ??
    Von Bibiman im Forum Elektronik
    Antworten: 14
    Letzter Beitrag: 22.03.2007, 13:50
  3. Gleitender Durchschnitt
    Von teslanikola im Forum Software, Algorithmen und KI
    Antworten: 5
    Letzter Beitrag: 06.01.2006, 11:23
  4. Effektivwert Gleichrichtwert Mittelwert
    Von slaud im Forum Elektronik
    Antworten: 2
    Letzter Beitrag: 15.11.2005, 00:40
  5. befehl für mittelwert?
    Von Bluesmash im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 8
    Letzter Beitrag: 29.07.2005, 16:12

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

fchao-Sinus-Wechselrichter AliExpress