Forum: Mikrocontroller und Digitale Elektronik aus Funktion ins Array schreiben


von MasterBrained (Gast)


Lesenswert?

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

von Einer K. (Gast)


Lesenswert?

Vermutlich suchst du einen Ringbuffer.

von sid (Gast)


Lesenswert?

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

von sid (Gast)


Lesenswert?

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

von foobar (Gast)


Lesenswert?

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
}

von M. K. (sylaina)


Lesenswert?

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 = ... ;)

von foobar (Gast)


Lesenswert?

> 1. Durchlauf: (0+1)%10 = 9

Das solltest du noch mal überdenken ;-)

von M. K. (sylaina)


Lesenswert?

Hm, stimmt. Ich hatte da ne andere Funktion im Kopf, % ist ja der 
Modulo-Operator in C

von Alex (Gast)


Lesenswert?

Mh, schöne Funktion. Könntest du erklären wieso beim return Value 
nocheinmal 5 addiert werden müssen, bevor durch 10 dividiert wird?

von Cyblord -. (cyblord)


Lesenswert?

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

von W.S. (Gast)


Lesenswert?

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.

von W.S. (Gast)


Lesenswert?

Nachtrag: i auf irgend einen Index im Feld. Nicht unbedingt auf 0.
W.S.

von HildeK (Gast)


Lesenswert?

@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
Noch kein Account? Hier anmelden.