(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; }