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