(Layout verändert, Kommentare gefärbt) |
|||
| Zeile 9: | Zeile 9: | ||
=== Header === | === Header === | ||
;FloatingAverage.h | ;FloatingAverage.h | ||
| − | |||
| − | |||
| − | |||
| − | #include <inttypes.h> | + | #ifndef FLOATING_AVERAGE_H |
| + | #define FLOATING_AVERAGE_H | ||
| + | |||
| + | #include <inttypes.h> | ||
| + | |||
| + | {{ccomment|Ueber wieviele Werte soll der gleitende Mittelwert berechnet werden?}} | ||
| + | {{ccomment|Zulaessige Werte 1..255}} | ||
| + | #define SIZE_OF_AVG 8 | ||
| + | |||
| + | {{ccomment|Datentyp, ueber den der gleitende Mittelwert berechnet werden soll.}} | ||
| + | typedef uint16_t tFloatAvgType; | ||
| + | {{ccomment|typedef float tFloatAvgType;}} | ||
| + | |||
| + | {{ccomment|Wird nur intern fuer die Durchschnittsberechnung benutzt.}} | ||
| + | {{ccomment|Muss Zahlen fassen koennen, die SIZE_OF_AVG mal groesser als tFloatAvgType sind.}} | ||
| + | typedef uint32_t tTempSumType; | ||
| + | {{ccomment|typedef float tTempSumType;}} | ||
| + | |||
| + | {{ccomment|Die Struktur, in der die Daten zwischengespeichert werden}} | ||
| + | typedef struct | ||
| + | { | ||
| + | tFloatAvgType aData[SIZE_OF_AVG]; | ||
| + | uint8_t IndexNextValue; | ||
| + | } tFloatAvgFilter; | ||
| + | |||
| + | |||
| + | {{ccomment|Initialisiert das Filter mit einem Startwert.}} | ||
| + | void InitFloatAvg(tFloatAvgFilter * io_pFloatAvgFilter, | ||
| + | tFloatAvgType i_DefaultValue); | ||
| + | |||
| + | {{ccomment|Schreibt einen neuen Wert in das Filter.}} | ||
| + | void AddToFloatAvg(tFloatAvgFilter * io_pFloatAvgFilter, | ||
| + | tFloatAvgType i_ui16NewValue); | ||
| + | |||
| + | {{ccomment|Berechnet den Durchschnitt aus den letzten SIZE_OF_AVG eingetragenen Werten.}} | ||
| + | tFloatAvgType GetOutputValue(tFloatAvgFilter * io_pFloatAvgFilter); | ||
| + | |||
| + | #endif | ||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
=== Quellcode === | === Quellcode === | ||
;FloatingAverage.c | ;FloatingAverage.c | ||
| − | + | ||
| − | #include "FloatingAverage.h" | + | #include "FloatingAverage.h" |
| + | |||
| + | void InitFloatAvg(tFloatAvgFilter * io_pFloatAvgFilter, | ||
| + | tFloatAvgType i_DefaultValue) | ||
| + | { | ||
| + | {{ccomment|Den Buffer mit dem Initialisierungswert fuellen:}} | ||
| + | for (uint8_t i = 0; i < SIZE_OF_AVG; ++i) | ||
| + | { | ||
| + | io_pFloatAvgFilter->aData[i] = i_DefaultValue; | ||
| + | } | ||
| + | {{ccomment|Der naechste Wert soll an den Anfang des Buffers geschrieben werden:}} | ||
| + | io_pFloatAvgFilter->IndexNextValue = 0; | ||
| + | } | ||
| + | |||
| + | |||
| + | void AddToFloatAvg(tFloatAvgFilter * io_pFloatAvgFilter, | ||
| + | tFloatAvgType i_NewValue) | ||
| + | { | ||
| + | {{ccomment|Neuen Wert an die dafuer vorgesehene Position im Buffer schreiben.}} | ||
| + | io_pFloatAvgFilter->aData[io_pFloatAvgFilter->IndexNextValue] = | ||
| + | i_NewValue; | ||
| + | {{ccomment|Der naechste Wert wird dann an die Position dahinter geschrieben.}} | ||
| + | io_pFloatAvgFilter->IndexNextValue++; | ||
| + | {{ccomment|Wenn man hinten angekommen ist, vorne wieder anfangen.}} | ||
| + | io_pFloatAvgFilter->IndexNextValue %= SIZE_OF_AVG; | ||
| + | } | ||
| + | |||
| + | |||
| + | tFloatAvgType GetOutputValue(tFloatAvgFilter * io_pFloatAvgFilter) | ||
| + | { | ||
| + | tTempSumType TempSum = 0; | ||
| + | {{ccomment|Durchschnitt berechnen}} | ||
| + | for (uint8_t i = 0; i < SIZE_OF_AVG; ++i) | ||
| + | { | ||
| + | TempSum += io_pFloatAvgFilter->aData[i]; | ||
| + | } | ||
| + | {{ccomment|Der cast is OK, wenn tFloatAvgType und tTempSumType korrekt gewaehlt wurden.}} | ||
| + | tFloatAvgType o_Result = (tFloatAvgType) (TempSum / SIZE_OF_AVG); | ||
| + | return o_Result; | ||
| + | } | ||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
=== Anwendungsbeispiel === | === Anwendungsbeispiel === | ||
Hier folgt ein Beispiel, das die Anwendung in einem PC-Konsolen-Programm demonstriert | Hier folgt ein Beispiel, das die Anwendung in einem PC-Konsolen-Programm demonstriert | ||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | + | #include <stdio.h> | |
| − | + | #include "FloatingAverage.h" | |
| − | + | ||
| − | + | int main(void) | |
| + | { | ||
| + | {{ccomment|Datenstruktur anlegen:}} | ||
| + | tFloatAvgFilter FilterVoltageBatt; | ||
| + | |||
| + | {{ccomment|initialisieren und mit 0 fuellen}} | ||
| + | InitFloatAvg(&FilterVoltageBatt, 0); | ||
| + | |||
| + | AddToFloatAvg(&FilterVoltageBatt, 100); | ||
| + | {{ccomment|jetzt steht 1 mal 100 und 7 mal 0 im Buffer:}} | ||
| + | printf("100/8 = %d\n", GetOutputValue(&FilterVoltageBatt)); | ||
| + | |||
| + | AddToFloatAvg(&FilterVoltageBatt, 200); | ||
| + | {{ccomment|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); | ||
| + | {{ccomment|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; | ||
| + | } | ||
| − | |||
| − | |||
| − | |||
[[Kategorie:Quellcode C]] | [[Kategorie:Quellcode C]] | ||
Version vom 5. November 2009, 11:25 Uhr
| 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;
}