| Dieser Artikel ist noch lange nicht vollständig. Der Auto/Initiator hofft das sich weitere User am Ausbau des Artikels beteiligen.
Das Ergänzen ist also ausdrücklich gewünscht! Besonders folgende Dinge würden noch fehlen: viel mehr erklärender Text |
Inhaltsverzeichnis
Verwendung
Um beispielsweise verrauschte Messwerte zu glätten, wird häufig der Mittelwert über die letzten gemessenen Werte gebildet. Details dazu hier: [1]
C-Code
Auf Optimierungen, inline-Funktionen etc. wurde vorerst zugunsten der Lesbarkeit verzichtet.
Header
- FloatingAverage.h
#ifndef FLOATING_AVERAGE_H
#define FLOATING_AVERAGE_H
#include <inttypes.h>
// Ueber wieviele Werte soll der gleitende Mittelwert berechnet werden?
// Zulaessige Werte 1..255
#define SIZE_OF_AVG 8
// Datentyp, ueber den der gleitende Mittelwert berechnet werden soll.
typedef uint16_t tFloatAvgType;
// typedef float tFloatAvgType;
// Wird nur intern fuer die Durchschnittsberechnung benutzt.
// Muss Zahlen fassen koennen, die SIZE_OF_AVG mal groesser als tFloatAvgType sind.
typedef uint32_t tTempSumType;
// typedef float tTempSumType;
// Die Struktur, in der die Daten zwischengespeichert werden
typedef struct
{
tFloatAvgType aData[SIZE_OF_AVG];
uint8_t IndexNextValue;
} tFloatAvgFilter;
// Initialisiert das Filter mit einem Startwert.
void InitFloatAvg(tFloatAvgFilter * io_pFloatAvgFilter,
tFloatAvgType i_DefaultValue);
// Schreibt einen neuen Wert in das Filter.
void AddToFloatAvg(tFloatAvgFilter * io_pFloatAvgFilter,
tFloatAvgType i_ui16NewValue);
// Berechnet den Durchschnitt aus den letzten SIZE_OF_AVG eingetragenen Werten.
tFloatAvgType GetOutputValue(tFloatAvgFilter * io_pFloatAvgFilter);
#endif
Quellcode
- FloatingAverage.c
#include "FloatingAverage.h"
void InitFloatAvg(tFloatAvgFilter * io_pFloatAvgFilter,
tFloatAvgType i_DefaultValue)
{
// Den Buffer mit dem Initialisierungswert fuellen:
for (uint8_t i = 0; i < SIZE_OF_AVG; ++i)
{
io_pFloatAvgFilter->aData[i] = i_DefaultValue;
}
// Der naechste Wert soll an den Anfang des Buffers geschrieben werden:
io_pFloatAvgFilter->IndexNextValue = 0;
}
void AddToFloatAvg(tFloatAvgFilter * io_pFloatAvgFilter,
tFloatAvgType i_NewValue)
{
// Neuen Wert an die dafuer vorgesehene Position im Buffer schreiben.
io_pFloatAvgFilter->aData[io_pFloatAvgFilter->IndexNextValue] =
i_NewValue;
// Der naechste Wert wird dann an die Position dahinter geschrieben.
io_pFloatAvgFilter->IndexNextValue++;
// Wenn man hinten angekommen ist, vorne wieder anfangen.
io_pFloatAvgFilter->IndexNextValue %= SIZE_OF_AVG;
}
tFloatAvgType GetOutputValue(tFloatAvgFilter * io_pFloatAvgFilter)
{
tTempSumType TempSum = 0;
// Durchschnitt berechnen
for (uint8_t i = 0; i < SIZE_OF_AVG; ++i)
{
TempSum += io_pFloatAvgFilter->aData[i];
}
// Der cast is OK, wenn tFloatAvgType und tTempSumType korrekt gewaehlt wurden.
tFloatAvgType o_Result = (tFloatAvgType) (TempSum / SIZE_OF_AVG);
return o_Result;
}
Anwendungsbeispiel
Hier folgt ein Beispiel, das die Anwendung in einem PC-Konsolen-Programm demonstriert
#include <stdio.h>
#include "FloatingAverage.h"
int main(void)
{
// Datenstruktur anlegen:
tFloatAvgFilter FilterVoltageBatt;
// initialisieren und mit 0 fuellen
InitFloatAvg(&FilterVoltageBatt, 0);
AddToFloatAvg(&FilterVoltageBatt, 100);
// jetzt steht 1 mal 100 und 7 mal 0 im Buffer:
printf("100/8 = %d\n", GetOutputValue(&FilterVoltageBatt));
AddToFloatAvg(&FilterVoltageBatt, 200);
// jetzt steht 1 mal 100, 1 mal 200 und 6 mal 0 im Buffer:
printf("300/8 = %d\n", GetOutputValue(&FilterVoltageBatt));
AddToFloatAvg(&FilterVoltageBatt, 300);
AddToFloatAvg(&FilterVoltageBatt, 200);
// jetzt steht 1 mal 100, 2 mal 200, 1 mal 300 und 4 mal 0 im Buffer:
printf("800/8 = %d\n", GetOutputValue(&FilterVoltageBatt));
return 0;
}