Forum: Mikrocontroller und Digitale Elektronik Gedankenanstoß Messwertauswertung


von Peter der Kleine (Gast)


Lesenswert?

Hallo Leute,

ich habe da gerade ein kleines Problem bei dem ich Hilfe bräuchte. Ich 
überwache einen Absolutwert. Der Geber ist auf einer Schiene angebracht 
und ich versuche herauszufinden, wann er sich in die eine, die andere 
Richtung bewegt, bzw. wann Stillstand ist.

Das Problem ist, daß der Geber durch kleinste äußere Einflüsse im 
Stillstand schon zwischen zwei Werten springt. Ich mache das momentan 
so, daß ich einen Old-Wert aufnehme und danach einen New-Wert und die 
Differenz bilde. Wäre diese 0 würde ich mich nicht bewegen. Allerdings 
verfälscht die springerei des Messwerts das Ergebnis.

Hat jemand einen Tip wie mann das am besten machen kann ? Ich glaube 
nicht, daß ein Toleranzband die beste Idee ist.

Danke

von Karl H. (kbuchegg)


Lesenswert?

Peter der Kleine schrieb:

> Hat jemand einen Tip wie mann das am besten machen kann ? Ich glaube
> nicht, daß ein Toleranzband die beste Idee ist.

Letzten Endes wirst du aber keine andere Wahl haben.

von Weingut P. (weinbauer)


Lesenswert?

Ein Filter könnte Abhilfe schaffen.

IIR Filter ... Kalman Filter ...

Ein AD-Wandler hat immer etwas rauschen mit dabei ... dazu noch den 
Quantisierungsfehler ... ist halt so.

Auch ein Tiefpass am Eingang kann da Verbesserung aber kaum absolute 
Abhilfe schaffen.

von Kevin K. (nemon) Benutzerseite


Lesenswert?

mehrmals Sampeln und den Mittelwert bilden, hilft aber auch nur 
beschränkt. Ein Toleranzband brauchst du vermutlich eh und dann noch 
eine Betrachtung der letzten paar Bewegungen, also du erwartest den 
neuen Messwert irgendwo anhand der letzten Positionen.

von Noname (Gast)


Lesenswert?

"Glauben" ist in technischen Angelegenheiten nicht angebracht. 
Spätestens seit Voltaire sollten wir uns bemühen zu wissen. ;-)


Was ist das für ein Geber? Nach welchem Prinzip funktioniert er?
Was für Bewegungen, mit welcher Geschwindigkeit und Beschleunigungen 
willst Du erkennen? Vor allem: Was sind die Minima?

Ein Toleranz, ein gewisser Bereich in dem Bewegungen ignoriert werden 
macht Sinn. Evtl. in Zusammmenhang mit der Zeit. In Erweiterung ein 
Mittelwert oder ein höherwertiger Filter.

von Peter der Kleine (Gast)


Lesenswert?

Hallo,

das mit den Tiefpässen oder Filtern ist zwar prinzipiell eine gute Idee. 
Leider ist die Sachlage aber so:

An der Hardware wird definitiv nichts geändert. In meinem C-Code kommen 
also einfach die Werte in ein Array und werden dort je zyklus 
aktualisiert.

Würdet ihr das wirklich so machen:

Ist-Wert Aufnahme (Old-wert)
Ist-Wert Aufnahme (New-wert)

Differenz bilden

Wenn Differenz <= Positive Toleranzgrenze && Differenz >= Negative 
Toleranzgrenze

Dann

Stillstand

von Udo S. (urschmitt)


Lesenswert?

Wie wäre es wenn du etwas mehr als nur den aktuellen und letzten Wert in 
deine Überlegung einbeziehst?

von Noname (Gast)


Lesenswert?

>das mit den Tiefpässen oder Filtern ist zwar prinzipiell eine gute Idee.
>Leider ist die Sachlage aber so:

>An der Hardware wird definitiv nichts geändert.

Öh.
Das ist doch kein Widerspruch. Man kan filter auch in SW implementieren.

>Würdet ihr das wirklich so machen...

Ja. Genau. So oder anders.

Sagst Du mal was zu Deinen Vorkenntnissen und dem Kontext des Problems?

von Hans M. (hansilein)


Lesenswert?

Du musst uns erklären was Du vorhast.

Das was Du hier skizzierst geht manchmal super, versagt aber ein anderes 
mal kläglich.

ein Auto würde z.B. ganz langsam und unbemerkt den Berg runterfahren.

von Johannes E. (cpt_nemo)


Lesenswert?

Das ist ein Problem, das relativ häufig auftritt, wenn man versucht, mit 
kurzer Zykluszeit eine Geschwindigkeit durch Ableitung eines 
Inkrementalgebers zu messen.

Du musst erst mal eine Geschwindigkeit als Grenzwert festlegen. In der 
Regel ist diese langsamer als 1 Inkrement/Zyklus; dadurch spricht dann 
die Überwachung jedesmal an, wenn sich der Geber um ein Inkrement 
bewegt.

Die Ist-Geschwindigkeit muss deshalb gefiltert werden, z.B. durch einen 
PT1-Tiefpass oder durch Mittelwertbildung über mehrere Zyklen hinweg. Je 
nach Grenzwert muss die Filterzeitkonstante bzw. das Intervall für die 
Mittelwertbildung sinnvoll gewählt werden.

von Peter der Kleine (Gast)


Lesenswert?

Ich nehme zyklisch die Werte des Gebers entgegen.

1. Zyklus einen Wert (Old-Wert)
2. Zyklus einen Wert (New-Wert)
Noch im 2. Zyklus die Differenzbildung
Noch im 2. Zyklus schreibe ich auf den alten Wert (Old-Wert) den 
New-Wert um keinen weiteren Zyklus zu verlieren

Dann beginnt das Spiel von vorne. Ab dem zweiten Zyklus bilde ich also 
ständig die Differenz.

Wie schon gesagt:

Im Stillstand (rein optisch) kann es trotzdem vorkommen, daß die Werte 
um 0 Herumspringen.

PS:

Daß man einen Filter auch in SW realisieren kann ist mir klar. Jedoch 
steigt der Aufwand damit ungeheuer an. Hier geht es nicht um eine ganz 
exakte Nullposition. Wenn ich um ca. 2 Millimeter schwanke macht das 
nichts, aber die Schwankung sollte eben tolleriert werden.

von Kevin K. (nemon) Benutzerseite


Lesenswert?

wieso krasser Aufwand?
Mittelwert über 256 Werte geht so: Array aus 256 Plätzen bilden. Da wird 
der Reihe nach immer reingeschrieben. Zusätzlich in einer anderen 
Variable die Summe über alle Werte speichern. Wenn ein neuer Wert 
ankommt, und du an der Stelle 134 bist, von der Summe den 134. Arraywert 
abziehen, den neuen Wert addieren und den neuen Wert an Stelle 134 im 
Array speichern. Dann zum Ausgang die Summe 8 Stellen nach rechts 
schieben. Macht so ~10 Taktzyklen.

von Peter der Kleine (Gast)


Lesenswert?

sorry,

aber das hab ich jetzt nicht ganz verstanden.

Angenommen mein Schlitten bleibt stehen (das kann ich ja detektieren) 
und schwingt um 0, dann würdet ihr also über einige Zylken den 
Mittelwert der Gebersignale aufnehmen. Dieser steht dann auf irgendeinem 
(kleinen) Wert. Wenn dieser Wert kleiner ist als eine bestimmte Grenze, 
dann würdet ihr sagen daß ich stehe ?

von EQVVS OCTOBER (Gast)


Lesenswert?

Mittelwert ist ein ganz schlechter Filter für Messwerte und auch 
allgemein. Warum meinen immer leute den verwenden zu müssen? Er 
verbessert das Messsignal in keinster Weise, er verwischt es nur. Was du 
suchst ist der Zentralwert (Median).

von Jonathan S. (joni-st) Benutzerseite


Lesenswert?

Wie wär's mit einer mitlaufenden Hysterese? Dazu brauchst Du eine untere 
Grenze, eine obere Grenze, einen Eingangswert und einen Ausgangswert. So 
würde man das programmieren:

1. Oberen Grenzwert, unteren Grenzwert und Ausgangswert auf Null setzen.
2. Eingangswert einlesen
3. Wenn Eingangswert > obere Grenze, dann
  3.1 Obere Grenze auf Eingangswert setzen
  3.2 Untere Grenze auf Eingangswert minus Hysterese setzen
  3.3 Ausgangswert auf den Durchschnitt der Grenzwerte setzen
4. Wenn Eingangswert < untere Grenze, dann
  4.1 Untere Grenze auf Eingangswert setzen
  4.2 Obere Grenze auf Eingangswert plus Hysterese setzen
  4.3 Ausgangswert auf den Durchschnitt der Grenzwerte setzen
5. Zurück zu 2

Damit bekommst Du ein absolut rauschfreies Signal (sofern die Hysterese 
größer als das Rauschen ist), die Geschwindigkeit bleibt gleich und das 
Signal ist auch nicht "verwischt". Der einzige Nachteil ist, dass der 
Ausgangswert nicht ganz an das Minimum und das Maximum des 
Eingangswertes rankommt (auf 1/2 der Hysterese).


Gruß
Jonathan

von Peter der Kleine (Gast)


Lesenswert?

Herzlichen Dank an euch alle für die Antworten.

Insbesondere an Kevin K. und Johannes E.

Aus euren Antworten konnte ich noch notwendige Erweiterungen ableiten 
(die zu implementieren zwar nicht ganz einfach sind) aber sehr zur 
Stabilität der Überwachung beitragen könnten.

von Peter der Kleine (Gast)


Lesenswert?

Übrigens auch vielen Dank an Jonathan für deine sehr ausführliche Idee, 
auch wenn ich es wohl doch letzenendes anders machen werde sind solche 
Denkanstöße es oft wert sich zu notieren um vielleicht später einmal 
darauf zurückgreifen zu könnnen.

von Johannes E. (cpt_nemo)


Lesenswert?

Peter der Kleine schrieb:
> Ich nehme zyklisch die Werte des Gebers entgegen.
>
> 1. Zyklus einen Wert (Old-Wert)
> 2. Zyklus einen Wert (New-Wert)
> Noch im 2. Zyklus die Differenzbildung
> Noch im 2. Zyklus schreibe ich auf den alten Wert (Old-Wert) den
> New-Wert um keinen weiteren Zyklus zu verlieren
>
> Dann beginnt das Spiel von vorne. Ab dem zweiten Zyklus bilde ich also
> ständig die Differenz.

Ja, genau so. Die Differenz ist dann die Geschwindigkeit.

Diese muss dann noch gefiltert werden, am einfachsten nach diesem 
Schema:

v_filter_neu = v_filter_alt + (diff - v_filter_alt) * k

k ist eine Zahl im Bereich 0..1. Wenn die Filterzeitkonstant z.B. 100 
Zyklen betragen soll, muss k den Wert 0.01 haben.

von Johannes E. (cpt_nemo)


Lesenswert?

Jonathan Strobl schrieb:
> Wie wär's mit einer mitlaufenden Hysterese? Dazu brauchst Du eine untere
> Grenze, eine obere Grenze, einen Eingangswert und einen Ausgangswert...

Das ist eigentlich nur dann sinnvoll, wenn man ein echtes Rauschen hat. 
Bei einer Stillstandsüberwachung kommt das Problem eher durch die 
Quantisierung.

Beispiel:

Motor hat einen Geber mit 2048 Strichen, also 8192 Inkremente pro 
Umdrehung.
Grenzdrehzahl für Stillstandsüberwachung ist 1 U/min
Zykluszeit ist 1 ms

Der Grenzwert sind also ca. 136 Inkremente/s = 0,136 Inkremente/Zyklus

Man muss also eine Geschwindigkeit auflösen, die weniger als ein 
Inkrement/Zyklus ist. Durch die Hysterese-Auswertung gewinnt man aber 
keine Auflösung.

EQVVS OCTOBER schrieb:
> Mittelwert ist ein ganz schlechter Filter für Messwerte und auch
> allgemein. Warum meinen immer leute den verwenden zu müssen? Er
> verbessert das Messsignal in keinster Weise, er verwischt es nur. Was du
> suchst ist der Zentralwert (Median).

Diese Aussage ist so nicht richtig. Je nach Anwendung hat auch ein 
Mittelwertfilter seine Berechtigung.

Im Prinzip ist ein Mittelwertfilter die einfachste Art eines 
FIR-Filters, bei dem alle Koeffizienten =1 sind. Er hat also eine 
lineare Phase und Nullstellen bei allen ganzzahligen Vielfachen der 
Filterzeit.

Wenn man z.B. ein Signal hat, das durch PWM-Modulation erzeugt wird 
(also mit fester Frequenz), kann man mit Mittelwertbildung über eine 
PWM-Periode sehr elegant die Grundwelle und alle Oberwellen der PWM 
herausfiltern.

Für eine Geschwindigkeitsmessung ist Mittelwertbildung allerdings nicht 
so optimal, da ist ein PT1-Tiefpass sinnvoller.

von Peter der Kleine (Gast)


Lesenswert?

Leute Leute,

da raucht die Birne. Ich habe gerade einen Kurzschluß an der Stelle, an 
der die physikalischen Dinge ins Spiel kommen.

Möglicherweise (und zwar ziemlich sicher) wird mein Schlitten bei sehr 
langsamer Fahrt keinen neuen Wert erreichen bevor der nächste Zyklus 
wieder durchläuft und den Wert aufnimmt. Nun wäre also der neu 
aufgenommene und der alte der selbe Zahlenwert und ich würde als 
Bewegung den Stillstand detektieren.

Nun möchte ich das so machen, daß ich zwar in jedem Zyklus eine Bewegung 
ermittle, diese aber nur unter Array_Vorlaeufige_Bewegung und in jedem 
weiteren Zyklus nachschaue, ob das ermittelte Ergebnis immer noch mit 
Array_Vorlaeufige_Bewegung uebereinstimmt.

Erst wenn diese Ermittlung sagen wir mal 10mal durchlaufen wurde, dann 
schreibe ich auf Array_endgueltige_Bewegung einen Zahlenwert, der 
entweder rauf-runter bzw. Stillstand entspricht.

Gibts da draußen irgendjemanden der das anders machenw würde ?

Für Tips bin ich sehr dankbar

von Karl H. (kbuchegg)


Lesenswert?

Peter der Kleine schrieb:

> schreibe ich auf Array_endgueltige_Bewegung einen Zahlenwert, der
> entweder rauf-runter bzw. Stillstand entspricht.

benötigst du nur die boolsche Information "Bewegung in die eine 
Richtung" bzw. "Bewegung in die andere Richtung" bzw. "Stillstand" oder 
brauchst bei den Bewegungen auch die Größe der Bewegung?

> Gibts da draußen irgendjemanden der das anders machenw würde ?

Von der Idee her würde ich das auch so machen. Also dass Stillstand erst 
dann gilt, wenn er n mal hintereinander festgestellt wurde.

Nur implementieren würde ich das anders.
Ich hätte einfach einen Zähler, der mit jedem mal Stillstand detektieren 
um 1 erhöht wird. Kommt dein Messverfahren zum Schluss: kein Stillstand, 
dann wird der Zähler wieder auf 0 zurückgesetzt. Erreicht der Zähler 
tatsächlich irgendwann mal den Wert n, dann wurde folgerichtig n mal 
hintereinander Stillstand festgestellt und ich melde meinem Benutzer: 
wir stehen!

Für rauf/runter würde ich das genau gleich machen, WENN die Größe der 
Bewegung nicht gebraucht wird.

von Peter der Kleine (Gast)


Lesenswert?

Im Prinzip mache ich das genauso wie du auch gesagt hast.

Da gibts noch eine Frage zu der Sache mit dem inkrementieren des 
Zählers.

Von einem inkrement zum anderen dauert es ja genau einen Zyklus. Kann 
man das eigentlich so sagen ?


Denn prinzipiell könnte ich auch mit der Zykluszeit arbeiten (dafür habe 
ich eine Funktion, die mir diese zurückgibt) allerdings bräuchte ich 
dann einen festen Zeitwert, der vergehen darf bis ich endgueltige 
Positionen zurueckgebe.

wenn man nun an der Maschine steht und im experiment einen Zahlenwert zu 
finden hat, bei dem die Ausgaben zur Bewegung passen, finde ich es 
einfacher die Ausgabe der tatsächlichen Bewegung über die ZyklenANZAHL 
und nicht über eine ZEITBASIS zu realisieren. Ich müßte halt nur den 
Zählwert erhöhen (sofern man wirklcih sagen kann, daß zwischen den 
inkrementen genau ein Zyklus vergeht...was aber halt eigentlich genau so 
sein MUSS...wenn ich mich nciht irre )

von Johannes E. (cpt_nemo)


Lesenswert?

Peter der Kleine schrieb:
> Möglicherweise (und zwar ziemlich sicher) wird mein Schlitten bei sehr
> langsamer Fahrt keinen neuen Wert erreichen bevor der nächste Zyklus
> wieder durchläuft und den Wert aufnimmt. Nun wäre also der neu
> aufgenommene und der alte der selbe Zahlenwert und ich würde als
> Bewegung den Stillstand detektieren.

Ja, du hast entweder eine Änderung um ein Inkrement oder keine Änderung. 
Du brauchst also in irgendeiner Form eine Mittelung über mehrere Zyklen.

Peter der Kleine schrieb:
> Erst wenn diese Ermittlung sagen wir mal 10mal durchlaufen wurde, dann
> schreibe ich auf Array_endgueltige_Bewegung einen Zahlenwert, der
> entweder rauf-runter bzw. Stillstand entspricht.

Du könntest genau so gut nur in jedem zehnten Zyklus die Differenz 
berechnen (die Differenz zum 10. Zyklus davor).


Mach es mit einem Filter, so wie ich's oben beschrieben habe. Das 
funktioniert wirklich gut, ich hab das schon oft gemacht.
Wenn du noch nie einen Filter programmiert hast, dann ist das jetzt eine 
gute Gelegenheit. Es sieht komplizierter aus als es ist.


Karl Heinz Buchegger schrieb:
> Ich hätte einfach einen Zähler, der mit jedem mal Stillstand detektieren
> um 1 erhöht wird. Kommt dein Messverfahren zum Schluss: kein Stillstand,
> dann wird der Zähler wieder auf 0 zurückgesetzt.

Dann hat man aber das Problem, wenn der Geber genau zwischen zwei 
Inkrementen steht und zwischen diesen beiden Positionen dauernd hin- und 
herspringt.

von Karl H. (kbuchegg)


Lesenswert?

Johannes E. schrieb:

>> Ich hätte einfach einen Zähler, der mit jedem mal Stillstand detektieren
>> um 1 erhöht wird. Kommt dein Messverfahren zum Schluss: kein Stillstand,
>> dann wird der Zähler wieder auf 0 zurückgesetzt.
>
> Dann hat man aber das Problem, wenn der Geber genau zwischen zwei
> Inkrementen steht und zwischen diesen beiden Positionen dauernd hin- und
> herspringt.


Moment.
Ich dachte die 'Filterung' sei jetzt schon gegessen?

Zu einer Zeit als Mauspositionen sich noch ein wenig veränderten, selbst 
wenn die Maus völlig ruhig am Tisch lag, haben wir das so gemacht, dass 
wir eine Mausbewegung erst dann akzeptierten, wenn sie sich von der 
letzten als Stillstand anerkannten Mausposition mindestens 5 Pixel in X 
bzw. Y wegbewegt hat. Zumindest bei der Maus hat das ganz gut 
funktioniert.

von Johannes E. (cpt_nemo)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Zu einer Zeit als Mauspositionen sich noch ein wenig veränderten, selbst
> wenn die Maus völlig ruhig am Tisch lag, haben wir das so gemacht, dass
> wir eine Mausbewegung erst dann akzeptierten, wenn sie sich von der
> letzten als Stillstand anerkannten Mausposition mindestens 5 Pixel in X
> bzw. Y wegbewegt hat. Zumindest bei der Maus hat das ganz gut
> funktioniert.

Das kommt natürlich auch drauf an, wie man Stillstand definiert. Das ist 
nämlich gar nicht so eindeutig, wie es sich vielleicht anhört:

Man kann festlegen, dass bei einer Geschwindigkeit unterhalb eines 
bestimmten Grenzwerts Stillstand gemeldet werden soll. In diesem Fall 
wäre ein ganz langsames wegdriften also auch noch erlaubt. Das ist z.B. 
dann sinnvoll, wenn man nach dem Abbremsen einer Fräßspindel die 
Schutztüre öffnen will. Hier ist es nicht wichtig, dass die Spindel 
genau auf einer bestimmten Position stehen bleibt.

Oder man definiert, dass sich die Position von einem bestimmten Punkt 
aus nicht über eine bestimmte Distanz entfernen darf. In diesem Fall 
wäre eine Bewegung innerhalb dieses Bereichs erlaubt (sogar eine relativ 
schnelle Bewegung). Das ist dann also eine Positions- und keine 
Geschwindigkeitsüberwachung.

Man kann natürlich auch beides miteinander kombinieren.

Erst nachdem man festgelegt hat, was für eine Überwachung benötigt wird, 
sollte man sich den genauen Lösungsansatz überlegen.

von Peter der Kleine (Gast)


Lesenswert?

Hallo Johannes E.

Daß es eine gute Gelegenheit wäre, sich mit dem Programmieren eines 
Filters auseinander zu setzen stimmt in der Tat.

Allerdings verstehe ich es irgendwie nicht so ganz was mit deiner Formel 
hier passiert.

Johannes E. schrieb:
> Peter der Kleine schrieb:
>> Ich nehme zyklisch die Werte des Gebers entgegen.
>>
>> 1. Zyklus einen Wert (Old-Wert)
>> 2. Zyklus einen Wert (New-Wert)
>> Noch im 2. Zyklus die Differenzbildung
>> Noch im 2. Zyklus schreibe ich auf den alten Wert (Old-Wert) den
>> New-Wert um keinen weiteren Zyklus zu verlieren
>>
>> Dann beginnt das Spiel von vorne. Ab dem zweiten Zyklus bilde ich also
>> ständig die Differenz.
>
> Ja, genau so. Die Differenz ist dann die Geschwindigkeit.
>
> Diese muss dann noch gefiltert werden, am einfachsten nach diesem
> Schema:
>
> v_filter_neu = v_filter_alt + (diff - v_filter_alt) * k
>
> k ist eine Zahl im Bereich 0..1. Wenn die Filterzeitkonstant z.B. 100
> Zyklen betragen soll, muss k den Wert 0.01 haben.


Als erstes sollte man Festhalten, daß meine Differenz keine 
Geschwindigkeit ist, weil ich die Zykluszeit nicht mit verwende. Meine 
Differenz ist also eigentlich nur eine Positionsdifferenz, also ein Weg.

Weg_neu = Weg_alt + (diff - Weg_alt) * k

Irgendwie steh ich gerade auf der Leitung, aber ich komme nicht drauf, 
was hier tatsächlich gefiltert wird.

Es wäre sehr nett von Dir wenn du Dir nochmals Zeit nehmen könntest um 
das zu erklären.

Herzlichen Dank

von Johannes E. (cpt_nemo)


Lesenswert?

Peter der Kleine schrieb:
> Als erstes sollte man Festhalten, daß meine Differenz keine
> Geschwindigkeit ist, weil ich die Zykluszeit nicht mit verwende. Meine
> Differenz ist also eigentlich nur eine Positionsdifferenz, also ein Weg.

Das ist trotzdem eine Geschwindigkeit, allerding nicht in der Einheit 
Weg/s sondern Weg/Zyklus. Da der Zyklus einem Zeitintervall entspricht, 
kann man das als Zeit betrachten.

Peter der Kleine schrieb:
> Es wäre sehr nett von Dir wenn du Dir nochmals Zeit nehmen könntest um
> das zu erklären.

Ich versuchs mal; zuerst einige Definitionen:

x_act: Aktuelle Position
x_old: Position aus dem letzten Zyklus
v_act: aktuelle, ungefilterte Geschwindigkeit, also v_act = x_act - 
x_old
v_filter_act: gefilterte Geschwindigkeit
v_filter_old: gefilterte Geschwindigkeit aus dem letzten Zyklus

Dann kann man den Filter folgendermaßen Berechnen:

v_filter = v_filter_old + (v_act - v_filter_old) * k

Der Ausdruck "v_act - v_filter_old" ist die Differenz zwischen der 
aktuell gemessenen Geschwindigkeit und dem gefilterten (gemittelten) 
Wert.

Von dieser Differenz wird ein kleiner Anteil (je nach k) auf den 
gefilterten Wert draufaddiert. Wenn v_act und v_filter gleich groß sind, 
wird nichts draufaddiert, der Filter ist dann eingeschwungen.

Die Filterzeitkonstante kann für kleine Werte von k relativ einfach als 
1/k angenähert werden. Das stimmt zwar nicht ganz exakt, ist aber nicht 
so wichtig.

Wenn man z.B. eine Filter-Zeitkonstante von 20 Zyklen haben möchte, muss 
k=0.05 sein.

Diese Betrachtung war jetzt für Fließkomma-Zahlen. Wenn du einen µC mit 
Integer-Zahlen hast, berechnet man das am besten mit 
Festkomma-Arithmetik.

Dazu muss man die gefilterte Geschwindigkeit normieren, z.B. mit 8 
binären Nachkommastellen.

Die Formel ist dann folgendermaßen:
v_filter = v_filter_old + (v_act - ((v_filter_old + 128) >> 8) * k

mit k = 0 .. 256 entspricht 0.0 .. 1.0

Beachte den Ausdruck (+ 128), der ist dazu da, dass korrekt gerundet 
wird. Wenn man eine andere Normierung haben möchte, muss das auch 
angepasst werden.

Die Variable v_filter ist damit um den Faktor 256 größer als v_act, die 
hinteren 8 Bit sind die Nachkommastellen.


Beispiel mit Zahlen:
k = 8, entspricht also 0.03125, die Zeitkonstante ist damit 32 Zyklen

Startwert: v_filter = 0
v_act ist abwechselnd 0 und 1

 1. Zyklus: v_act = 0 -> v_filter = 0
 2. Zyklus: v_act = 1 -> v_filter = 8 (entspricht 0,03125)
 3. Zyklus: v_act = 0 -> v_filter = 8 (entspricht 0,03125)
 4. Zyklus: v_act = 1 -> v_filter = 16 (entspricht 0,0625)
 5. Zyklus: v_act = 0 -> v_filter = 16 (entspricht 0,0625)
 6. Zyklus: v_act = 1 -> v_filter = 32 (entspricht 0,09375)
 7. Zyklus: v_act = 0 -> v_filter = 32 (entspricht 0,09375)
 8. Zyklus: v_act = 1 -> v_filter = 64 (entspricht 0,125)
 9. Zyklus: v_act = 0 -> v_filter = 64 (entspricht 0,125)
...
v_filter = 128:
v_act = 1 -> v_filter = 128 (entspricht 0,500)
v_act = 0 -> v_filter = 127   (entspricht 0,496)
v_act = 1 -> v_filter = 128 (entspricht 0,500)
v_act = 0 -> v_filter = 127   (entspricht 0,496)
...

Der Wert v_filter pendelt sich also bei 128 ein, das ist eine 
Geschwindigkeit von 0,5 Inkrementen/Zyklus. Man bekommt also aus der 
Abfolge von abwechselnd 0 und 1 einen Mittelwert.

Wenn v_act weniger oft ungleich 0 wäre, würde sich der Filter bei einem 
kleineren Wert einpendeln.

Ich hoffe, das hilft dir weiter.

von Johannes E. (cpt_nemo)


Lesenswert?

Mit ist noch aufgefallen, dass die Formel:

etwas unegschickt ist, da große Rundungsfehler entstehen.

Besser geht es mit:

von Peter der Kleine (Gast)


Lesenswert?

Hallo Johannes,

recht herzlichen Dank für deine sehr ausführliche Antwort. Es sieht sehr 
interessant und professionell aus.

Ich habe in der Zwischenzeit etwas anderes programmiert. Was hältst du 
eigentlich davon.

Ich nehme jeden Wert den mir der Geber liefert und berechne immer die 
Differenz. Diese Differenz untersuche ich ganz simpel ob > 0 oder <0.

Der Stillstand ist ein extra Programmteil. Jetzt mal nur auf oder ab.

Wenn ich >0 bin, dann schreibe ich eine 1 in einen Ringpuffer. Das mache 
ich über eine (einstellbare) zyklusanzahl von z.B. 10 Zyklen. Nach 10 
zyklen multipliziere ich die Elemente meiens Ringpuffers. Erst wenn nach 
der Multiplikation 1 rauskommt gehe ich davon aus, daß er tatsächlich 
nach oben fährt.

Das selbe mache ich bei der Stillstandsdetektion (allerdings innerhalb 
definierter Grenzen um 0).

Solange ich mich also innerhalb diesen Grenzen befinde schreibe ich eine 
1 in einen Ringpuffer. Schwinge ich über, steht an einer Stelle eine 0 
und das Produkt des Ringpuffers ergibt 0.

Das Problem ist, daß ich sehr wenig Zeit habe um den Code zu 
implementieren. Erst mal brauch ich was lauffähiges. Verbessern kann ich 
das dann nach und nach.

Was hältst du von meinem Vorschlag ?

von Johannes E. (cpt_nemo)


Lesenswert?

Peter der Kleine schrieb:
> Was hältst du von meinem Vorschlag ?

Das hört sich ziemlich kompliziert an, man muss da Zyklen mitzählen und 
mehrere Ringpuffer verwalten und dann auch noch viele Werte 
multiplizieren.

Es könnte schon funktionieren, ist aber im Vergleich zu einem einfachen 
Filter sicherlich nicht weniger Aufwand.

> Wenn ich >0 bin, dann schreibe ich eine 1 in einen Ringpuffer. Das mache
> ich über eine (einstellbare) zyklusanzahl von z.B. 10 Zyklen. Nach 10
> zyklen multipliziere ich die Elemente meiens Ringpuffers. Erst wenn nach
> der Multiplikation 1 rauskommt gehe ich davon aus, daß er tatsächlich
> nach oben fährt.

Das heist, du detektierst auf eine Mindestdrehzahl von 1 
Inkrement/Zyklus. Falls das zufällig zur Vorgabe passt, kann man das 
theoretisch so machen. Es ist sehr unflexibel, falls du mal eine andere 
Grenzdrahzahl haben möchtest.


> Das selbe mache ich bei der Stillstandsdetektion (allerdings innerhalb
> definierter Grenzen um 0).
>
> Solange ich mich also innerhalb diesen Grenzen befinde schreibe ich eine
> 1 in einen Ringpuffer. Schwinge ich über, steht an einer Stelle eine 0
> und das Produkt des Ringpuffers ergibt 0.

Wie ist denn jetzt die Anforderung an die Stillstandsüberwachung? Es 
kann schon sein, dass es funktionier, aber das Risiko ist groß, dass es 
sich dann doch nicht so verhält wie man sich das vorgestellt hat.

Auserdem ist es nicht sehr schon, wenn man für eine andere Filterzeit 
die Array-Größe (Länge des Ringpuffers) ändern muss. Bei der Variante 
mit dem Filter kann man die Filter-Zeitkonstante sehr einfach zur 
Laufzeit ändern.

von RonnyRoster (Gast)


Lesenswert?

Hallo,

ohne genauere Angaben isses wirklich schwierig, dir passend zu helfen.

Du hast momentan eine schlechte Version des Vorschlags aus dem Beitrag 
Beitrag "Re: Gedankenanstoß Messwertauswertung" implementiert.

Bedenke: Wenn du einen Ringpuffer auf Nullen überprüfst, machst du 
nichts anderes, als vorrauszusetzen, dass X mal hintereinander deine 
Bedingung erfüllt sein muss. Das lässt sich einfacher durch einen Zähler 
realisieren, den man auf 0 setzt und bei Erfüllung deiner Bedingung 
inkrementiert. Wird die Bedingung nicht erfüllt, wir der Zähler wieder 
auf null gesetzt.
Wenn der Zähler einen gewissen Wert X erreicht hat, dann gilt das 
Ereignis als sicher.

von Peter der Kleine (Gast)


Lesenswert?

Hallo,

jetzt habe ich einiges nochmals überdacht und da stellen sich schon 
einige Fragen.

Aufgrund der Trägheit der Mechanik (die ist echt protzig) macht es 
eigentlich gar keine Sinn in jedem Zyklus eine Bewegungsänderung zu 
machen.

Deshalb nehme ich jetzt im ersten Zyklus alle "Alt" Werte auf, jedoch 
die Neuwerte erst nach einer einstellbaren Anzahl an Zyklen.

Die Berechnung der Position erfolgt somit nicht mehr in jedem Zyklus 
sondern sagen wir mal nach 20 Zyklen. Langsame Fahrten großer Massen 
kann ich also so zuverlässiger feststellen.

Jetzt stellt sich nur die Frage ob der Ringpuffer in den ich die 
Bewegungen schreibe und erst dann als solche ausgebe wenn mehrere 
Ergebnisse das selbe Resultat liefern überhaupt noch nötig ist.

Was meint Ihr ? Theoretisch verbessert der Ringpuffer das Ergebnis ja 
schon, weil ich nicht einem ermittelten Wert vertraue, sondern erst eine 
Ausgabe mache, wenn ich mehrmals das selbe Resultat erhalten habe, 
jedoch sind die Schwankungen, welche auftreten könnten wenn ich Zyklus 
für Zyklus eine Berechnung mache ja dadurch schon erschlagen, daß ich 
das jetzt nur alle n-Zyklen mache.

Wie seht ihr das mit dem Ringpuffer bei einer Messwertaufnahme alle n 
Zyklen ?

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
Noch kein Account? Hier anmelden.