Guten Morgen Searcher,
dein Oszilloskopbild habe ich mal vergrößert und ausgedruckt und mit dem Lineal gemessen.
Hier ist eindeutig zu erkennen, dass die Messwerte erheblich schwanken.
Da Du anscheinend wenig RAM zur Verfügung hast, wäre ein Softwarefilter (Tiefpass) angebracht.
Ich hab mal in mühsamer Kleinarbeit einen Tiefpass geschrieben, der ohne Floats auskommt
und auch keinen Puffer benötigt, da er in Echtzeit (Samplegenau) funktioniert.
Der Code ist absolut trivial, aber entspricht exakt einem RC-Tiefpass und lässt sich sehr einfach anpassen.
Zunächst mal einige Erläuterungen dazu:
Das Entscheidende ist die Abtastrate (Samplerate) also wieviele Messwerte kommen pro Sekunde
und die Centerfrequenz (Fc) des Filters.
Beispiel bei mir:
Mein ADU liefert 1000 Messwerte pro Sekunde, das ist also die Abtastrate
Die Centerfrequenz (Fc) ist die Frequenz an dem die Amplitude um 3 Dezibel fällt wenn man eine
Sinusschwingung durch den Filter schickt.
Um sich unnötige (komplizierte) Berechnungen zu ersparen, kann mein Controller eh nicht
habe ich "vorab" einen Faktor benannt mit "D" berechnet.
Dieser Wert wird nur einmal (extern, Taschenrechner) berechnet und abgelegt.
Da ich keine floats habe, wird der Wert vorher noch mit 65536 multipliziert
So kann ich auch Nachkommastellen berücksichtigen
Ich habe den Code inzwischen in Pascal und C implementiert, aber ich denke das sollte kein Problem sein
ihn nach (sieht aus wie Basic ?) zu konvertieren.
Die Funktion ist für 32 Bit Integer ausgelegt
In Basic musst Du vermutlich den Typ long nehmen für 32 Bit
Dreh und Angelpunkt ist die Vorabberechnung bzw. der Wert von "D"
D:=1-exp(-(2*pi*Fc) / Samplerate);
Hier kannst Du aber auch ganz experimentell Werte probieren und schauen wie es sich verhält.
Die "C" Variante
Code:
/*---------------------------------------------------------------------------*/
/* Siro's Spezialfunktion für einen Softwarefilter Tiefpass */
/* simuliert exakt ein ganz normales R/C Glied */
/* D:=1-exp(-(2*pi*Fc) / Samplerate); */
/* Fc ist die Centerfrequenz, der -3dB Punkt */
/* dann den Wert noch mit 65536 multiplizieren, wegen Integer Berechnungen < 0 */
/* Bezogen auf eine Abtastrate von 1000 Hz (1KHz) ergeben sich folgende Werte */
/* D = 21 ==> Fc = 0.05 Hz */
/* D = 41 ==> Fc = 0.1 Hz */
/* D = 206 ==> Fc = 0.5 Hz */
/* D = 410 ==> Fc = 1 Hz */
/* D = 818 ==> Fc = 2 Hz */
/* D = 2026 ==> Fc = 5 Hz */
/* D = 3991 ==> Fc = 10 Hz */
/* D = 7739 ==> Fc = 20 Hz */
/* D = 17668 ==> Fc = 50 Hz */
/* D = 30573 ==> Fc = 100 Hz */
/* D = 46884 ==> Fc = 200 Hz */
/* D = 62704 ==> Fc = 500 Hz */
S32 flowFilter(S32 value)
{ const S32 d = 206; // LowPassFilter Fc=0.5 Hz at 1000 Hz Samplerate
static S32 n = 0;
static S32 rest = 0;
S32 xx;
value = value - n;
xx = value * d;
rest = (xx+rest) % 65536; // % ist MOD Modulo (Divisionsrest) in "C"
xx = (xx+rest) / 65536;
n = n + xx;
return n;
}
/*---------------------------------------------------------------------------*/
Die "Pascal" Variante:
Code:
{------------------------------------------------------------------------------}
// !!!!! die mit const deklarierten Variablen
// müssen "statisch lokal" sein oder "global"
// sie müssen also erhalten bleiben nach dem Verlassen der Funktion
// in Pascal kann man das mit Const erzwingen.
Function FilterTP(value:Integer):Integer; // Tiefpass
const d : Integer = 206; // LowPassFilter Fc=0.5 Hz at 1000 Hz Samplerate
const n : Integer = 0;
const rest : Integer = 0;
var xx : Integer = 0;
begin
value:= value - n;
xx := value * d; // d ist ja schon mit 65536 multipliziert
rest := (xx + rest) MOD 65536; // wir muessen jetzt durch 65536 teilen
xx := (xx + rest) DIV 65536; // und den jeweiligen rest uns merken
n := n + xx;
result:=n;
end;
{------------------------------------------------------------------------------}
Der Aufruf erfolgt mit
Messwert:=FilterTP(Messwert); // durch den Filter jagen
Ausgabe(Messwert); // hier dann anzeigen
Du kannst einfach mit dem Wert für "D" herum experimentieren,
je kleiner der Wert wird, umso ruhiger wird auch deine Anzeige, aber auch träger.
PS.: Die Variablen innerhalb der Funktion solltest Du vermutlich "GLOBAL" definieren, ich hab nicht gefunden dass Basic statische lokale Variablen kann...
Einfach mal den D Wert irgendwie setzen und vor deiner Anzeige des Messwertes diesen durch den Filter schicken.
Siro
Hier mal ein Beispiel was er aus meinem verrauschten Signal macht: die grüne Kurve ist die gefilterte mit obigen Code.
Hier habe ich den D-Wert vergößert: es wird etwas unruhiger, aber dafür schnellere Reaktionszeit
Lesezeichen