So weit mir bekannt sind die üblichen Drehimpulsgeber (als Poti-alternative) eher so gebaut das sie ein Überlappendes Signal an zwei Pins ausgeben aus dem man die Richtung und Zahl der Impulse erst raus "rechnen" müsste.
Gibt es dazu evtl. ein IC (und wie heißt dessen Funktion) das diese Signale auftrennt so das man z.b. 2-3 einfache Digitale Signalausgänge erhält die einfach nur Links-drehende, Rechts-drehende Impulse und einen Ausgang für die Tastfunktion (falls auch codiert) liefern?
Das hielte ich jedenfalls für einfacher es so z.b. an den GPIO eines Raspi o.a. Mikrokontrollers an zu schließen als das in Software zu versuchen (was ich für noch schwieriger hielte).
Mit so einer Hardware-lösung könnte man den Geber auch als Ersatz für Up/Down Taster in irgend etwas ein setzen. Denke ich mir mal so...
Das ist bei einem Mikrocontroller in Software ziemlich simpel. Man schaltet beide Signale auf flankengetriggerte INT-Eingänge.
Kommt nun an A eine steigende Flanke wird der Pegel an B eingelesen. Ist B auf Low, wird der Zähler incrementiert, ist B auf High wird decrementiert. Anschließend wird die Flanke umgeschaltet, d.h. der nächste INT an A wird über die fallende Flanke ausgelöst (geht ja nicht anders weil A jetzt auf High ist). Ist bei der fallenden Flanke auf A der Pegel auf B = High, wird wieder incrementiert, ansonsten decrementiert. Dasselbe macht man mit den INTs, die durch das Signal an B getriggert werden.
Hier mal Pseudopascalcode:
Procedure INTA; // wird bei Flanke an A aufgerufen begin if B = High then inc(z) else dec(z); FlankenbitA = not(FlankenbitA); // reagiere beim nächsten mal auf andere Flanke end;
Procedure INTB; // wird bei Flanke an B aufgerufen begin if A = Hight then inc(z) else dec(z); FlankenbitB = not(FlankenbitB); end;
Die Anfangszustände der Flankenbits sind egal. Man kann sie natürlich initialisieren, aber nach den ersten Signalen an A und B "weiss" der Prozessor dann, wo es lang geht.
Wenn man auf beide Flanken triggern kann geht es auch so:
Procedure INTA; // wird bei Flanke an A aufgerufen begin if B = A then dec(z) else inc(z); end;
Procedure INTB; // wird bei Flanke an B aufgerufen begin if B = A then inc(z) else dec(z); end;
Achtung: die mechanischen Encoder prellen ziemlich heftig, also ist vor der Logik eine saubere Entprellung nötig!
Der Microcontroller macht das nebenher. Die billigste Lösung für das Problem ist vermutlich ein ATTINY13 o.ä..
formatting link
Nach meiner Erfahrung ist die sinnvollste Variante für "handbediente" Encoder, wo man mit Pollfrequenzen im einstelligen kHz-Bereich auskommt, den Zustand der Eingänge periodisch zu pollen (z.B. per Timerinterrupt) und damit eine Statemachine zu füttern:
Kommt darauf an, wie schnell die Störimpulse sind. Wenn der MC schnell genug ist, jeden Signalwechsel mitzubekommen, rechnet er das einfach mit raus, d.h. wenn das Signal kurz nach einem Wechsel von Low auf High kurz wieder auf Low geht, zählt der Zähler wieder rückwärts und beim folgenden Wechsel auf High wieder vorwärts. Ein einfaches RC-Glied sollte also ausreichen.
Das bezog sich auf den Vorschlag, das mit diskreter Logik zu machen.
Ja, für den uC gilt das, die Variante mit ausreichend schnellem Polling macht das so. Der Versuch, die ungefilterten Encodersignale per flankengesteuertem Interrupt auswerten zu wollen, kann leicht schiefgehen.
Ja, der Encoder muß halt langsam genug prellen, so daß jeder Interrupt komplett bearbeitet werden kann, bevor die nächste Flanke kommt. Außerdem produziert das ordentlich Interruptlast und Latenz im System, da muß man sehen, ob das stört oder nicht. Zyklisches Polling vermeidet das.
Man könnte auch die Freigabe der INTs verzögern, d.h. wenn eine Flanke aufgetreten ist wird der INT gesperrt und nach einer fest eingestellten Zeit über einen Timer wieder eingeschaltet.
Frage: wie schnell darf ein mechanischer Encoder überhaupt drehen, bevor die Kontakte abheben? Die sind doch nur für manuelle Bedienung geeignet, wo selbst eine falsche Zählung von dem korrigiert wird, der dran dreht. Eine Maus wird ja auch so lange verschoben, bis der Zeiger an der richtigen Stelle steht - da dürfen Impulse auch mal verschütt gehen, dafür würde auch Polling reichen. Für höhere Drehzahlen braucht man verschleißfreie (optische/magnetische) Encoder, die nicht-prellen können.
Du koenntest sowas mit 3-4Gattern machen. Hab ich jedenfalls vor
20Jahren mal irgendwo gesehen.
Es gab auch mal ICs die haben das gemacht und hatten gleich den Zaehler drin. Da konnte man direct den Positionsstand auslesen. Ist aber lange obsolet.
Es ist sehr einfach das einfach nur im TimerIRQ einzulesen.
Es gibt auch Mikrocontroller die haben das in Hardware integriert, macht aber nur Sinn wenn man wirklich schnell arbeiten muss.
Da gibt es andere MEinungen zu. .-)
Fuer diese eine exotische Anwendung gab es obige Gatterloesung. ICh meine das war in einer Elektor. Musst du dir wohl mal selber die Zeiten aufmalen und ueber die schlatung nachdenken. Problem ist nur das du dann immer noch Fehltriggerungen hast wenn der Encoder mal prellt. Das wuerde dir eine Softwareloesung gleich mit entfernen.
Klar gibt es da Grenzen, und wenn das selten genug passiert, ist das OK. Aber: man merkt das (bei Encodern mit mechanischer Rastung) schon recht deutlich, wenn Pulse nicht gezählt werden, auch bei schnellerem Drehen.
Ja, ich habe 2000..2001 eine Tastenentprellung am Arbeitsplatz entwickelt (uC; ohne Auftrag). Ich habe da im 1ms-Interrupt if (++keys >= 10) Keys(0), keys=0; programmiert. Also werden alle 10ms die Tastenzustände geprüft. Ein Zustand muß 10ms später immer noch gleich sein, damit er in Wirkung kommt.
Diese Entprellung hat sich bis 11.2014, meinem Ausscheiden, makellos bewährt.
Am 23.09.2023 um 11:57 schrieb Michael Schwingen: > On 2023-09-22, Hans-Peter Diettrich snipped-for-privacy@aol.com wrote: >> Frage: wie schnell darf ein mechanischer Encoder überhaupt drehen, bevor >> die Kontakte abheben? Die sind doch nur für manuelle Bedienung geeignet, >> wo selbst eine falsche Zählung von dem korrigiert wird, der dran dreht. >
Wenn man es richtig macht, ruckelt da nichts.
Auf jede fallende Flanke muss eine steigende Flanke folgen. Wenn es jetzt wie auf dem Bild in dem von dir verlinkten Artikel aussieht, könnte es theoretisch passieren, dass Flanken nicht erfasst werden. Das ist richtig, und sollte berücksichtigt werden, ist aber trivial.
formatting link
formatting link
Wenn es also eine fallende Flanke gibt, die einen INT auslöst und noch während dieser INT verarbeitet wird eine steigende Flanke kommt die dann keinen INT auslöst weil der Prozessor noch nicht bereit ist und danach eine weitere fallende Flanke, würde der Zähler einmal zuviel zählen. Wenn die Zahl der "verschluckten" Flanken geradzahlig ist, passiert das aber nicht.
Es kommt also drauf an, ob es vor der Flanke eine entgegengesetzte Flanke gab.
In dem folgenden Beispielcode reagiert der INT auf jede Flanke, also egal ob fallend oder steigend. Wenn eine Flanke verschluckt wurde, hat man also zwei gleichartige Flanken nacheinander. Das würde zu einem Zählfehler führen. Das passiert auch bei jeder ungeradzahligen Anzahl von verschluckten Flanken.
Wenn man das entsprechend berücksichtigt, gibt es keine Zählfehler. "Falsche" INT-Aufrufe belasten natürlich den Prozessor. Ob das ein Problem ist hängt von den Rahmenbedingungen ab.
Das Signal kann man vor der Auswertung natürlich noch verbessern, z.B. mit einem RC Tiefpass und Schmitt-Trigger.
Hier mal ein Code-Beispiel wo verschluckte Flanken berücksichtig werden:
Man kann das natürlich auch per Timer machen. Da "vernichten" sich die falschen Flanken dann automatisch.
int counter; // Zähler bool SigA; // alter Zustand von Eingang A bool SigB; // alter Zustand von Eingang B
void Interrupt_A() // Flankengetriggerter INT, reagiert auf // steigende und fallende Flanken an Signal A { InA = Encodersignal_A(); // Signal in InA speichern InB = Encodersignal_B(); if (InA != SigA) { // nur wenn es einen Signalwechsel gab wird das Bit verarbeitet if (InA == InB) { counter++; } else counter--; SigA = InA; // am Ende den Zustand des Bits speichern } }
void Interupt_B() // Flankengetriggerter INT, reagiert auf // steigende und fallende Flanken an Signal B { InB = Encodersignal_B(); InA = Encodersignal_A(); if (InB != SigB) // InB ist das Eingangsbit von Kanal B { // nur wenn es einen Signalwechsel gab wird das Bit verarbeitet if (InA == InB) { counter--; } else counter++; SigB = InB; // am Ende den Zustand des Bits speichern } }
IRPT-Eingänge waren bei uns nicht belegt. Die Tasten-Bits lagen in einem Port-Register. Alle Tasten gleichzeitig bitweise zu verknüpfen, war also einfach.
Ich hatte die Tasten-Entprellung auch mit einem 4-stufigen Tasten-Autorepeat verknüpft, wobei die vierte Stufe ungefähr 60 Ticks pro Sekunde lieferte. Bei uns mußten Zahlen bis 999 durch Tastentippen (up/down) eingegeben werden. Deshalb habe ich diesen Autorepeat entwickelt.
olaf schrieb am Samstag, 23. September 2023 um 07:00:04 UTC+2:
Der legendäre THCT2000... ich hab damit mal ne Zählerkarte mit 3 Kanälen entwickelt, nicht nur für Inkrementalgeber, sondern auch für Frequenz- und Zeitmessung (konnte das Teil auch, einer der beiden Encoder-Eingänge wurde dann als Gate benutzt). Ist aber schon über 30 Jahre her, das Teil scheints tatsächlich nicht mehr zu geben.
ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here.
All logos and trade names are the property of their respective owners.