Forum: Compiler & IDEs uint16_t wertearray shiften


von Norbert S. (norton)


Lesenswert?

Hallo, ich hätte bezüglich Arrays einige Fragen, und hoffe daß Ihr mir 
weiterhelfen könnt.

System:
ATmega48
AVR Studio
GCC

Anforderung;
Ich möchte eine bestimmte Anzahl an Messdaten eines Sensors in ein Array 
schreiben den kleinsten und den größten Wert entfernen und anschließend 
den Mittelwert bilden. Jedesmal wenn ein neuer Wert dazukommt soll der 
älteste Wert aus dem Array entfernt werden.

Bsp.: Messwerttabelle ist 8 groß
Wertetabelle: 8; 20; 27; 21; 22; 21; 23; 22;
Auswertung: 20; 21; 22; 21; 23; 22;  --> 21(,5)
neuer Wert: (8 fällt raus) 20; 27; 21; 22; 21; 23; 22; 23
Auswertung:
.
.

Fragen:
Kann man in ein Array die Messwerte reinshiften oder muss man jedes mal 
alle Werte selbst um eine Stelle verschieben?

Gibt es fertige Funktionen für das Auffinden von min bzw max Werten in 
einem Array?

Ich hoffe ihr könnt mir helfen einen relativ optimalen Code zu 
produzieren.

von Johannes M. (johnny-m)


Lesenswert?

So was machst Du mit einem Ringspeicher und einem Zeiger, der auf den 
aktuell ältesten Wert zeigt. Wenn ein neuer Wert reinkommt, an der 
Stelle speichern, auf die der Zeiger zeigt und den Zeiger entsprechend 
erhöhen. Wenn Du am Ende des Arrays angekommen bist, muss der Zeiger 
entsprechend wieder auf den Anfang gesetzt werden.

Für die Auswertung einfach jeweils das komplette Array in einer Schleife 
durchgehen (mit Index).

von Norbert S. (norton)


Lesenswert?

@Johannes M.

Wenn ich das richtig verstanden habe entspricht der "Ringspeicher" einem 
Array. Ich verschiebe allerdings nicht die Werte sondern nur einen 
zeiger wo der älteste Wert zum überschreiben steht.
Oder gibt es da eine spezielle definition und handhabung für einen 
Ringspeicher"?

von Johannes M. (johnny-m)


Lesenswert?

Norbert S. wrote:
> Wenn ich das richtig verstanden habe entspricht der "Ringspeicher" einem
> Array. Ich verschiebe allerdings nicht die Werte sondern nur einen
> zeiger wo der älteste Wert zum überschreiben steht.
Im Prinzip ist es genau das. Der "Ring" entsteht eben dadurch, dass 
nicht mehr mit den echten Array-Grenzen im Speicher gearbeitet wird, 
sondern dass ein Zeiger definiert, wo gerade der (virtuelle) Anfang bzw. 
das Ende des Arrays ist. Wenn der Zeiger eine der echten Array-Grenzen 
erreicht, muss er eben wieder an das andere Ende befördert werden.

> Oder gibt es da eine spezielle definition und handhabung für einen
> Ringspeicher"?
Eigentlich nicht... Es gibt aber ne Menge Beispiele. Ringspeicher werden 
z.B. gerne als Puffer für irgendwelche Sende- und Empfangsroutinen 
benutzt, wenn Zeichenfolgen verarbeitet werden sollen und nicht 
gewährleistet ist, dass die einzelnen Zeichen sofort nach Eintreffen 
bearbeitet werden können. Sollte im AVR-GCC-Tutorial und in der 
Codesammlung ein paar Anhaltspunkte geben...

von Norbert S. (norton)


Lesenswert?

Hat irgendjemand einen Beispielcode, der ein Array als Ringspeicher 
benutzt, bei der Hand? Es genügt auch irgend ein Link mit so einem 
Beispiel.
Bei der Suche habe ich meistens nur ein Register als Puffer gefunden. 
Oder ich suche nach den falschen Stichworten.

Ihr würdet mir sehr helfen wenn ich nicht alles für mich neu erfinden 
muss.

von Karl H. (kbuchegg)


Lesenswert?

Was spricht gegen die gute alte Methode: Papier und Bleistift.
So kann man mal so ein Array aufeichnen und die Funktionsweise
durchschauen. Dann kommt man drauf, dass das eigentlich ziemlich
simpel ist:
1
#define MAX_WERTE 8
2
uint16_t Werte[ MAX_WERTE ];
3
uint8_t NextAdd;
4
5
void Add( uint16_t Wert )
6
{
7
  Werte[NextAdd] = Wert;
8
  NextAdd++;
9
  if( NextAdd == MAX_WERTE )
10
    NextAdd = 0;
11
}

Der Index NextAdd geht reihum und zeigt an, wo der nächste Wert
einzufügen ist. Ist er am Ende des Arrays angekommen, fängt
er wieder von vorne an und sorgt so dafür, daß immer der älteste
Wert überschrieben wird.

> Gibt es fertige Funktionen für das Auffinden von min bzw max
> Werten in einem Array?

Sowas wirst du ja wohl noch selbst schreiben können :-)
Falls nicht: Hier eine Funktion, die den kleinsten Wert
bestimmt
1
uint16_t min()
2
{
3
  uint8_t i;
4
  uint16_t tmp;
5
6
  tmp = Werte[0];
7
  for( i = 1; i < MAX_WERTE; ++i )
8
    if( Werte[i] < tmp )
9
      tmp = Werte[i];
10
11
  return tmp;
12
}

> relativ optimalen Code
Wenn du relativ optimalen Code haben willst, dann machst du deine
Auswertung nicht mit getrennten min, max und summe Funktionen, sondern
alles in einem Rutsch durch das Array.

von Norbert S. (norton)


Lesenswert?

Danke an alle!

Ich habe bei Zeiger irgendwie an Pointer usw.. gedacht und bin deshalb 
irritiert gewesen.

Die Funktionen (Funktion) für min, max, usw. waren eh nicht das problem, 
es hätte ja sein können das es da Funktionen gibt. Bin halt etwas 
verwöhnt von anderen Programmiersprachen.

von Rolf Magnus (Gast)


Lesenswert?

> Ich habe bei Zeiger irgendwie an Pointer usw.. gedacht und bin deshalb
> irritiert gewesen.

Das war ja auch gemeint. Der Beispielcode verwendet zwar einen Index, 
aber das geht mit einem Zeiger natürlich genauso.

von Norbert S. (norton)


Lesenswert?

Meine Lösung für die Messwerttabelle sieht nun so aus:
1
#define MW_SIZE 10
2
3
uint16_t mw_array[MW_SIZE];
4
uint8_t aeltester_wert_zeiger = 0;
5
6
uint16_t mw_tabelle( uint16_t Wert )
7
{
8
  mw_array[aeltester_wert_zeiger] = Wert;
9
  aeltester_wert_zeiger++;
10
  if (aeltester_wert_zeiger == MW_SIZE)
11
  {
12
    aeltester_wert_zeiger = 0;
13
  }
14
15
  uint8_t i = 0;
16
  uint16_t min = 0;
17
  uint16_t max = 0;
18
  uint16_t summe = 0;
19
  uint16_t schnitt = 0;
20
21
  min = mw_array[0];
22
  max = mw_array[0];
23
  summe = mw_array[0];
24
  for (i = 1; i < MW_SIZE; i++)
25
  {
26
    if(mw_array[i] < min )
27
      min = mw_array[i];
28
29
    if(mw_array[i] > max )
30
      max = mw_array[i];
31
32
    summe += mw_array[i];
33
  }
34
  schnitt = (summe - min - max) / (MW_SIZE - 2);
35
36
  return schnitt;
37
}

Danke nochmals für eure Hilfe!

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.