Forum: FPGA, VHDL & Co. Drehgeber Emulation


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Ja D. (jacoie)


Lesenswert?

Hallo Zusammen,

ich bin gerade dabei, ein kleines Projekt mit meinem Artik7 zu 
programmieren
wo ich einen Drehgeber mit VHDL emulieren möchte. Im Gegensatz zum Code 
von Lothar Miller wird die Position als analoges Signal eingelesen, dann 
digitalisiert und A und B als digitale Ausgangssignale erzeugt 
(invertierte Funktionalität des Lothar Miller Codes). Der ADC ist 
bereits eingerichtet und ich kann das analoge Positionssignal einlesen 
und in ein std_logic_vector Signal umwandeln. Um nun A und B mit einer 
Zeitverzögerung zu erzeugen, muss ich zuerst die Drehrichtung des 
std_logic_vector (oder die Positionsanzeige) erkennen und dann eine 
entsprechende Logik programmieren. Hat jemand eine Idee, wie ich die 
Drehrichtung erkennen kann (um zu wissen, ob ein std_logic_vector 
inkrementiert oder dekrementiert)? oder hat jemand eine Idee, ob ein 
solcher Code irgendwo anders programmiert ist?

Beste Grüsse
Michael

: Bearbeitet durch User
von Fabian N. (flyget)


Lesenswert?

Wenn ich dich richtig verstehe, is das was ähnliches wie ich mal hier 
vorgestellt habe:
Beitrag "Feedback erstes VHDL-Projekt"

Bei mir gab es allerdings beim Rohsignal wrap-arounds, sodass die Logik 
etwas mehr beachten musste. Im speziellen mussten die Sprünge im 
Rohsignal erkannt und beseitigt werden, um einen durchgängigen Zähler 
für den Quadraturausgang zu erhalten.

von Markus F. (mfro)


Lesenswert?

Ja D. schrieb:
> Hat jemand eine Idee, wie ich die
> Drehrichtung erkennen kann (um zu wissen, ob ein std_logic_vector
> inkrementiert oder dekrementiert)?

Warum nimmst Du einen std_logic_vector, wenn Du Zahlenwerte vergleichen 
willst?

Nimm' stattdessen einen signed oder unsigned Wert und Du kannst 
unmittelbar auf größer oder kleiner testen.

von Falk B. (falk)


Lesenswert?

Ja D. schrieb:
> Um nun A und B mit einer
> Zeitverzögerung zu erzeugen, muss ich zuerst die Drehrichtung des
> std_logic_vector (oder die Positionsanzeige) erkennen und dann eine
> entsprechende Logik programmieren. Hat jemand eine Idee, wie ich die
> Drehrichtung erkennen kann (um zu wissen, ob ein std_logic_vector
> inkrementiert oder dekrementiert)? oder hat jemand eine Idee, ob ein
> solcher Code irgendwo anders programmiert ist?

Man braucht einen 2. Zähler, der die Anzahl/Position der schon 
ausgegebenen Pulse repräsentiert. Die Differenz zum Analogwert gibt dir 
die Richtung vor. Sprich, der interne Zähler läuft dem ADC-Wert 
hinterher.

Beitrag "Re: 0-10V Signal in Drehimpulsgeber Signal Umwandeln"

von Ralf (Gast)


Lesenswert?

Ja D. schrieb:
> wo ich einen Drehgeber mit VHDL emulieren möchte.
Was heißt "emulieren"? Dasheißt für mich, du möchtest das Verhalten 
eines Drehgebers erzeugen, also z.B. aus einer Position die Werte AB 
generieren.

Was du aber im Folgesatz beschreibst, ist ein blosses Auswerten eines 
Analogsignals. Woher kommt das Analogsignal und wie sieht es aus?

XY-Poti?

Angenommen, man kann das Signal in einen Winkel übersetzen, dann muss 
einfach nur für A = 0 ... 180 und für B=90 ...270 eine 1 ausgegeben 
werden.

000 ... 090  A=1, B=0
090 ... 180  A=1, B=1
180 ... 270  A=0, B=1
279 ... 360  A=0, B=0

von Duke Scarring (Gast)


Lesenswert?

Ja D. schrieb:
> Hat jemand eine Idee, wie ich die
> Drehrichtung erkennen kann
Sind beide Signale sinusförmig?
Wenn ja, würde ich die Phase zwischen den beiden Signalen ermitteln.
Alternativ: Umwandeln in ein Rechtecksignal (Komparator) und dann die 
klassischen Verfahren anwenden.

Duke

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Ja D. schrieb:
> Im Gegensatz zum Code von Lothar Miller wird die Position als analoges
> Signal eingelesen
Ist das ein sin/cos Geber wie hier beschrieben:

http://www.servotechnik.de/fachwissen/geber/f_beitr_00_410.htm

Ja D. schrieb:
> Um nun A und B mit einer Zeitverzögerung zu erzeugen, muss ich zuerst
> die Drehrichtung des std_logic_vector (oder die Positionsanzeige)
> erkennen und dann eine entsprechende Logik programmieren. Hat jemand
> eine Idee, wie ich die Drehrichtung erkennen kann (um zu wissen, ob ein
> std_logic_vector inkrementiert oder dekrementiert)?
Mit hoher Wahrscheinlichkeit ist der Ansatz falsch. Du musst da nichts 
umdrehen, weil dir ja der Geber immer die aktuelle Posittion liefert.

> oder hat jemand eine Idee
Beschreibe doch mal, was du hast (mit Typbezeichnungen usw usf) und dann 
zeichne mal ein Diagramm mit dem Signalverlauf am Eingang und was du 
daraus machen sollst.

Ja D. schrieb:
> ob ein solcher Code irgendwo anders programmiert ist?
Solltest du für den besten Lerneffekt die Aufgabe nicht besser selber 
lösen, statt irgendwas im Internetz zusammenzukopieren?

: Bearbeitet durch Moderator
von Jürgen S. (engineer) Benutzerseite


Lesenswert?

Lothar M. schrieb:
> Solltest du für den besten Lerneffekt die Aufgabe nicht besser selber
> lösen, statt irgendwas im Internetz zusammenzukopieren?
ja, wobei:

Eine richtige Drehgeber-Emulation, mit der man etwas anfangen kann, 
funktioniert schon noch ein wenig komplizierter, je nachdem was der 
Anwender benötigt. Meistens will er ja seine Ausgangs-Elektronik und die 
Signalverarbeitung optimieren.

- Drehgeber haben mehrere Impulswechsel pro Vollkreis
- die Kontakte prellen. d.h. sie haben einen während des Schaltens 
veränderlichen Widerstand, der auch nochmal 0 werden kann
- die Kontakte prellen unterschiedlich lange und schnell
- die Kontakte haben unterschiedliche Mikro-Positionen, die nicht 
exakten Winkelteilungen 1/n entsprechen
- die Kontakte haben unterschiedliche elektrische Ruhewiderstände
- die Kontakte altern und verschmutzen, sodass die Widerstände steigen
- die Kontakte kratzen beim Drehen
- Die Drehgeber haben mitunter mechanische und/oder magnetische 
Rastpunkte
- die Rastpunkte haben eine unterschiedliche mechanische Stärke
- die Rastpunkte liegen nicht exakt auf ganzzahligen Winkelteilungen 1/n
- die Rastpunkte sind gegenüber den Kontakten teilweise um eine halbe 
Rastweite versetzt, sodass die Kontakte nicht im Bereich der Rastpunkte 
liegen und damit effektiv weniger prellen
- die Welle nimmt bei schnellen Bewegungen ein Rotationsmoment auf
- die Welle schleift
- die Welle schwingt in sich nach
- der Knopf hat eine Trägheit
- der Knopf schwingt nach

(Für einen Wellen-Drehgeber ersetze "Knopf" durch "Getriebe" oder 
"Achse".)

Ich habe ein komplettes VHDL-Modell für solche Drehgeber, in welchem 
alle diese Parameter einstellbar sind. Funktioniert realistisch bis 
30kUPM bei 60MHz. Angeschlossen werden z.B. virtuelle Reihen- und 
pullup-Widerstände und Versorgungs-Spannungen, gefolgt von Kapazitäten, 
die ebenfalls parametrierbar sind. Ausgabe ist ebenfalls eine virtuelle 
Spannung, die mit EMI-noise beaufschlagt werden kann und an die man 
einen Komparator anschließen kann, der eine parametrierbare Hysterese 
hat.

Damit bekommt man dann die digitalen A/B/(C) Signale mit allen möglichen 
Varianzen.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Jürgen S. schrieb:
> je nachdem was der Anwender benötigt.
Ja, das ist noch unklar...

Jürgen S. schrieb:
> Eine richtige Drehgeber-Emulation, mit der man etwas anfangen kann,
> funktioniert schon noch ein wenig komplizierter
Ich glaube, das Wort "Emulation" wurde vom TO falsch verwendet. Ich 
vermute, er will einfach nur einen sin/cos-Geber einlesen und daraus 
A/B/0-Quadratur Signale machen.

Das ist im ersten Ansatz eigentlich ganz einfach, es müssen nur 
hinreichend große ROM/RAM vorbelegt werden, dann kann ich mit den 
AD-Werten als Adressvektor direkt die A/B/0-Werte auslesen.

Alternativ kann man eine Impulsnachlaufregelung basteln, oder..., 
oder...

von Ja D. (jacoie)


Lesenswert?

Hallo Zusammen,

sorry für meine späte Antwort. Eigentlich möchte ich einen 
Encodersensor, den ich nicht habe, in VHDL simulieren. Der Encoder ist 
Teil einer Strecke, die ich auf einem echtzeitfähigen Controller 
simuliere. Von dem Controller kann ich aber nur analoge Signale 
ausgeben, also ist die Idee, dass ich die Rotorposition als analoges 
Signal ausgebe und in das FPGA einlese, wo dann die Schaltimpulse A/B 
erzeugt werden. Dazu muss ich das analoge Signal einlesen, die Richtung 
erkennen und die Schaltimpulse erzeugen.

Beste Grüsse
Michael

von Ja D. (jacoie)


Lesenswert?

Für die Richtungserkennung kann man natürlich das gewandelte Signal, das 
ich als std_logic_vector habe, in Integer umwandeln und mit einem 
vorherigen vergleichen, aber ich habe vor ein paar Jahren die Erfahrung 
gemacht, dass ein vhdl-Prozess, der auf Integer-Zahlen empfindlich ist, 
ziemlich instabil ist.

von Ja D. (jacoie)


Lesenswert?

> Eine richtige Drehgeber-Emulation, mit der man etwas anfangen kann,
> funktioniert schon noch ein wenig komplizierter, je nachdem was der
> Anwender benötigt. Meistens will er ja seine Ausgangs-Elektronik und die
> Signalverarbeitung optimieren.
>

das klingt wirklich nach einem detaillierten und teilweise notwendigen 
Entwurf. Ich habe schon an so etwas gedacht, um fehlerhafte 
Schaltimpulse zu erzeugen, damit ich sehen kann, wie die 
Weiterverarbeitung der Signale mit solchen Störungen umgehen kann.

von Ja D. (jacoie)


Lesenswert?

> Warum nimmst Du einen std_logic_vector, wenn Du Zahlenwerte vergleichen
> willst?
>
> Nimm' stattdessen einen signed oder unsigned Wert und Du kannst
> unmittelbar auf größer oder kleiner testen.

Für die Richtungserkennung kann man natürlich das gewandelte Signal, das
ich als std_logic_vector habe, in Integer umwandeln und mit einem
vorherigen vergleichen, aber ich habe vor ein paar Jahren die Erfahrung
gemacht, dass ein vhdl-Prozess, der auf Integer-Zahlen empfindlich ist,
ziemlich instabil ist.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Ja D. schrieb:
> aber ich habe vor ein paar Jahren die Erfahrung gemacht, dass ein vhdl-
> Prozess, der auf Integer-Zahlen empfindlich ist, ziemlich instabil ist.
Dir ist grundlegend schon klar, dass "ein Prozess" an sich nicht 
"empfindlich" sein kann?

Was da "empfindlich" sein kann, ist eine ungünstig beschriebene 
Hardware. Denn natürlich darfst du z.B. niemals zwei Integer einfach so 
kombinatorisch vergleichen und auf dieses Vergleichsergebnis asynchron 
reagieren. Denn dann spuckt dir natürlich jeder Glitch und jeder Spike 
in die Suppe. Mit höchster Wahrscheinlichkeit hast du damals genau diese 
Erfahrung gemacht.

Allerdings hast du aus dieser Erfahrung nichts gelernt, denn das, was du 
da gerade basteln willst, läuft auf das selbe Ergebnis hinaus: du willst 
asynchron einen Analogwert ausgeben, diesen völlig asynchron wandeln und 
dann in irgendwelche Impulse übersetzen.

Beschreib doch mal die Lösung, wie du sie dir vorstellst, denn offenbar 
macht dir dabei eine wie auch immer gerartete "Richtungserkennung" 
Probleme.

Und überleg mal eine Antwort auf diese Fragen:
Wie willst du die Position in dem Analogwert unterbringen?
Wie willst du die "Unendlichkeit" eines Drehgebers abbilden?
Was passiert bei Rauschen und Störungeinkopplungen auf dem Analogwert?

Oder soll der Analogwert eine Geschwindigkeit abbilden?
Das wäre sowieso die einfachere Möglichkeit, denn wenn der ADC eine 
Absolutposition ausgeben soll, dann kannst du mit einem 10-Bit-DAC 
gerade mal 1 einzige Umdrehungen eines 256er-Drehgebers mit 
4-fach-Auswertung abbilden...

von Bongo (Gast)


Lesenswert?

Ja D. schrieb:
> Von dem Controller kann ich aber nur analoge Signale
> ausgeben, also ist die Idee, dass ich die Rotorposition als analoges
> Signal ausgebe und in das FPGA einlese, wo dann die Schaltimpulse A/B
> erzeugt werden. Dazu muss ich das analoge Signal einlesen, die Richtung
> erkennen und die Schaltimpulse erzeugen.
d.h. du kriegst die Position als AD-gewandelten Digitalwert?

Dann gilt das was ich hier schrieb:

Ralf schrieb:
> Angenommen, man kann das Signal in einen Winkel übersetzen, dann muss
> einfach nur für A = 0 ... 180 und für B=90 ...270 eine 1 ausgegeben
> werden.
>
> 000 ... 090  A=1, B=0
> 090 ... 180  A=1, B=1
> 180 ... 270  A=0, B=1
> 270 ... 360  A=0, B=0

Muss halt noch etwas Hysterese rein und zwar in den Winkelwert. Der darf 
nicht wackeln, sondern muss nur in einer Richtung laufen. Das Beispiel 
hier aus dem Artikelbereich von Danegger ist doch so etwas ...

von Ja D. (jacoie)


Angehängte Dateien:

Lesenswert?

> Was da "empfindlich" sein kann, ist eine ungünstig beschriebene
> Hardware. Denn natürlich darfst du z.B. niemals zwei Integer einfach so
> kombinatorisch vergleichen und auf dieses Vergleichsergebnis asynchron
> reagieren. Denn dann spuckt dir natürlich jeder Glitch und jeder Spike
> in die Suppe. Mit höchster Wahrscheinlichkeit hast du damals genau diese
> Erfahrung gemacht.
>

Danke, du hast natürlich recht. Das ist genau das, was ich vermeiden 
wollte... Ich hoffe, ich lerne aus meinen Fehlern. Zu meiner 
Verteidigung muss ich sagen, dass ich das letzte Mal vor 3 Jahren VHDL 
geschrieben habe und nicht annähernd so erfahren bin wie du

> Beschreib doch mal die Lösung, wie du sie dir vorstellst, denn offenbar
> macht dir dabei eine wie auch immer gerartete "Richtungserkennung"
> Probleme.

Ich habe hier ein entsprechendes Bild des Vorhabens beigefügt.

> Und überleg mal eine Antwort auf diese Fragen:
> Wie willst du die Position in dem Analogwert unterbringen?

 Der Vorschlag von Ralph ist wirklich spannend, nur müsste man 
prinzipiell auch wissen, ob das digitalisierte Positionssignal 
inkrementiert oder dekrementiert.

Ralf schrieb:
> Angenommen, man kann das Signal in einen Winkel übersetzen, dann muss
> einfach nur für A = 0 ... 180 und für B=90 ...270 eine 1 ausgegeben
> werden.
>
> 000 ... 090  A=1, B=0
> 090 ... 180  A=1, B=1
> 180 ... 270  A=0, B=1
> 270 ... 360  A=0, B=0

> Wie willst du die "Unendlichkeit" eines Drehgebers abbilden?

durch Aufteilung des Positionssignals in 4 Winkelsektoren kann ich die 
Ausgabe eines Gary-Codes nach jeder Periode wiederholen

> Was passiert bei Rauschen und Störungeinkopplungen auf dem Analogwert?

Ich werde ein analoges Differenzsignal für die Übertragung zwischen dem 
Controller und dem FPGA verwenden, so dass die Einkopplung von Störungen 
reduziert wird.

> Oder soll der Analogwert eine Geschwindigkeit abbilden?

nein

von Ja D. (jacoie)


Lesenswert?

Ralf schrieb:

> Angenommen, man kann das Signal in einen Winkel übersetzen, dann muss
> einfach nur für A = 0 ... 180 und für B=90 ...270 eine 1 ausgegeben
> werden.
>
> 000 ... 090  A=1, B=0
> 090 ... 180  A=1, B=1
> 180 ... 270  A=0, B=1
> 279 ... 360  A=0, B=0

vielen Dank für den Vorschlag

von Jürgen S. (engineer) Benutzerseite


Lesenswert?

Lothar M. schrieb:
> Das ist im ersten Ansatz eigentlich ganz einfach, es müssen nur
> hinreichend große ROM/RAM vorbelegt werden, dann kann ich mit den
> AD-Werten als Adressvektor direkt die A/B/0-Werte auslesen.
Warum als Tabelle und nicht analytisch, mathematisch? Das Umsetzen von 
Winkel auf AB ist - wenn man meine Liste von oben mit den ganzen 
Einflüssen zur Seite lässt - ja nun eigentlich trivial, oder?

Eine Tabelle würde ich eher hernehmen, um ein Sin/Cos-Signal aus der 
Position zu generieren (was man mein Modell selbstredend auch kann).

Ja D. schrieb:
> Ich werde ein analoges Differenzsignal für die Übertragung zwischen dem
> Controller und dem FPGA verwenden, so dass die Einkopplung von Störungen
> reduziert wird.
Das wird nicht reichen, weil schon die Drehgebersignale verrauscht sind. 
Sie sind es gerade durch Wellenschwingungen. Man kann auf schnellen 
Maschinengebern regelrecht die Phasenmodulation von Störungen messen und 
im Einzelfall sogar diese als Signal hernehmen, um Körperschall 
aufzugreifen. Dann wirken die Encoder als Mikrofone :-)

Zur Zeichnung:

Wenn es analoges Signal des Typs X,Y ist, wie hier im Raume steht, dann 
braucht es in der analogen Welt einen Komparator. Der aber sollte wie 
ein Schmitt-Trigger funktionieren, also zwei Schaltschwellen haben. Gfs 
braucht es noch ein auto-gain, um selbige nachzuregeln.

Ja D. schrieb:
> dass ich das letzte Mal vor 3 Jahren VHDL geschrieben habe
das ist ein reines Digitalthema. Mit einem Microcontroller müsste man es 
genau so machen.

Ja D. schrieb:
> Ich habe schon an so etwas gedacht, um fehlerhafte
> Schaltimpulse zu erzeugen, damit ich sehen kann, wie die
> Weiterverarbeitung der Signale mit solchen Störungen umgehen kann.
Genau dafür werden solche Modelle genutzt - wenn auch oft einfacher.

... und letztlich dient die Emulation sicher dazu, die nachfolgende 
Auswertung zu testen, nehme ich an.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Ja D. schrieb:
> Ich habe hier ein entsprechendes Bild des Vorhabens beigefügt.
Ich kann das Analogsignal nicht der A/B Spur zuordnen. Kannst du die mal 
übereinander malen? Dabei musst du bedenken, dass es abgesehen von den 
Maximalwerten jeden Analogwert 2x gibt. Wenn ich dir sage: der 
Analogwert ist 0.707 vom Maximalwert, dann kannst du mir nicht sagen, ob 
ich damit 45° oder 135° meine.

>> Wie willst du die "Unendlichkeit" eines Drehgebers abbilden?
> durch Aufteilung des Positionssignals in 4 Winkelsektoren kann ich die
> Ausgabe eines Gary-Codes nach jeder Periode wiederholen
Ich möchte behaupten, dass du das nicht ganz fertig gedacht hast. Zeig 
doch mal, wie du das Analogsignal da auf den Graycode abbilden willst. 
Und vor allem: wie du es schaffst, die Übergänge des Analogsignals so 
zu gestalten, dass dieser Graycode nicht nur immer vor- und zurückläuft.

von Ja D. (jacoie)


Lesenswert?

> Ich kann das Analogsignal nicht der A/B Spur zuordnen. Kannst du die mal
> übereinander malen? Dabei musst du bedenken, dass es abgesehen von den
> Maximalwerten jeden Analogwert 2x gibt. Wenn ich dir sage: der
> Analogwert ist 0.707 vom Maximalwert, dann kannst du mir nicht sagen, ob
> ich damit 45° oder 135° meine.

auch hier hast Du völlig recht, ich werde die Winkelinformation vom 
Controller in Form eines Sägezahnsignals ausgeben zwischen 0 und 2*pi, 
dann hätte ich das Problem nicht mehr.

> Ich möchte behaupten, dass du das nicht ganz fertig gedacht hast. Zeig
> doch mal, wie du das Analogsignal da auf den Graycode abbilden willst.
> Und vor allem: wie du es schaffst, die Übergänge des Analogsignals so
> zu gestalten, dass dieser Graycode nicht nur immer vor- und zurückläuft.

Ich werde zunächst versuchen, es pragmatisch und nicht sehr clever zu 
lösen, indem ich die Drehrichtung als digitales Signal aus dem 
Controller lese und je nach Zustand entscheide, ob ich vorwärts oder 
rückwärts drehe....wahrscheintlich bilde ich mir dadurch unnötige Jitter

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Ja D. schrieb:
> ich werde die Winkelinformation vom Controller in Form eines
> Sägezahnsignals ausgeben zwischen 0 und 2*pi, dann hätte ich das Problem
> nicht mehr.
Ein Sägezahn steigt theoretisch linear vom Minimalwert zum Maximalwert 
und fällt in der Zeit 0 wieder auf den Minimalwert.

Und jetzt kommt der Knackpunkt: in der Praxis gibt es aber keine 
unendlich steilen Flanken, deshalb läuft das im Analogwert codiert 
Bitmuster langsam "hoch" und schnell wieder "runter".
Und dazwischen gibt es alle möglichen Glitches und Spikes.

von Jürgen S. (engineer) Benutzerseite


Lesenswert?

Lothar M. schrieb:
> Und jetzt kommt der Knackpunkt: in der Praxis gibt es aber keine
> unendlich steilen Flanken,

Nun ja, ein schneller GaAs-Schalttransi, dann geht es sogar für 
FPGA-Eingänge zackig genug :-)

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.