Guten Abend,
ich möchte die elektrische Rotorlage mit einem optischen Encoder
bestimmen.
Von dem Encoder bekomme ich die Signale A und B (GrayCode) welche ich in
einem Timer IRQ verarbeite:
Da der Zähler von dem Encoder pro reale Umdrehung um 4096 erhöht wird,
setze ich ihn alle 4096 wieder auf null um so eine zyklische Zählung zu
erhalten (siehe die zwei if's)
Der mit dem Encoder verbundene Motor macht pro reale Umdrehung 7
elektrische Umdrehungen.
Die Berechnung des elektrischen Winkels (in rad) sieht folgendermaßen
aus:
1
floatposition_p=(float)position;
2
// 4096 / 7 = 585.1428571
3
while(position_p>585.1428571)
4
{
5
position_p-=585.1428571;
6
}
7
8
// 2PI / 585.1428571 = 0.01073786552
9
angle=(position_p)*0.01073786552;
Der BLDC Motor wird mit einem festen, langsamen, Drehfeld gesteuert,
sprich ich weiß programmintern, welcher elektrischer Winkel gerade
anliegt.
Der vom Encoder berechnete Winkel driftet allerdings vom fest
vorgegebenen Winkel langsam ab.
Die Erklärung dazu wäre ja dass meine Float Werte nicht unendlich genau
sind, aber wie kann der Winkel driften, wenn ich quasi jedes mal mit dem
inkrementierten Wert (Integer) neu rechne?
Wie berechnet man den Winkel bei so einer Krummen Polzahl korrekt? Die
ganze Float Sache ist ja nicht besonders schön.
Davor hatte ich einen Motor, welcher 8 elektr. Rotationen pro Umdrehung
macht, da war es kein Problem, denn 4096 / 8 = 512 (=kein Float, schöner
runder Wert)
(Es ist mir wichtig, dass der Winkel am Ende als Fließkommazahl in Rad
vorliegt)
Grüße,
Andreas
Wenn möglich, solltest du die Hardwareunterstützung für Quadraturencoder
verwenden. Was ist das für ein Mikrocontroller? STM32 oder XMEGA z.B.
haben das. Softwarelösungen sind prinzipiell sehr empfindlich. Funkt ein
anderer IRQ kurzfristig dazwischen, verliert man u.U. einen Click und
Ähnliches...
Drift bei deiner Anwendung hat man aber prinzipiell immer, denn die
Fertigungsgenauigkeit eines Drehgebers ist begrenzt. Bei nominalen 4096
CPR hast du vielleicht tatsächliche 4095.8 CPR o.ä. Eventuell ist das
sogar temperaturabhängig. Die mangelnde Precision von Floats ist das
kleinste Problem!
Es gibt aber eine Lösung: Encoder mit Indexsignal nehmen und beim
Nullpunkt den Wert zurücksetzen.
drama schrieb:> Quadraturencoder
Kann der GrayCode!?
drama schrieb:> Encoder mit Indexsignal
Was meinst Du damit im Gegensatz zum GrayCode?
drama schrieb:> Drift bei deiner Anwendung hat man aber prinzipiell immer, denn die> Fertigungsgenauigkeit eines Drehgebers ist begrenzt.
Eine Umdrehung ist eine Umdrehung! Die GrayCode-Scheibe kann sich doch
nicht drehen.
Ich denke "Softwarelösungen sind prinzipiell sehr empfindlich" ist der
richtige Hinweis.
Andreas True schrieb:> Von dem Encoder bekomme ich die Signale A und B (GrayCode)
Das ist kein richtiger Graycode, sondern schlichte Quadratursignale, hat
sich aber wohl schon geklärt. Warum adaptierst du nicht PeDas Drehgeber
Routine auf den STM32? Die läuft sehr zuverlässig und ist auch auf
verschiedene Quadratursignale anpassbar (1,2 und 4 stufig).
Deine ISR verliert nämlich beim hin- und herdrehen ab und zu mal einen
Step, das ist der Haken, wenn man nur ein Signal (A oder B) zum
Auslösen der ISR nimmt.
Beitrag "Drehgeber/Encoder 1-, 2- oder 4-schrittig"
Da hier nur ein Timer benutzt wird, und der STM32 davon mehr als genug
hat, sollte das ohne Probleme klappen.
>wenn man nur ein Signal (A oder B) zum Auslösen der ISR nimmt
Er benutzt doch gar keinen Flanke, um die Dekodierung zu triggern,
sondern einen Timer. Und solange innerhalb dieser Zeitperiode nie 2
Impulse in die gleiche Richtung kommen wird es kleine Probleme geben.
Die Auswertung sieht richtig aus.
Allerdings sehen ich auch in der Float Umrechnung kein Problem. Klar
gibt es kleine Fehler, aber die akkumulieren sich hier doch nicht auf.
Angenommen, "position" steht nach x Umdrehungen wieder auf 0. Der
Drehgehen also in der Ursprungslage, dann ist position_p = 0 und auch
angle.
Kannst Du das testen? Also Drehgeber markieren, Lage 0, Drehgeber bei
0°.
Lange drehen lassen. Rotor wieder auf 0° drehen.
Steht dann die Variable "position" auch auf (fast)0?
Matthias Sch. schrieb:> Warum adaptierst du nicht PeDas Drehgeber> Routine auf den STM32? Die läuft sehr zuverlässig und ist auch auf> verschiedene Quadratursignale anpassbar (1,2 und 4 stufig).
Die Aktion kann er sich schenken, da diese Routinen viel zu langsam
sind.
Entweder nimmt man einen Hardwaredekoder, wovon der STM32 viele hat,
oder, falls die Pins nicht passen, wertet man per Interrupt aus.
Nachfolgender Link zeigt auf Beispiele mit AVRs, mit einem STM32 geht es
genauso einfach nur noch viel schneller.
Beitrag "4-fach Flankenauswertung per Interrupt mit ATmega48/88"Andreas True schrieb:> Da der Zähler von dem Encoder pro reale Umdrehung um 4096 erhöht wird,> setze ich ihn alle 4096 wieder auf null um so eine zyklische Zählung zu> erhalten (siehe die zwei if's)
Ich weiß nicht, was das soll, aber den Wert mit 4095 zu maskieren ist
zuverlässiger.
Wie hoch ist denn die max. Drehzahl des Motors?
Matthias Sch. schrieb:> sondern schlichte Quadratursignale, hat sich aber wohl schon geklärt.
Nein, hatte ich bis eben anders verstanden. Stimmt: Bei "Signal (A oder
B)" kann es tatsächlich kein GrayCode sein.
drama schrieb:> Wenn möglich, solltest du die Hardwareunterstützung für Quadraturencoder> verwenden. Was ist das für ein Mikrocontroller?
Da muss Andreas erstmal antworten, denn beim STM32 macht Interrupt z.B.
wegen dem eingebauten Quadraturdecoders incl. Entprellung überhaupt gar
keinen Sinn. Das wäre das nichtmal eine Glaubensfrage.
Guten Tag,
vielen Dank für die vielen Antworten.
Die interrupt Routine läuft mit 1MHz, also keine Flankentriggerung. Der
Encoder macht laut Datenblatt max. 100kHz (oder maximal 6k Umrd.),
sollte also locker passen. Der Interrupt hat auch die höchste Prio. in
meinem Programm.
Der Encoder hat einen zusätzlichen Z Durchgang rausgeführt, jedoch
dachte ich dass ich mit A und B auskommen müsste da man ja eig. keinen
Einlesefehler dank des GrayCodes bekommen sollte oder?
Das mit kgv hört sich nicht schlecht an :)
Position am Encoder Markieren, ein paar mal drehen lassen und schauen ob
die Variable 'position' danach immer noch an der selben stelle ist,
werde ich heute nach der Arbeit auch ausprobieren.
So, ich hoffe ich habe allen geantwortet, habs nur schnell überflogen,
da Mitttagspause.
PS: uC ist ein STM32F4, jedoch hätte ich gerne eine Softwarelösung um
flexibel zu bleiben, wenn es natürlich möglich ist.
Grüße
Andreas
>sollte also locker passen
Ob es wirklich reicht: Einfach noch den 4. Zustand (Fehler) nicht auf 0,
sondern auf einen anderen Wert setzen und den dann abfragen.
Es darf nicht gesetzt werden.
Andreas True schrieb:> Die interrupt Routine läuft mit 1MHz, also keine Flankentriggerung. Der> Encoder macht laut Datenblatt max. 100kHz (oder maximal 6k Umrd.),> sollte also locker passen.
Dann sieh Dir mal das Listing der ISR an! Der Code ist zu groß, um mit 1
MHz zuverlässig abgearbeitet werden zu können. Der STM32F4 ist sehr
schnell, verlangt für solche Geschichten aber auch eine passende
Programmierung. Dazu gehören, PortD mit einem Befehl einzulesen und
diesen Tabellenquatsch zu unterlassen!
Die Flanken an PortD0 + PortD1 kann man per Interrupt schnell erfassen;
der µC wird nur belastet, wenn Flanken auftreten. Die 1 MHz Grundlast
von TIM2 kann vollständig entfallen.
Andreas True schrieb:> jedoch hätte ich gerne eine Softwarelösung um> flexibel zu bleiben
Ich glaube, Du hast das nicht verstanden: Es geht darum, den
integrierten Timer zu benutzen. Den kannst Du doch flexibel
parametrieren. Beispiel:
Dispol schrieb:> Kann TIM1 Quadratursignale dekodieren?
Falls sich das auf mein Beispiel bezog:
Das war Cut&Paste aus meinem Projekt mit dem STM32F103C8.
Ich glaube es gibt hier ein generelles Verständnisproblem was die
Signale A, B und Z bedeuten und wie A und B codiert ist. A und B sind
Inkrementelle Signale die in ihrer Phasenlage kodiert haben ob es Vor-
oder Rückwärts geht. Der Z-Impuls ist der Null-Impuls um den Anfang
einer 360 Grad Umdrehung zu definieren. Am deutlichsten wird es wenn man
sich ein Zeitdiagramm des Verlaufen über 360 Grad ansieht
(http://www.ichaus.de/wp2_encoderanschluss Bild 2 auf Seite drei). Per
Software müssen dann die Flanken mit Phasenlage vor- oder zurückgezählt
werden und mit dem Z-Impuls wird der Zähler auf Null gesetzt, bzw. es
kann überprüft werden ob die Software auch alle Flanken korrekt gezählt
hat, bzw. welche verloren hat. Sinnvoll ist auch in der Software zu
prüfen das A/B-Signal keinen Jitter hat, z.B. durch Doppelabfrage des
Pegels.
m.n. schrieb:> Die Flanken an PortD0 + PortD1 kann man per Interrupt schnell erfassen;
Meinst du dass man zB auf steigende und fallende Flanken der Pins einen
IRQ triggert? Das habe ich anfangs auch so gemacht, und es lief extrem
schlecht, trotz logischer Überprüfung, dass A nicht zwei mal getriggert
wird, bevor B getriggert wurde etc. Dann habe ich gelesen, dass man
Encoder unbedingt mit einer Timer IRQ verarbeiten sollte, ist auch hier
beschrieben:
http://www.dse-faq.elektronik-kompendium.de/dse-faq.htm#F.29
@Torsten C: gut, so 'unflexibel' sieht es nicht aus. Ohne mich damit
bereits beschäftigt zu haben, könntest du mir vielleicht ein paar Fragen
beantworten?
1. Verstehe ich es richtig, dass der CounterWert dann in TIM1 steht?
2. Bedeutet die "16384", dass der Timer bis 16384 zählt und dann wieder
bei 1 anfängt?
3. Kann die Funktion auch rückwärts Zählen?
4. Mein Encoder macht auf A und auf B pro Umdrehung jeweils 1024
versetzte Ticks, durch den GrayCode (fallende und steigende von A und B
beachten) komme ich so auf 4096 Ticks pro Umdrehung, macht die Funktion
TIM_EncoderInterfaceConfig(..) das auch so?
Mir hat meine Funktion eigentlich gut gefallen, (siehe auch Link oben)
schade dass es anscheinend doch nicht so gut ist :(
EDIT:
@Horst H:
Würde es genügen, wenn ich statt meiner zwei IFs einfach so etwas wie
hinzufügen würde? Gibt es eine Lösung wie Torsten C sie vorgeschlagen
hat, nur dass auch Z beachtet wird?
Ich kann es gerade leider noch nicht ausprobieren.
Grüße
Andreas
Andreas True schrieb:> 1. Verstehe ich es richtig, dass der CounterWert dann in TIM1 steht?
Ja.
> 2. Bedeutet die "16384", dass der Timer bis 16384 zählt und dann wieder> bei 1 anfängt?
Nein, damit habe ich nur initialisiert. Er geht von 0 .. 32767.
> 3. Kann die Funktion auch rückwärts Zählen?
Klar, das ist doch der einzige Sinn des Quadraturdecoders.
> 4. Mein Encoder macht auf A und auf B pro Umdrehung jeweils 1024> versetzte Ticks, durch den GrayCode (fallende und steigende von A und B> beachten) komme ich so auf 4096 Ticks pro Umdrehung, macht die Funktion> TIM_EncoderInterfaceConfig(..) das auch so?
Ja. Weil der Timer von 0 bis 32767 zählt, verunde mit 0x0FFF, dann hast
Du da Dein 0 .. 4095.
Du kannst in den restlichen MSBits noch volle Umdrehungen auslesen.
Andreas True schrieb:> m.n. schrieb:>> Die Flanken an PortD0 + PortD1 kann man per Interrupt schnell erfassen;>> Meinst du dass man zB auf steigende und fallende Flanken der Pins einen> IRQ triggert? Das habe ich anfangs auch so gemacht, und es lief extrem> schlecht, trotz logischer Überprüfung, dass A nicht zwei mal getriggert> wird, bevor B getriggert wurde etc.
Es kommt darauf an, wie fein Du das Encodersignal auswerten möchtest.
Bei 2-fach Auswertung, braucht man nur eine ISR, die auf positive und
negative Flanken hin angesprungen wird. In der ISR wird lediglich
entschieden ob +1 oder -1 zum Zähler addiert werden muß. Nichts mit
Entprellen oder sonstigen Prüfungen!
Bei 4-fach Auswertung braucht man eine 2. ISR für den anderen Kanal,
wobei die Fallunterscheidung invertiert wird, sodaß der Zähler
fortlaufend in-/dekrementiert wird je nach Drehrichtung.
> Dann habe ich gelesen, dass man> Encoder unbedingt mit einer Timer IRQ verarbeiten sollte, ist auch hier> beschrieben:
Das schreiben in der Regel Leute, die die Hose sofort gestrichen voll
haben, sobald das Wort 'Interrupt' auftaucht. Sie kennen nichts anderes,
haben nie etwas anderes gebraucht bzw. probiert und schreien immer nur
laut: Verrat! Ignoriere es einfach!
Andreas True schrieb:> Mir hat meine Funktion eigentlich gut gefallen,
Aber hier sind Dir doch schon Überläufe passiert, die Du kompensieren
mußtest.
> TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
Wenn Die Routine schnell genug ist, ist dieses Bit nie gesetzt.
Ich zeige Dir ein einfaches Beispiel für 2-fach Auswertung.
(Ich hoffe, ich habe es richtig für den STM32F4 angepaßt.)
#define PHASE_A 0 // an PORTD.0
#define PHASE_B 1 // an PORTD.1
#define MASKE 3 // vereinfachte Schreibweise
volatile int count;
// nur Interrupt eines Pins wird zur Auswertung verwendet
void XYZ_IRQHandler(void) // muß für Phase_A angepaßt werden
{
int8_t temp = GPIOD->IDR & MASKE; // Zustand der beiden Phasen lesen
if((temp & MASKE) == MASKE ||
(temp & MASKE) == 0) // PHASE_A und PHASE_B auswerten
count++; // PHASE_A == PHASE_B: Zaehler + 1
else
count--; // ungleicher Pegel: Zaehler - 1
}
Wenig Code, ganz schnell und nur aktiv, wenn sich eine Flanke an Phase_A
zeigt.
>Das schreiben in der Regel Leute, die die Hose sofort gestrichen voll>haben, sobald das Wort 'Interrupt' auftaucht. Sie kennen nichts anderes,>haben nie etwas anderes gebraucht bzw. probiert und schreien immer nur>laut: Verrat! Ignoriere es einfach!
Der Nachteil einer Interrupt-bei-Flanke Lösung ist halt: Hast Du ein
hochfrequentes Signal am Eingang, steht das System.
Der Nachteil einer Lösung mit fester Abtastzeit ist: Man hat immer eine
fest Auslastung. Auch wenn sich nichts tut.
Eine 3. Lösung wäre eine Interrupt bei Flanke, der jedoch für eine Zeit
x nach dem Event gesperrt bleibt. Dann hätte man beide Vorteile. Aber
das wäre etwas komplizierter.
Ideal ist natürlich, ein Hardware zu nutzen (Wenn es eine gibt). Wobei
ich mir nicht ganz sicher bin, ob beim STM32 wirklich alle 4 Zustände
gezählt werden. Beim letzten Projekte war ich der Meinung, es waren nur
2. Das spielte für mich jedoch keine Rolle.
Dispol schrieb:> Der Nachteil einer Interrupt-bei-Flanke Lösung ist halt: Hast Du ein> hochfrequentes Signal am Eingang, steht das System.
Wo, bitte schön, soll denn dieses 'hochfrequente' Signal herkommen? Der
Drehgeber liefert es nicht!
Dieses 'hochfrequente' Signal taucht als 'Argument' immer dann auf, wenn
es um Drehgeberauswertung per Interrupt geht. Bei ser. Datenübertragung
gibt es das wohl nicht; die läuft immer völlig störungsfrei ;-)
Dispol schrieb:> Eine 3. Lösung wäre eine Interrupt bei Flanke, der jedoch für eine Zeit> x nach dem Event gesperrt bleibt. Dann hätte man beide Vorteile. Aber> das wäre etwas komplizierter.
Dafür würden sich Capture-Eingänge von Timern eignen, die selber keine
Encoderauswertung bieten (TIM9-TIM14). Diese haben wirksame
Eingangsfilter. Der Timer selbst wird nicht benötigt.
Dispol schrieb:> Ideal ist natürlich, ein Hardware zu nutzen (Wenn es eine gibt). Wobei> ich mir nicht ganz sicher bin, ob beim STM32 wirklich alle 4 Zustände> gezählt werden. Beim letzten Projekte war ich der Meinung, es waren nur> 2. Das spielte für mich jedoch keine Rolle.
Wenn man das beim Design berücksichtigt, ist es fraglos die beste
Lösung. Man kann zwischen 2-fach und 4-fach Auswertung wählen; siehe
Ref.-Manual.
Fall es um ein Design geht, kann ich noch den HCTL-2022 vorschlagen. Ich
weiß, dass ist zwar antiquiert aber es passt zum Thema. Ich schlage mich
schon seid 15 Jahren mit diesem Thema rum und habe damals zu einer FPGA
Lösung gegriffen und bin nie enttäuscht worden. Über den HCTL-2022 bin
ich mal durch Zufall gestolpert.
Ein Trick habe ich noch genutzt, wenn sich bei der Abtastung ergibt,
dass sich beide Encodersignale geändert haben, ist die
Wahrscheinlichkeit groß, dass es zwei Schritte in die gleiche Richtung
wie beim letzten mal waren.
Die nächste Herausforderung ist die Auswertung von SIN/COS Signalen. Die
Periodendauer ist oft größer und sie können z.B. mit einem ADC122S706
simultan samplend werden.
Guten Abend,
vielen Dank für die zahlreichen Vorschläge, m.n. vielen Dank für den
Code!
Ich habe es erstmal so wie Torsten es vorgeschlagen, mit einem Timer
gemacht und verunde das Ergebnis immer mit 0x0FFF. Leider driftet der
Winkel immer noch ab.
Ich lasse den Motor 300 Umdrehungen fahren, markiere mir zu Sicherheit
die Rotorposition. Der Timer Counter steht 1723.
Dann lasse ich den Motor weitere 300 Umdrehungen fahren, die markierte
Position stimmt überein. Der Timer Counter steht nun aber bei 1425.
(1723-1425)/4095 => bedeutet dass die markierte Position um 26 Grad
abweichen müsste, was nicht Fall ist.
Wie könnte ich am geschicktesten den Timer mit der Z Phase zurücksetzen?
So wie ich das am Scope sehe, gibt Z immer nur einen ganz kurzen
NegativImpuls, vermutlich ein mal pro Umdrehung.
Wenn ich nun auf Z einen Flanken Interrupt mache und den Timer
zurücksetze, werde ich ja wieder mit Mehrfachtriggerung zu tun bekommen.
EDIT: Z gibt einen negativen Puls siehe PDF Seite 5 Timingdiagram
http://dlnmh9ip6v2uc.cloudfront.net/datasheets/Robotics/E6B2Encoders.pdf
Grüße
Andreas
Nur so eine Idee:
Du hast die Zahlen 1425, 300 und 1723.
Auf den ersten Blick 1425 + 300 = ~ 1723.
Kann es sein, dass deine Umdrehung irgendwie um 1 zu kurz/zu lange ist?
Wiederhole doch den gleichen Versuch mit 150 oder 600 Umdrehungen,
um zu sehen, ob die obige Berechnung wieder ähnliche Ergebnisse liefert.
Martin H. schrieb:> Die nächste Herausforderung ist die Auswertung von SIN/COS Signalen. Die> Periodendauer ist oft größer und sie können z.B. mit einem ADC122S706> simultan samplend werden.
So mache ich es, seitdem es den AT90S4433 gibt:
http://www.mino-elektronik.de/mt12_iic/mt12_iic.htm
Mit einen ATmega48 kommt die Schaltung mit minimaler Hardware aus.
Ein STM32F407 hat drei ADCs und kann ebenfalls simultan abtasten. Damit
geht es dann noch besser, als mit HCTL-xxx + ADCxxx. Aber ein bißchen
Hirn braucht man doch noch für eine perfekte Lösung.
Martin Maurer schrieb:> Wiederhole doch den gleichen Versuch mit 150 oder 600 Umdrehungen,> um zu sehen, ob die obige Berechnung wieder ähnliche Ergebnisse liefert.
Und vielleicht auch noch rückwärts drehen lassen und beobachten, was
passiert.
m.n. schrieb:> So mache ich es, seitdem es den AT90S4433 gibt:> http://www.mino-elektronik.de/mt12_iic/mt12_iic.htm
Ich verwende wie oben erwähnt eine FPGA Lösung, der hat keinen ADC daher
das extra Bauelement. Du hast ja auch noch 2 OPV verwendet, diese sind
im differentiellen ADC schon integriert. Außerdem muss ich 20 um mit
5m/s erfassen können da brauche ich 1MS um die Quadratur nicht zu
verpassen.
Disco schrieb:> Du hast ja auch noch 2 OPV verwendet, diese sind> im differentiellen ADC schon integriert.
Die werden für die +/- 11 µA Signale als Strom/Spannungswandler
benötigt.
> Außerdem muss ich 20 um mit> 5m/s erfassen können da brauche ich 1MS um die Quadratur nicht zu> verpassen.
Bei mir geht's mehr um die Auflösung von 0,1 µm UND um die
Referenzmarke.
Sollen wir die Kosten beider Varianten vergleichen? Für einen ADC122S706
müßte schon Weihnachten sein, damit ich ihn mir leisten kann ;-)
Aber es ist schon in Ordnung, wie Du es machst!
m.n. schrieb:> Für einen ADC122S706 müßte schon Weihnachten sein, damit ich ihn mir> leisten kann ;-)
Zum Glück ist der Weihnachtsmann immer gnädig mit mir. Bauche etwa 60
Stück im Jahr... Aber ich sollte vielleicht auch mal schauen, dass er
nicht so tief in die Tasche greifen muss. Trotzdem auch Dir schöne
Weihnachten, die Lösung sieht auch super aus. Und entscheidend ist ja
noch die weitere Auswertung... Amplitude, Pahase usw.
m.n. schrieb:> Ein STM32F407 hat drei ADCs und kann ebenfalls simultan abtasten
Die ADCs sind bei mir leider schon belegt (Phasenstrommessung für SVPWM,
muss unbedingt simultan laufen)
Wenn ich den Encoder nicht mit einem Timer Interrupt, wie anfangs
auswerte, sondern wie Torsten es vorgeschlagen hat, mit
TIM_EncoderInterfaceConfig(..), bekomme ich pro Umdrehung nicht 4096
sondern nur noch die Hälfte, was aber von der Genauigkeit her kein
Problem ist.
Der Code sieht aktuell so aus:
Martin Maurer schrieb:> Wiederhole doch den gleichen Versuch mit 150 oder 600 Umdrehungen
Die Counterstände mit dem oberen Code nach jeweils 150 Umdrehungen:
300 - 279 - 259 - 237 - 208 - 166
(der Motor ist dabei jedes mal an der selben Markierung stehen
geblieben)
Etwas anderes: Laut Datenblatt macht der Encoder nicht 2048 sondern 2000
Ticks, wenn ich allerdings den Counter weiter zählen lasse:
1
TIM_TimeBaseStructure.TIM_Period=0xffff;
und per Mausklick eine Umdrehung fahren lasse, ändert sich der
Zählerstand immer um 2048.
Gibt es eine Möglichkeit den TIM zusätzlich mit der Z Phase zu koppeln?
Grüße,
Andreas
Hallo "m.n.",
> Dispol schrieb:>> Der Nachteil einer Interrupt-bei-Flanke Lösung ist halt: Hast Du ein>> hochfrequentes Signal am Eingang, steht das System.>> Wo, bitte schön, soll denn dieses 'hochfrequente' Signal herkommen? Der> Drehgeber liefert es nicht!
Doch, dass kann ganz schnell gehen. Und zwar wenn der Geber genau an
einem Hell-Dunkel Übergang der Geberscheibe steht. Bei jeder kleinen
Vibration bekommst du dann einen ganzen Flankenzug an Pulsen, ohne das
sich die Position tatsächlich ändert. Bei Abtastung in einem festen
Zeitraster entgehen einem vielleicht die meisten dieser Pulse, was aber
keine Rolle spielt. Im nächsten Takt ist man entweder noch in der alten
Position, oder um +/-1 Inkrement weiter. Das ganze Gezappel auf der
Leitung kümmert nicht weiter.
Mit freundlichen Grüßen
Thorsten Ostermann
Thorsten Ostermann schrieb:> Doch, dass kann ganz schnell gehen. Und zwar wenn der Geber genau an> einem Hell-Dunkel Übergang der Geberscheibe steht. Bei jeder kleinen> Vibration bekommst du dann einen ganzen Flankenzug an Pulsen, ohne das> sich die Position tatsächlich ändert.
Es tut mir Leid, wenn Du jemals solche Probleme gehabt haben hätten
solltest.
Halbwegs brauchbare Geber machen so etwas nicht. Die haben intern zum
einen eine Hysterese und sind zum anderen elektrisch und mechanisch
intern so 'träge', daß die erdichteten Impulsströme garnicht entstehen
können.
Tu mir den Gefallen und schreibe diese Geschichten ins Märchenbuch.
Andreas True schrieb:> Der Encoder macht laut Datenblatt max. 100kHz
Die von mir gezeigte Interruptroutine schafft rund 3 MHz ;-)
Selbst, wenn die Auswertung nicht so schnell wäre, gäbe es 1000
Möglichkeiten, die Bandbreite zu begrenzen!
Andreas True schrieb:> Wenn ich den Encoder nicht mit einem Timer Interrupt, wie anfangs> auswerte, sondern wie Torsten es vorgeschlagen hat, mit> TIM_EncoderInterfaceConfig(..), bekomme ich pro Umdrehung nicht 4096> sondern nur noch die Hälfte, was aber von der Genauigkeit her kein> Problem ist.
(Gemeint ist hier ein anderer Torsten!)
Dann wird nur 2-fach Auswertung verwendet; das kann man umprogrammieren.
Siehe: Ref. Manual.
Mit dem Hardwaredekoder muß der Zählerstand immer stimmen, sonst stimmt
etwas mit Deinen Signalen nicht. (Vielleicht OC-Ausgang und Pullup zu
groß?)
Kannst Du u.U. TIM2 oder TIM5 verwenden? Deren Register sind 32 Bit
breit. Lasse sie unverändert und errechne die eff. Position erst dann,
wenn sie benötigt wird und kläre, ob es 2048 oder 2000 Schritte/U sind!
Anzahl Umdrehungen = TCNTx / 2000
aktuelle Position = TCNTx % 2000
Beim STM32F407 kannst Du auch auf float verzichten und gleich double
rechnen. Es ist affenschnell!
Hallo "m.n.",
> Thorsten Ostermann schrieb:>> Doch, dass kann ganz schnell gehen. Und zwar wenn der Geber genau an>> einem Hell-Dunkel Übergang der Geberscheibe steht. Bei jeder kleinen>> Vibration bekommst du dann einen ganzen Flankenzug an Pulsen, ohne das>> sich die Position tatsächlich ändert.>> Es tut mir Leid, wenn Du jemals solche Probleme gehabt haben hätten> solltest.> Halbwegs brauchbare Geber machen so etwas nicht. Die haben intern zum> einen eine Hysterese und sind zum anderen elektrisch und mechanisch> intern so 'träge', daß die erdichteten Impulsströme garnicht entstehen> können.> Tu mir den Gefallen und schreibe diese Geschichten ins Märchenbuch.
Da ich Encoder-Auswertung schon immer per Timer mache, bin ich nie in
die Verlegenheit gekommen. Die vielen Fragen und Probleme die hier in
Zusammenhang mit Encoder-Auswertung aufkommen zeigen aber, dass das ein
schwieriges Thema ist.
Wo die mechanische Trägkeit in einem Encoder herkommen soll musst du uns
mal genauer erklären. Bei den offenen Avago-Gebern ist ja z.B. nicht mal
ein Lager integriert. Den mechanischen Anbau macht dann der OEM. Auch
das mit der Hysterese halte ich für ein Gerücht. Das würde ja alles die
Messung verfälschen. Hysterese gibt es höchstens, wenn man aus einem
Rohsignalgeber (1Vss oder 20mA analog) digitale Signale per
Interpolationseinheit erzeugt.
Mit freundlichen Grüßen
Thorsten Ostermann
Thorsten Ostermann schrieb:> Da ich Encoder-Auswertung schon immer per Timer mache, bin ich nie in> die Verlegenheit gekommen.
Dann wiederhole doch bitte nicht die vorgeschobenen Argumente, die hier
andere Leute zu diesem Thema abgeben. Was ich von ihnen halte, hatte ich
ja weiter oben kommentiert.
Zeig mir reale, 'zitternde' Signale. Wenn sie tatsächlich auftreten
sollten, können wir gerne darüber diskutieren, wie man mit ihnen umgeht.
Vorweg: es ist kein Problem!
> Die vielen Fragen und Probleme die hier in> Zusammenhang mit Encoder-Auswertung aufkommen zeigen aber, dass das ein> schwieriges Thema ist.
Dabei geht es in der Regel doch um Drehgeber mit mechanischen Kontakten.
Da tauchen dann die 'PeDa-Glaubenskrieger' auf, unfähig über den
Tellerrand zu sehen und auf Alternativen einzugehen.
Da geht es dann aber auch nicht um Signale mit einigen 100 kHz, sondern
um solche im 100 Hz-Bereich: das ist doch langweilig!
Thorsten Ostermann schrieb:> Den mechanischen Anbau macht dann der OEM. Auch> das mit der Hysterese halte ich für ein Gerücht. Das würde ja alles die> Messung verfälschen.
Die Umformung analog->digital erledigt in der Regel ein Komparator;
dabei ist eine Hysterese Pflicht. Dadurch wird die Messung nicht
verfälscht sondern erst ermöglicht. Im einfachsten Fall hat der
verwendete µC diesen schom am Eingang integriert.
m.n. schrieb:> Tu mir den Gefallen und schreibe diese Geschichten ins Märchenbuch.
Ich hoffe, Thorsten Ostermann tut das nicht, ist ja auch kein Märchen.
@All: Hier geht es nicht um einen trollenden Gast und nicht ums "recht
haben wollen", sondern um einen Rat an Andreas True. Wir würden ihm
einen schlechen Rat geben, wenn wir hier was falsches behaupten.
@Andreas: Hat Dein Sensor eine Hysterese? Falls Du flexibel sein willst,
würde ich mich nicht darauf verlassen.
Ich habe einen Artikel gefunden, der das Problem ganz gut beschreibt.
Wichtig ist vor allem der Hinweis auf elektrische Störungen. Die werden
nämlich gerne vernachlässigt, was bei Motorsteuerungen mit PWM oft nicht
zulässig ist. Vor allem dann nicht, wenn man einen Encoder ohne
Linedriver verwendet.
http://quantumdevices.wordpress.com/2009/04/15/what-is-hysteresis-and-how-is-it-used-in-optical-encoders/
Der Artikel geht auch darauf ein, das eine größere Hysterese zu einem
größeren Messfehler führt.
Mit freundlichen Grüßen
Thorsten Ostermann
Thorsten Ostermann schrieb:> Vor allem dann nicht, wenn man einen Encoder ohne> Linedriver verwendet.
Wer schlampige Elektronik verwendet, der soll sich über Fehler nicht
wundern.
> http://quantumdevices.wordpress.com/2009/04/15/what-is-hysteresis-and-how-is-it-used-in-optical-encoders/> Der Artikel geht auch darauf ein, das eine größere Hysterese zu einem> größeren Messfehler führt.
Ich habe ihn überflogen und insbesondere die Bildchen angesehen.
Unskalierte Kurven sind ja ganz nett, aber für eine differenzierte
Betrachtung völlig daneben. Haben die gezeigten Sinuskurven nun 50 Hz
und ist ein 1 ms Impuls auszufiltern, oder sind es 1 MHz und die Störung
10 ns breit?
Daß eine größere Hysterese zu einem höheren Fehler führt, ist ja leicht
dahergesagt. Aber wie sieht es denn mit den Fehlern aus, wenn (wie oben
ausgeführt) ein 400 kHz Signal mit 1 MHz abgetastet wird? Erfolgt die
Abtastung etwa synchron im Nulldurchgang? Eben nicht, sondern mit völlig
wackelnder Phasenlage. Und das ergibt keine Fehler?
Wäre hier ein analoges Signal zu messen, würde jeder sofort auf die Idee
kommen, die Störungen per RC wegzufiltern. Sobald digitale Signale
vorliegen darf man aber anscheinend beliebige Störungen, sei es durch
mangelnde Abschirmung oder viel zu hochohmige Datenleitungen, zulassen.
Ich denke, ich lasse es sein, gegen Vorurteile zu argumentieren.
Da Andreas True die Hardwaredekoder entdeckt hat, liegt er auf der
sicheren Seite, sofern der Rest der Elektronik nicht 'verschlampt' ist.
m.n. schrieb:> Mit dem Hardwaredekoder muß der Zählerstand immer stimmen, sonst stimmt> etwas mit Deinen Signalen nicht. (Vielleicht OC-Ausgang und Pullup zu> groß?)
Ich habe den Motor jetzt 20000 Umdrehungen laufen lassen mit ca 1400rpm.
Der Drift vom elektrischen Winkel beträgt ca 85 Grad. Bei 7 elektrischen
Rotationen pro reale Umdrehung habe ich also 85 / 7 = 12 Grad Drift an
der Encoderwelle.
m.n. schrieb:> Da Andreas True die Hardwaredekoder entdeckt hat, liegt er auf der> sicheren Seite, sofern der Rest der Elektronik nicht 'verschlampt' ist
Ich muss zugeben dass die Elektronik dazu (noch) nicht schön ist. Auf
Lochraster, Spannung des Encoders billig mit Spannungsteiler auf 3 Volt
runtergeteilt, ca 50cm Leitungen zusammen mit PWM Zuleitungen. Da
könnten sich vllt. auch falsche Signal einschleichen.
Torsten C. schrieb:> @Andreas: Hat Dein Sensor eine Hysterese? Falls Du flexibel sein willst,> würde ich mich nicht darauf verlassen.
Ist Hysterese so etwas wie eine Plausibilitätsprüfung zwischen aktuellem
und letzten Wert? Habe dafür Google bemühen müssen :D
Bin mir nicht sicher ob der Encoder das hat.
Ich verwende jetzt den Hardware Encoder (mit TIM1) und zusätzlich
externe Interruptroutine für den Nulldurchgang in der ich den Timer auf
null setze. Bis jetzt habe ich keinen Drift festgestellt (geht ja auch
nicht wenn der Counter immer an der selben phys. Position zurückgesetzt
wird).
Allerdings:
ich gebe mir den Winkel mit dem ich den Motor künstlich füttere und den
Encoder Winkel jeweils als Sägezahnsignal am Scope aus, und ab und zu
zuckt der Encoderwinkel.
Entweder ist es Ablesefehler (Scope Trigger springt kurz etc.) oder die
Nulldurchgang Routine wird mehrmals ausgeführt.
Ich könnte mir vorstellen dass der Motor dann auch zucken wird.
Aber erstmal muss ich es hinbekommen, beim Start den Encoder Offset zum
Elektrischen Winkel des Motors richtig zu berechnen und zu beachten. Ist
wohl auch nicht ganz einfach da ich nach dem Einschalten ja nicht weiß
ob der Counter "bald" wieder durch den Nulldurchgang Interrupt
zurückgesetzt wird.
Grüße
Andreas
Andreas True schrieb:> Ist Hysterese so etwas wie eine Plausibilitätsprüfung zwischen aktuellem> und letzten Wert?
Beim Übergang von Schwarz und Weiss gibt es zwei Schaltschwellen: Eine
für 1->0 und eine andere von 0->1. Dadurch kann man Störungen etwas
verringern, also solche wie hier:
http://quantumdevices.files.wordpress.com/2009/04/extra-pulses1.jpg?w=630
Welchen STM32 hast Du? Der STM32W108C8 hat z.B.
Schmitt-Trigger-Eingänge. Du könntest für eine Hysterese auch diskrete
Schmitt-Trigger ergänzen.
> Habe dafür Google bemühen müssen :D
Anderes Suchwort: Schmitt-Trigger
> Bin mir nicht sicher ob der Encoder das hat.
Vermutlich nicht. Ich kenne keine Encoder mit Hysterese, lerne aber gern
welche kennen.
m.n. schrieb:> Halbwegs brauchbare Geber … haben intern zum einen eine Hysterese …
Ach. Welcher?
Ich habe noch ein Problem mit dem Offset des Encoders.
Berechnet wird der Winkel Folgendermaßen:
1
intt_pos;
2
Angle=(((t_pos)*7)&0x07FF)*0.003067961576;
Erklärung:
Der Timer zählt 0..2047:
1
TIM_TimeBaseStructure.TIM_Period=0x07ff;
Das entspricht genau einer Umdrehung der Encoderwelle
Der Motor macht 7 elektrische Rotationen pro WellenUmdrehung.
Durch
1
(((t_pos)*7)&0x07FF)/7
erhalte ich die Anzahl der Zählerpulse seit der letzten vollen
elektrischen Umdrehung des Motors.
Es wird über kgV gerechnet um eine while(float > float) Schleife zu
sparen.
Ein Zählerpuls entspricht 0.0214 rad elektrisch.
(2048 / 7) = 292.5714 entspricht 2PI elektrisch
2PI / 292.5714 = 0.0214
Ergibt Folgendes:
1
Angle=(((t_pos)*7)&0x07FF)/7*0.0214
gekürzt:
1
Angle=((t_pos)*7)&0x07FF)*0.003067961576;
Ich hoffe es ist bis jetzt nachvollziehbar, es kommen auch plausible
Winkel raus.
Jetzt muss in diese Rechnung ein Offset integriert werden da der Encoder
mit der Motorwelle Winkelmäßig nicht übereinstimmt.
Dazu lasse ich den Motor am Anfang 2 volle, langsame Umdrehungen fahren,
damit der Encoder-Timer mit dem Nulldurchgang synchronisiert wird.
Jetzt steht der Motor auf Winkel_elektrisch == 0; und der Zähler hat
einen bestimmt Wert.
1
encoder_offset=((t_pos*7)&0x07ff)/7;
Dann bei der Winkelberechnung immer Offset berücksichtigen
1
t_pos=TIM1->CNT;
2
3
t_pos-=encoder_offset;
4
if(t_pos<0)t_pos+=2047;
5
if(t_pos>2047)t_pos-=2047;
6
Angle=((t_pos)*7)&0x07FF)*0.003067961576;
Am Ende kommt allerdings immer noch ein Falscher Winkel raus und die
Abweichung ist nach jedem Start nicht einmal konstant.
Ich hoffe, ihr habt in meiner Rechnung einigermaßen durchblicken können
und habt einen Fehler gefunden :)
Grüße
Andreas
Andreas True schrieb:> Ich hoffe, ihr habt in meiner Rechnung einigermaßen durchblicken können> und habt einen Fehler gefunden :)
1. Mach doch erst einmal den ersten Schritt und sorge dafür, daß der
Zähler richtig zählt. Wie ich bislang verstanden habe, gibt der Encoder
1000 Impulse/Spur/Umdrehung aus. Mit der 2-fach Auswertung sind es dann
2000 Impulse/U, die sich der Zählerstand ändern muß.
Vergiss daher alle von Dir ins Spiel gebrachten Zahlen 2047, 2048, 4095
und 4096!
2. Vergiss den Z-Impuls, der sich in dieser Form nicht als
Rücksetzimpuls eignet, und laß den Zähler frei weiterzählen. Dann
vergleiche Position und Zählerstand. Sofern hier Differenzen auftreten,
brauchst Du nichts weiter auszuwerten.
Sollten hier hingegen stabile Werte vorliegen, werte diese aus und laß
den Zähler unverändert.
Um weiter oben erwähnte 'Fehler' oder Hysteresen kümmere Dich nicht. Der
Encoder liefert Rechtecksignale und hat daher schon interne Hysteresen
samt dem daraus resultierenden 'Fehler', den Du getrost ignorieren
kannst!
Hallo m.n.
jetzt weis ich sicher, dass der Encoder 1024 Pulse macht, tolles
Datenblatt!
Der Encoder läuft jetzt stabil, der Timer wird in der Z Phase -
Interrupt Routine auf Null gesetzt. Warum eignet sich dieses Signal
nicht dafür? Am Oszi ist es ein schöner Rechteck (negativaktiv).
Allerdings habe ich den Aufbau gerade wieder ohne der Z Routine
ausprobiert und der Motor läuft sehr gut mit dem Winkel, keine Ahnung
was vorgestern mit dem Ding los war :/
EDIT: es kann sein, dass es vorgestern ohne Z nicht funktioniert hat,
weil ich den Minus des uC nicht mit dem Minus der restlichen Elektronik
verbunden hatte, diese waren quasi nur über Steckdose und PC USB
verbunden.
Mir ist es lieber wenn die Pulse immer vom gleichen realen Punkt aus
zählen. Nennt man sowas AbsolutEncoder? Ich brauche das ganze um einen
Winkelbeobachter für FOC mit SVPWM zu entwickeln und zu optimieren.
Ich habe es aber leider immer noch nicht geschafft, den Offset
rauszurechnen und richtig zu integrieren. Gibt es bessere
Vorgehensweisen, als die, die ich oben beschrieben habe?
Grüße
Andreas
Andreas True schrieb:> bekomme ich pro Umdrehung nicht 4096> sondern nur noch die Hälfte>> TIM_EncoderInterfaceConfig(TIM1, TIM_EncoderMode_TI2,> TIM_ICPolarity_Falling, TIM_ICPolarity_Rising);
Für 4x Auswertung:
TIM_EncoderMode_TI12 anstatt TIM_EncoderMode_TI2