Guten Tag, Ich bin noch ein Anfänger was programmieren am µC angeht und habe deshalb folgende Frage: Ich habe eine Funktion die mir Messwerte liefert über den Parameter value. Ich möchte in einem Array nun die letzen 10 Messungen speichern. Es soll immer der älteste Messwert aktualisiert werden. Anschließend soll der Mittelwert berechnet werden. Leider verzweifle ich an der genauen herangehensweise dieses Problemes. In der Theorie ist es mir zwar klar wie es zu machen wäre, leider weiss ich nicht wie ich es auch programmieren kann. Ich hoffe auf Unterstützung :) MfG, MB
bei zehn Messwerten klingt mir das schwer nach rauschunterdrückung.. da würd ich immer tatsächlich zehn Ablesungen nehmen (also das komplette array vollschreiben) Aber nundenn, wenn Du immer nur einen Messwert aktualisieren möchtest geht das natürlich auch; da Du für den Mittelwert keinen UNterschied bei der Reihenfolge machen musst am einfachsten in etwa so:
1 | int buffer[10]={0}; // das array, zunächst null gefüllt |
2 | int arpt = 0; // array_pointer für später |
3 | float mean =0; // der Mittelwert |
4 | |
5 | void readSensor() |
6 | {
|
7 | // int value = analogRead(SensorPin);
|
8 | // oder wie auch immer Du den WErt liest
|
9 | buffer[arpt] = value; |
10 | arpt = (arpt+1)%10 ; // zähle hoch von 0-9 und wiederhole; dies nur ein einzelschritt natürlich |
11 | }
|
12 | |
13 | void setup () |
14 | {
|
15 | // buffer schonmal mit werten füllen um ein Anfangsmittelwert zu haben
|
16 | for(int i=0, i<10; i++) |
17 | readSensor(); |
18 | // und was auch immer Du sonst so brauchst
|
19 | }
|
20 | |
21 | void loop() |
22 | {
|
23 | // readSensor();
|
24 | // und wann immer Du den Mittelwert brauchst
|
25 | int sum; |
26 | for(int i=0; i<10; i++) |
27 | sum += buffer[i]; |
28 | mean = sum/10.0; // .0 zwingt den compiler die dezimalstelle zu beachten |
29 | // was immer Du mit dem mittelwert tun möchtest
|
30 | |
31 | // willst Du unbedingt "ersten" und "letzten" Wert gesondert behandeln
|
32 | // wird es nur minimal komplizierter:
|
33 | for (int i =0; i<10; i++) |
34 | {
|
35 | if((arpt > 0 && i == arpt-1)|| (arpt==0 && i==9)) |
36 | {
|
37 | // der erste 'älteste' Wert
|
38 | sum += 5; // was auch immer |
39 | }
|
40 | else if (arpt==i) |
41 | {
|
42 | // der letzte 'neueste' Wert
|
43 | sum += 2* buffer[i]; // was auch immer |
44 | }
|
45 | else
|
46 | {
|
47 | // alle Anderen Werte
|
48 | sum += bugger[i]; // was auch immer |
49 | }
|
50 | // wie Du hier addierst ist Dir überlassen
|
51 | }
|
52 | // mean ist summe durch 10kommanull du weisst schon ;)
|
53 | }
|
So in etwa jdf.. hab's jetzt nur hingespuckt, könnten also Tippfehler und sogar logikfehler drin sein geht ja nur um's Prinzip, gell? Achso, ich weiss jetzt nicht wie gross deine values sind, oder von welchem Typ (ich gehe von 10bit integer aus.. dann ist alles gut) solltest du floats brauchen, oder besonders grosse Werte addieren, musst Du natürlich die Typen anpassen. 'sid
ups, blödsinn.. der älteste WErt ist arpt plus eins, nciht minus eins.. da ist schon der erste Logikfehler :( achja 5-uhr morgens, das Hirn ist Brei.. verzeih 'sid
1 | // give it a new value, returns the average of the last 10 given values
|
2 | int average(int val) |
3 | {
|
4 | static int last[10], i, sum; |
5 | |
6 | sum -= last[i]; |
7 | last[i] = val; |
8 | sum += last[i]; |
9 | |
10 | if (++i == 10) |
11 | i = 0; |
12 | |
13 | return (sum + 5) / 10; |
14 | }
|
sid schrieb: > arpt = (arpt+1)%10 ; // zähle hoch von 0-9 und wiederhole; dies nur ein > einzelschritt natürlich Das würde ich noch mal überdenken: arpt beim Start sei 0 1. Durchlauf: (0+1)%10 = 9 2. Durchlauf: (9+1)%10 = 0 3. Durchlauf: (0+1)%10 = ... ;)
> 1. Durchlauf: (0+1)%10 = 9
Das solltest du noch mal überdenken ;-)
Hm, stimmt. Ich hatte da ne andere Funktion im Kopf, % ist ja der Modulo-Operator in C
Mh, schöne Funktion. Könntest du erklären wieso beim return Value nocheinmal 5 addiert werden müssen, bevor durch 10 dividiert wird?
Alex schrieb: > Mh, schöne Funktion. Könntest du erklären wieso beim return Value > nocheinmal 5 addiert werden müssen, bevor durch 10 dividiert wird? Rundung
MasterBrained schrieb: > Ich habe eine Funktion die mir Messwerte liefert über den Parameter > value. > Ich möchte in einem Array nun die letzen 10 Messungen speichern. Es soll > immer der älteste Messwert aktualisiert werden. Anschließend soll der > Mittelwert berechnet werden. > > Leider verzweifle ich an der genauen herangehensweise dieses Problemes. So, du verzweifelst daran, daß du dein Problem nicht präzise formulieren kannst? Dann mußt du daran arbeiten - und das hat rein garnichts mit Programmieren zu tun, sondern mit Strategie. Beispiel: Du hast ein Feld mit 10 Einträgen, dazu eine Variable mit der Summe aus allen Einträgen und obendrein eine Laufvariable, die von 1 bis 10 (oder 0 bis 9) läuft. Wie also machst du es, daß du dein Feld aktualisierst und den Mittelwert aus ihm berechnest? Denk nach. Der älteste muß raus aus der Summe und dafür der neueste rein. Mal ne Formulierung aus dem Handgelenk: variable Summe; feld Wertefeld[1..10]; integer i; wenn neuerWertDa dann begin Summe:= Summe - Wertefeld[i]; // alter Wert raus Wertefeld[i]:= NeuerWert; Summe:= Summe + Wertefeld[i]; // neuer Wert rein increment(i); if i > 10 then i:= 1; Mittelwert:= Summe / 10; end Und zu den Startbedingungen: Du füllst vorher i, Summe und Wertefeld mit null. Dein Algorithmus hat FIR Charakteristik, also nach 10 Meßwerten ist es eingeschwungen. Das Prinzip dahinter solltest du jetzt verstanden haben - und die Umsetzung in irgend eine Programmiersprache sollte jetzt kein Problem mehr sein. Merke: das Wichtigste beim Programmieren ist, sich über die Strategie, also die Herangehensweise und prinzipielle Durchführung klar zu werden. Das Codieren ist dann erst der zweite Schritt. W.S.
Nachtrag: i auf irgend einen Index im Feld. Nicht unbedingt auf 0. W.S.
@MasterBrained (Gast) Ein Tipp: Wenn du nicht unbedingt auf die 10 Elemente angewiesen bist und ggf. auch 8 oder 16 verwenden kannst, machst du es deinem µC etwas einfacher, die Division durchzuführen. Die Addition zur Rundung musst du dann anpassen: 4 oder 8 addieren vor der Division durch 8 bzw. 16.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.