Hallo zusammen, ich habe eine Reihe aufeinanderfolgender Integer-Werte, u[i], die ich tiefpassfiltern will, d.h. die Anstiegs- und Abstiegsgeschwindigkeit soll begrenzt werden. Allerdings soll das Integral über alle Werte erhalten bleiben. Oder im diskreten Fall: Die Summe. Wenn der Eingang z.B. so aussähe: u[] = {0, 0, 10, 100, 40, 11, 0, 0, 0, 0, 0} und ein Anstieg von 40 erlaubt ist, könnte der Ausgang y[i] so aussehen: y[] = {0, 0, 10, 50, 90, 50, 10, -30, -9, 0, 0} Das zu implementieren sollte keine Schwierigkeit sein. Man benötigt im einfachsten Fall eine Akkumulator-Variable und ein paar Regeln für den Ausgang. Allerdings stört der negative Überschwinger etwas. Deswegen zwei Fragen: a) Gibt es für diese Klasse von Filtern einen Namen? b) Gibt es in dieser Klasse von Filtern Varianten ohne Überschwinger?
:
Bearbeitet durch User
Walter T. schrieb: > Deswegen zwei Fragen: > a) Gibt es für diese Klasse von Filtern einen Namen? Was würde das helfen? Auf jeden Fall ist es kein einfaches Tiefpassfilter, dass durch eine einfache Zeitkonstante beschrieben werden kann. Slew Rate Begrenzer würde die Sache vielleicht noch halbwegs beschreiben. Bei einem Clipping der Slew Rate kannst du aber nicht erwarten, dass das Integral unverändert bleibt. Stell dir einfach ein Sägezahnsignal vor. Die langsame Flanke kommt unverändert durch, auf der steilen Flanke wird abgeschnitten. Das Filter wird sogar nichtlinear, i.e. die Übertragungsfunktion hängt von der Signalamplitude ab.
Wolfgang schrieb: > Auf jeden Fall ist es kein einfaches Tiefpassfilter, dass durch eine > einfache Zeitkonstante beschrieben werden kann Da bin ich mir nicht so sicher. Es sieht nach einem direkten Komplement zum I-Glied aus. Ein gleitender Mittelwert ohne Rundungsfehler hätte diese Erhaltungseigenschaft übrigens auch. Wolfgang schrieb: > Was würde das helfen? Da sich schon viele schlaue Köpfe mit Signalverarbeitung und Regelungstechnik befasst haben, und viele davon Bücher und Artikel geschrieben haben, um ihr Wissen zu teilen, gilt es diesen Schatz zu finden. Das geht am besten dann, wenn man den Namen dessen weiß, was man sucht.
:
Bearbeitet durch User
Walter T. schrieb: > ich habe eine Reihe aufeinanderfolgender Integer-Werte, > u[i], die ich tiefpassfiltern will, d.h. die Anstiegs- > und Abstiegsgeschwindigkeit soll begrenzt werden. > Allerdings soll das Integral über alle Werte erhalten > bleiben. Oder im diskreten Fall: Die Summe. Das wäre ein Allpass: Verändert nur die Phase, nicht aber die Amplitude der Spektralkomponenten. > Wenn der Eingang z.B. so aussähe: > > u[] = {0, 0, 10, 100, 40, 11, 0, 0, 0, 0, 0} Summe: 161 > und ein Anstieg von 40 erlaubt ist, könnte der Ausgang > y[i] so aussehen: > > y[] = {0, 0, 10, 50, 90, 50, 10, -30, -9, 0, 0} Summe: 171 :) > Das zu implementieren sollte keine Schwierigkeit sein. > Man benötigt im einfachsten Fall eine Akkumulator-Variable > und ein paar Regeln für den Ausgang. Allerdings stört der > negative Überschwinger etwas. > > Deswegen zwei Fragen: > a) Gibt es für diese Klasse von Filtern einen Namen? Welche "diese"? Ich fürchte, dass Deine Randbedingungen bis jetzt noch zu viel Spielraum lassen. Ein Filter, das die Summe der Eingangswerte unverändert lässt, lässt einfach nur den Gleichanteil unverändert, und das leistet jeder Tiefpass, der bei f=0 die Verstärkung "Eins" hat. Nun enthält Deine Beispielfolge keine negativen Werte. Was soll dann passieren? Wäre eine Umsetzung von {0,50,100,0,-50,-100} auf {0,0,0,0,0,0} akzeptabel? Die Summe der Werte bleibt ja erhalten. Ist der Gleichanteil das richtige Maß, oder soll nicht vielmehr die Summe der Quadrate (=die Energie) erhalten bleiben? > b) Gibt es in dieser Klasse von Filtern Varianten ohne > Überschwinger? Im stetigen sind die (unüblichen) Gauss-Filter ganz und die Bessel-Filter nahezu ohne Überschwinger. M.W. ist auch der ungewichtete gleitende Mittelwert frei von Überschwingern. Ich sehe aber das Problem, dass es keinen Sinn hat, für beliebige Eingangsfolgen die Erhaltung der Energie zu fordern, weil dann logischerweise nur Allpässe in Frage kommen. Jedes "echte" Filter soll ja bestimmte Spektralbereiche dämpfen. Von Überschwingern im strengen Sinne freie Allpässe können m.M.n. nur Laufzeitleitungen sein, und die helfen Dir ja nicht weiter. Ich denke, dass alles, was Flanken beeiflusst, bereichsweise einen nichtlinearen Phasengang haben muss, und das verursacht bereichsweise Überschwinger.
Walter T. schrieb: > Ein gleitender Mittelwert ohne Rundungsfehler hätte > diese Erhaltungseigenschaft übrigens auch. Ja... was ich nicht verstehe: Welche Eigenschaft benötigst Du, die der gleitende Mittelwert NICHT hat?
Egon D. schrieb: > Welche Eigenschaft > benötigst Du, die der gleitende Mittelwert NICHT hat? Die Erhaltung der Summe. Führe ich den gleitenden Mittelwert auf Integer mit N Stützstellen aus, kann der Rundungsfehler bis zu N*(N-1) betragen. Auf Anhieb fällt mir auch kein Korrekturterm ein, der dieses Problem beheben würde. Egon D. schrieb: > Ist der Gleichanteil das richtige Maß, Ja. Egon D. schrieb: > und das leistet jeder Tiefpass, > der bei f=0 die Verstärkung "Eins" hat. Im kontinuierlichen Fall ja. Im diskreten Fall spucken mir die Rundungsfehler in die Suppe. Egon D. schrieb: > Wäre eine Umsetzung von > {0,50,100,0,-50,-100} auf {0,0,0,0,0,0} akzeptabel? Das wäre sogar das gewünschte Verhalten. Hintergrund: Ich habe eine Regelung, die bei berechneten Sollwertvorgaben sehr stabil läuft. Beim Handradbetrieb über einen Drehgeber lassen sich jedoch leicht Regelschwingungen provozieren. Jetzt sehe ich zwei Lösungsmöglichkeiten: a) Im Handbetrieb die Kreisverstärkung massiv zurücknehmen. b) Eine Art "virtuelles Schwungrad" am Drehgeber vorsehen. a) ist einfach zu realisieren, bewirkt aber eine Haptik wie eine mittlere Weinbergschnecke. Jetzt will ich b) probieren.
:
Bearbeitet durch User
wenn du sowieso mit Integer arbeitest, kannst du doch fehlerfrei arbeiten. Im Akkumulator dann nicht den Durchschnittswert vorhalten, sondern die Gasamtsumme, und nur für die Ausgabe teilen/runden.
Walter T. schrieb: > Die Erhaltung der Summe. Führe ich den gleitenden Mittelwert auf Integer > mit N Stützstellen aus, kann der Rundungsfehler bis zu N*(N-1) betragen. Nö, das sicher nicht. Der Rundungsfehler eines gleitenden Mittelwertes von N Integern ist natürlich < 1. Und obendrein völlig unabhängig von N.
c-hater schrieb: > Walter T. schrieb: > >> Die Erhaltung der Summe. Führe ich den gleitenden Mittelwert auf Integer >> mit N Stützstellen aus, kann der Rundungsfehler bis zu N*(N-1) betragen. > > Nö, das sicher nicht. Der Rundungsfehler eines gleitenden Mittelwertes > von N Integern ist natürlich < 1. Und obendrein völlig unabhängig von N. Mist. Mus natürlich <= 1 heissen.
Walter T. schrieb: > Egon D. schrieb: >> Welche Eigenschaft >> benötigst Du, die der gleitende Mittelwert NICHT hat? > > Die Erhaltung der Summe. Führe ich den gleitenden > Mittelwert auf Integer mit N Stützstellen aus, kann > der Rundungsfehler bis zu N*(N-1) betragen. Auf Anhieb > fällt mir auch kein Korrekturterm ein, der dieses > Problem beheben würde. Ich habe aus dem Stand auch keine Lösung -- glaube aber fest an die Lösbarkeit :) Folgender Denkansatz: Man stellt sich beim gleitenden Mittel immer vor, dass man zuerst die ganzen Zahlen addiert und anschließend durch die Anzahl teilt, und dabei bleiben halt Nachkommastellen übrig. Ich schlage vor, die Reihenfolge im Geiste umzudrehen und jeden einzelnen Abtastwert in den ganzen Anteil des Quotienten [a_n/N] und den (ganzzahligen) Rest zu zerlegen. Der ganze Anteil des gleitenden Mittelwertes ergibt sich (in erster Näherung) erstmal aus der Summe der ganzen Anteile aller dividierten Abtastwerte. Das ist nicht problematisch. Gesucht ist eine (adaptive) Strategie, wie man die Reste auf die Ausgabewerte aufteilt. Schätzungsweise sollte man die Reste akkumulieren und bei Überschreiten bestimmter Schwellwerte den Ausgabe- wert erhöhen und den Reste-Akku entsprechend korrigieren. Akkumulation von Rundungsfehlern kann dabei nicht auftreten, weil ja (bisher) nicht gerundet wird.
Beitrag #5839142 wurde von einem Moderator gelöscht.
Nachtrag: Egon D. schrieb: > Gesucht ist eine (adaptive) Strategie, wie man die > Reste auf die Ausgabewerte aufteilt. > Schätzungsweise sollte man die Reste akkumulieren und > bei Überschreiten bestimmter Schwellwerte den Ausgabe- > wert erhöhen und den Reste-Akku entsprechend korrigieren. Möglicherweise funktioniert eine viel einfachere Strategie: Wenn Divisionsrest k auftritt, dann werden die k jüngsten Reste incrementiert. Es ist ja für die Summe egal, ob ein Ausgabewert umd k Digit oder k Ausgabewerte um ein Digit vergrößert werden. Vorausgesetzt wird, dass das FIR-Filter als Warteschlange aufgefasst wird, d.h. dass nicht der mittlere, sondern der letzte (älteste) Wert aus Ausgabewert verwendet wird. Da bei einer Filterlänge von N der größte Rest (N-1) ist, wird höchstens der zweitälteste Rest incrementiert, aber nie der älteste. Zur Ausgabe wird einfach zur gleitenden Summe der älteste "Rest" addiert, das Resultat ausgegeben, und von der Summe der älteste ganze Anteil subtrahiert.
Guten Morgen, wenn man eine Nacht darüber geschlafen hat, sieht es eigentlich ganz einfach aus. Man muß eigentlich nur den Rest mitschleppen. So funktioniert es dann auch:
1 | #define N_FIR_ORDER 5
|
2 | |
3 | int32_t firConservative(int32_t u) |
4 | {
|
5 | static int32_t merker[N_FIR_ORDER]; |
6 | static int64_t summe = 0; |
7 | summe -= merker[N_FIR_ORDER-1]; |
8 | memcpy( &(merker[1]), &(merker[0]), (N_FIR_ORDER-1)*sizeof(int32_t)); |
9 | merker[0] = u; |
10 | summe += u; |
11 | |
12 | int32_t y = summe/N_FIR_ORDER; // Noch ziemlich teuer |
13 | int32_t rest = summe%N_FIR_ORDER; |
14 | summe += rest; |
15 | merker[0] += rest; |
16 | return y; |
17 | }
|
18 | |
19 | |
20 | |
21 | TEST(filter_fiir, conservative) |
22 | {
|
23 | // Warteschlange leeren
|
24 | for( int i = 0; i < N_FIR_ORDER; i++) |
25 | firConservative(0); |
26 | |
27 | // Gefilterte Werte
|
28 | int32_t y = 0; |
29 | y = firConservative(10); |
30 | y += firConservative(20); |
31 | y += firConservative(30); |
32 | y += firConservative(-10); |
33 | |
34 | // Warteschlange leeren
|
35 | for( int i = 0; i < N_FIR_ORDER; i++) |
36 | {
|
37 | y+= firConservative(0); |
38 | }
|
39 | |
40 | TEST_ASSERT_EQUAL( 50, y ); |
41 | }
|
Danke für die Denkanstöße!
:
Bearbeitet durch User
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.