Inhaltsverzeichnis:

So interpretieren Sie die Drehrichtung eines digitalen Drehschalters mit einem PIC - Gunook
So interpretieren Sie die Drehrichtung eines digitalen Drehschalters mit einem PIC - Gunook

Video: So interpretieren Sie die Drehrichtung eines digitalen Drehschalters mit einem PIC - Gunook

Video: So interpretieren Sie die Drehrichtung eines digitalen Drehschalters mit einem PIC - Gunook
Video: Einführung in die Bedienung und Interpretation von Digital Constellation FamilyClearing. 2024, Juli
Anonim
So interpretieren Sie die Drehrichtung eines digitalen Drehschalters mit einem PIC
So interpretieren Sie die Drehrichtung eines digitalen Drehschalters mit einem PIC

Das Ziel für dieses Instructable ist es, zu veranschaulichen, wie ein digitaler (quadraturcodierter) Drehschalter mit einem Mikrocontroller verbunden wird. Keine Sorge, ich erkläre Ihnen, was Quadraturkodierung für uns bedeutet. Diese Schnittstelle und die zugehörige Software ermöglichen es dem Mikrocontroller, die Drehrichtung für jede Bewegung von einer Raste zur anderen zu erkennen. Ich habe diesen Schaltertyp kürzlich in einem Mikrocontroller-Projekt verwendet, bei dem ein Drucksollwert mit einem Drehknopf mit 16. eingegeben werden musste Rasten statt Auf-/Ab-Tasten. Die Idee war, dem Benutzer zu ermöglichen, den gewünschten Druck "einzuwählen". Infolgedessen mussten wir eine Softwareroutine entwickeln, um die Positionsinformationen vom Schalter zu erhalten und die Drehrichtung abzuleiten, um den Drucksollwert für das Hauptsystem zu erhöhen oder zu verringern. In diesem Instructable werde ich die physikalische Schnittstelle behandeln zum Mikrocontroller, die Funktionstheorie für den Drehschalter, die Funktionstheorie für die Software sowie die Ableitungsroutine. Schließlich zeige ich Ihnen meine Anwendung der Abzugsroutine. Im weiteren Verlauf werde ich versuchen, die Dinge etwas allgemeiner zu halten, damit die Idee auf so vielen Plattformen wie möglich angewendet werden kann, aber ich werde auch teilen, was ich getan habe, damit Sie eine bestimmte Anwendung sehen können.

Schritt 1: Teile

Teile
Teile

Um dies zu implementieren, benötigen Sie: Einen Drehschalter (Quadraturkodiert) Hochziehen von Widerständen Geeignete Mikrocontroller-Plattform Für mein Projekt habe ich einen optischen Encoder von Grayhill 61C22-01-04-02 verwendet. Das Datenblatt des Drehschalters fordert 8,2 kOhm Pullup-Widerstände an den beiden vom Schalter kommenden Datenleitungen. Sie sollten das Datenblatt des Encoders überprüfen, den Sie verwenden möchten. Der von I verwendete Drehschalter kann auch mit axialem Druckknopfschalter bestellt werden. Es ist eine nützliche Funktion zum Festschreiben von Auswahlen, die eingewählt wurden usw., aber ich werde hier nicht auf die Benutzeroberfläche eingehen. Ich habe eine "geeignete Mikrocontroller-Plattform" aufgelistet, weil (glaube ich) diese auf mehr als einer Plattform implementiert werden kann. Ich habe viele Leute gesehen, die andere Mikrocontroller für Instructables verwenden, also möchte ich auch den allgemeinen Ansatz zeigen. Ich habe den gesamten Code in PIC Basic Pro für die Verwendung mit einem Microchip PIC16F877A geschrieben. Wirklich, das Wichtigste, was Sie auf dem Mikrocontroller benötigen, ist die Fähigkeit, zu unterbrechen, wenn an einem der beiden Pins eine Logikänderung auftritt. Auf dem PIC16F877A wird dies als PORTB-Change-Interrupt bezeichnet. Auf anderen Controllern kann es andere Namen dafür geben. Diese Interrupt-Funktion des Mikrocontrollers ist ein Teil dessen, was diese Implementierung so elegant macht.

Schritt 2: Hardware-Schnittstelle

Hardware-Schnittstelle
Hardware-Schnittstelle

Eine "einfache" Lösung wäre ein "Single Pole-16 Throw" Schalter mit 16 Verbindungen zum Mikrocontroller. Jeder Schaltausgang wäre dann mit einem Pin am Mikrocontroller verbunden, damit jede Drehknopfposition vom Mikrocontroller überprüft werden kann. Dies ist eine übermäßige Verwendung von I/O-Pins. Noch schlimmer wird es, wenn wir am Schalter mehr als 16 Positionen (Rastungen) zur Verfügung haben wollen. Jede zusätzliche Position des Schalters würde einen zusätzlichen Eingang für den Mikrocontroller erfordern. Dies wird schnell zu einer sehr ineffizienten Verwendung der Eingänge eines Mikrocontrollers. Geben Sie die Schönheit des Drehschalters ein. Der Drehschalter hat nur zwei Ausgänge zum Mikrocontroller, die im Datenblatt als A und B aufgeführt sind. Es gibt nur vier mögliche Logikpegel, die diese Leitungen annehmen können: AB = 00, 01, 10 und 11. Dies reduziert die Anzahl der Eingangsleitungen, die Sie zum Verbinden des Schalters mit dem Mikrocontroller verwenden müssen, erheblich. Daher haben wir die Anzahl der Eingabezeilen auf nur zwei reduziert. Was jetzt? Es scheint, als ob wir wirklich 16 verschiedene Zustände brauchen, aber dieser neue Schalter hat nur vier. Haben wir uns in den Fuß geschossen? Nö. Weiter lesen. Wir werden ein wenig die Theorie hinter der Drehschalterbedienung behandeln, um sie zu erklären.

Schritt 3: Hardware-Betriebstheorie

Hardware-Betriebstheorie
Hardware-Betriebstheorie
Hardware-Betriebstheorie
Hardware-Betriebstheorie
Hardware-Betriebstheorie
Hardware-Betriebstheorie

Die Drehrichtungserkennung ist mit dem oben genannten "Single Pole-16 Throw" -Schalter möglich, verbraucht jedoch viele Eingänge des Mikrocontrollers. Die Verwendung des Drehschalters reduziert die Anzahl der Eingänge zum Mikrocontroller, aber jetzt müssen wir die vom Schalter kommenden Signale interpretieren und diese in eine Drehrichtung übersetzen. Ich habe bereits erwähnt, dass der Schalter quadraturkodiert war. Dies ist auch eine der Schlüsseleleganzen dieser Lösung. Dies bedeutet, dass der Schalter einen 2-Bit-Code gibt, der der Position des Schalters entspricht. Sie denken vielleicht: "Wenn der Mikrocontroller einen 2-Bit-Eingang hat, wie stellen wir dann alle 16 Positionen dar?" Das ist eine gute Frage. Wir vertreten nicht alle. Wir müssen nur die relativen Positionen des Knopfes kennen, um die Drehrichtung zu bestimmen. Die absolute Position des Drehknopfes ist unerheblich. Bei Drehung im Uhrzeigersinn wiederholt sich der Code, den der Schalter gibt, alle vier Rasten und ist grau codiert. Gray-codiert bedeutet, dass bei jeder Positionsänderung nur ein Bitwechsel stattfindet. Anstatt dass der AB-Eingang für die Drehung im Uhrzeigersinn in binärer Form wie folgt hochzählt: 00, 01, 10, 11, ändert er sich wie folgt: 00, 10, 11, 01. Beachten Sie, dass es für das letztere Muster nur einen Eingang gibt, der zwischen wechselt setzt. Die Werte für den AB-Eingang des Mikrocontrollers gegen den Uhrzeigersinn sehen wie folgt aus: 00, 01, 11, 10. Dies ist einfach die Umkehrung des Musters im Uhrzeigersinn, wobei AB = 00 zuerst aufgeführt ist. Sehen Sie sich die Diagramme an, um eine visuellere Erklärung zu erhalten.

Schritt 4: Software-Betriebstheorie

Software-Betriebstheorie
Software-Betriebstheorie

Die Routine, die die Drehrichtung herleitet, wird unterbrochen gesteuert. Der von Ihnen ausgewählte Mikrocontroller muss in der Lage sein, jedes Mal zu unterbrechen, wenn sich an einem von (mindestens) zwei Pins ändert, wenn der Interrupt aktiviert ist. Dies wird auf dem PIC16F877A als PORTB-Change-Interrupt bezeichnet. Jedes Mal, wenn der Schalter gedreht wird, wird der Mikrocontroller unterbrochen und die Programmausführung wird an die Interrupt Service Routine (ISR) gesendet. Der ISR erkennt schnell, in welche Richtung der Schalter gedreht wurde, setzt ein entsprechendes Flag und kehrt schnell zum Hauptprogramm zurück. Dies muss schnell geschehen, falls der Benutzer den Schalter sehr schnell dreht. Wir wissen, dass sich das grau codierte AB-Muster alle vier Positionen wiederholt. Wenn wir also die Routinearbeiten für Übergänge zwischen diesen vier Positionen ausführen, wird es für alle anderen funktionieren. Beachten Sie, dass es in einem Vier-Positionen-Zyklus vier Kanten gibt. Eine steigende Flanke und eine fallende Flanke für den A-Eingang sowie den B-Eingang. Der Mikroprozessor wird bei jeder Flanke unterbrochen, was bedeutet, dass der Mikrocontroller jedes Mal unterbrochen wird, wenn der Knopf gedreht wird. Als Ergebnis muss der ISR herausfinden, in welche Richtung der Knopf gedreht wurde. Um herauszufinden, wie das geht, wenden wir uns der Wellenform für die Drehung im Uhrzeigersinn zu. Beachten Sie, dass jedes Mal, wenn A eine Flanke hat, sein neuer Wert sich immer von dem von B unterscheidet. Wenn der Knopf von Position 1 auf 2 wechselt, geht A von logisch-0 auf logisch-1 über. B ist für diesen Übergang immer noch 0 und stimmt nicht mit dem neuen Wert von A überein. Wenn der Knopf von Position 3 auf 4 geht, hat A eine fallende Flanke, während B auf logisch 1 bleibt. Beachten Sie erneut, dass B und der neue Wert von A unterschiedlich sind. Im Moment können wir sehen, dass jedes Mal, wenn A den Interrupt während der Drehung im Uhrzeigersinn verursacht, sein neuer Wert sich von dem von B unterscheidet. Schauen wir uns B an, um zu sehen, was passiert. B hat eine steigende Flanke, wenn der Schalter von Position 2 auf 3 wechselt. Hier ist der neue Wert von B der gleiche wie A. Betrachtet man die letzte verbleibende Flanke für die Drehung im Uhrzeigersinn, hat B eine fallende Flanke, die sich von Position 4 auf 5 bewegt. (Position 5 ist gleich Position 1.) Der neue Wert von B ist auch hier gleich A! Wir können jetzt einige Abzüge machen! Wenn A den Interrupt verursacht und der neue Wert von A sich von dem von B unterscheidet, war die Drehung im Uhrzeigersinn. Außerdem, wenn B den Interrupt verursacht und der neue Wert von B derselbe wie A ist, dann war die Drehung im Uhrzeigersinn. Betrachten wir kurz den Fall der Drehung gegen den Uhrzeigersinn. Genau wie die Drehung im Uhrzeigersinn verursacht eine Drehung gegen den Uhrzeigersinn vier Unterbrechungen in einem Zyklus: zwei für Eingang A und zwei für Eingang B. Eingang A hat eine steigende Flanke, wenn sich der Knopf von Position 4 auf 3 bewegt, und eine fallende Flanke, wenn Sie von Position 2 auf 1 wechseln Wenn sich der Knopf von Position 4 auf 3 bewegt, ist der neue Wert von A gleich dem Wert von B. Beachten Sie, dass, wenn A von Position 2 auf 1 bewegt wird, sein neuer Wert auch gleich dem von B ist. Jetzt können wir sehen, dass, wenn A den Interrupt verursacht und sein neuer Wert mit dem von B übereinstimmt, die Drehung gegen den Uhrzeigersinn erfolgte. Wir werden uns schnell Eingabe B ansehen, um alles zu überprüfen. B führt zu einer Unterbrechung, wenn sich der Knopf von Position 5 (entspricht 1) auf 4 bewegt und wenn sich der Knopf von Position 3 auf 2 bewegt. In beiden Fällen stimmt der neue Wert von B nicht mit dem bestehenden Wert überein von A, was das Gegenteil der Fälle ist, in denen B die Unterbrechung für die Drehung im Uhrzeigersinn verursacht. Das sind gute Neuigkeiten. Alles funktioniert wie es sollte. Um es zusammenzufassen, wenn A den Interrupt verursacht und sein neuer Wert nicht mit dem Wert von B übereinstimmt oder wenn B den Interrupt verursacht und der neue Wert von B mit dem Wert von A übereinstimmt, wissen wir, dass es eine Drehung im Uhrzeigersinn gab. Wir können die anderen Fälle auf Drehung gegen den Uhrzeigersinn in der Software überprüfen oder annehmen, dass es keine Drehung im Uhrzeigersinn war, sondern gegen den Uhrzeigersinn. Meine Routine machte einfach die Annahme.

Schritt 5: Software

Software
Software
Software
Software

Ich habe die eingebauten Interrupts in PIC Basic Pro nicht verwendet. Ich habe ein paar Dateien verwendet, die ich von Darrel Taylor in meinen Code eingefügt habe, um die Routine zu steuern. Hier gehört ein großes Lob an Darrel! Die Dateien sind kostenlos. Besuchen Sie einfach seine Website für weitere Informationen, andere Anwendungen und um die Dateien herunterzuladen. Sie können diesen Teil überspringen, wenn Sie keinen PIC mit Darrel Taylor-Interrupts verwenden. Richten Sie einfach die Interrupts nach Bedarf auf der von Ihnen verwendeten Plattform ein. Um die Darrel Taylor (DT)-Interrupts einzurichten, müssen Sie zwei Dinge tun: 1.) Fügen Sie die Dateien DT_INTS-14.bas und ReEnterPBP.bas in Ihr. ein code.2.) Kopieren Sie dies und fügen Sie es in Ihr code. ASMINT_LIST-Makro ein;IntSource, Label, Type, ResetFlag? INT_Handler RBC_INT, _ISR, PBP, ja endm INT_CREATEENDASMITabs und Leerzeichen wie die Grafik am Ende des Instructable einfügen, damit Sie die Dinge in Ihrem Code ein wenig einfacher sehen können. Sie müssen es leicht an Ihre Bedürfnisse anpassen. Ersetzen Sie unter Label ISR durch den Namen der Unterroutine, die Ihr ISR ist. Vergiss den Unterstrich nicht! Sie brauchen es!Um die Interrupts zum Laufen zu bringen, müssen Sie noch zwei weitere Dinge tun: 1.) Schreiben Sie die ISR. Sie werden dies so schreiben, wie Sie eine PBP-Unterroutine schreiben würden, außer dass Sie am Ende der Unterroutine @ INT_RETURN anstelle von RETURN einfügen müssen. Dadurch wird der Interrupt bestätigt und die Programmausführung an die Stelle zurückgesetzt, an der sie in der Hauptschleife aufgehört hat. Innerhalb des ISR müssen Sie das Interrupt-Flag löschen, damit Ihr Programm nicht in einen rekursiven Interrupt gerät. Es muss lediglich PORTB gelesen werden, um das Interrupt-Flag auf dem PIC16F877A zu löschen. Jeder unterschiedliche Mikrocontroller hat eine andere Möglichkeit, Interrupt-Flags zu löschen. Überprüfen Sie das Datenblatt für Ihren Mikrocontroller.2.) Wenn Sie den Punkt in Ihrem Code erreichen, an dem Sie den Interrupt aktivieren möchten, verwenden Sie diese Codezeile:@ INT_ENABLE RBC_INTWenn Sie den Interrupt deaktivieren möchten, verwenden Sie einfach:@ INT_DISABLE RBC_INTEs gibt viel von Sachen verpackt in das, was ich gerade behandelt habe, also fasse ich schnell zusammen. Bis jetzt sollte Ihr Programm ungefähr so aussehen:; Alle erforderlichen Einstellungen oder CodeINCLUDE "DT_INTS-14.bas"INCLUDE "ReEnterPBP.bas"ASMINT_LIST Makro;IntSource, Label, Type, ResetFlag? INT_Handler RBC_INT, _myISR, PBP, ja endm INT_CREATEENDASM; Jede andere erforderliche Einrichtung oder Code@ INT_ENABLE RBC_INT; Code, der wissen muss, in welche Richtung sich der Knopf dreht @ INT_DISABLE RBC_INT; Anderer CodeEND; Ende des ProgrammsmyISR:;ISR-Code hier@ INT_RETURN(Interrupt Handler Set Up Table)Ich denke, hier kann jeder, der keine PIC- oder DT-Interrupts verwendet, wieder mitmachen. Jetzt müssen wir den ISR tatsächlich schreiben, damit der Mikrocontroller weiß, in welche Richtung sich der Knopf dreht. Erinnern Sie sich aus dem Abschnitt zur Softwaretheorie daran, dass wir die Drehrichtung ableiten können, wenn wir den Eingang kennen, der den Interrupt verursacht hat, seinen neuen Wert und den Wert des anderen Eingangs. Hier ist der Pseudocode:Lesen Sie PORTB in eine Scratch-Variable, um das Interrupt-Flag zu löschenÜberprüfen Sie, ob A den Interrupt verursacht hat. Wenn wahr, vergleiche A und B. Prüfe, ob unterschiedlich, wenn unterschiedlich, Es war eine Drehung im Uhrzeigersinn. Falls wahr, vergleiche A und B Prüfen, ob unterschiedlich, falls gleich, Es war eine Drehung im Uhrzeigersinn Sonst, Es war gegen den Uhrzeigersinn EndifReturn from InterruptWoher wissen wir, ob eine Änderung an A oder B den Interrupt verursacht hat? Den neuen Wert der geänderten Eingabe und der anderen (unveränderten) Eingabe zu entdecken ist einfach, da wir sie in der ISR lesen können. Wir müssen wissen, wie der Zustand jedes einzelnen war, bevor die Ausführung an den ISR gesendet wird. Dies geschieht in der Hauptroutine. Die Hauptroutine sitzt und wartet darauf, dass eine Bytevariable, die wir CWflag genannt haben, vom ISR auf 1 gesetzt oder auf 0 gelöscht wird. Nach jeder quittierten Drehknopfänderung oder wenn keine Drehknopfaktivität vorliegt, wird die Variable auf 5 gesetzt, um einen Ruhezustand anzuzeigen. Wenn das Flag gesetzt oder gelöscht wird, inkrementiert oder dekrementiert die Hauptroutine sofort den Sollwertdruck entsprechend der Drehung und setzt dann die CW-Flag-Variable zurück auf 5, da der Knopf jetzt wieder im Leerlauf ist. Da die Hauptroutine das CW-Flag überprüft, dokumentiert sie auch den Zustand der A- und B-Drehschalterwerte. Das ist ganz einfach und sieht so aus:oldA = AoldB = BHier gibt es wirklich nichts Super Schickes. Fügen Sie einfach diese beiden Zeilen am Anfang der Schleife ein, die das CW-Flag auf Rotation überprüft. Wir aktualisieren nur die logischen Werte der Eingaben vom Drehknopf in der Inkrement-/Dekrement-Schleife in der Hauptroutine, damit wir sehen können, welche Eingabe den Interrupt verursacht hat, wenn die ISR ausgeführt wird. Hier ist der ISR-Code:ABchange: scratch = PORTB ' PORTB lesen, um das Interrupt-Flag zu löschen ' Wenn A den Interrupt verursacht, überprüfen Sie B auf Drehrichtung IF oldA != A THEN ' Wenn A und B unterschiedlich sind, war es eine Drehung im Uhrzeigersinn IF A != B THEN GOTO CW ' Sonst war es Drehung gegen den Uhrzeigersinn ELSE GOTO CCW ENDIF ENDIF ' Wenn B den Interrupt verursacht, überprüfen Sie A auf Drehrichtung IF oldB != B THEN ' Wenn A und B gleich sind, ist es war Drehung im Uhrzeigersinn IF A == B THEN GOTO CW ' Sonst war es Drehung gegen den Uhrzeigersinn ELSE GOTO CCW ENDIF ENDIFCW: CWflag = 1@ INT_RETURNCCW: CWflag = 0@ INT_RETURNI Ich habe den ISR-Code in eine AB_ISR.bas-Datei eingefügt, weil die Registerkarten im Code werden nicht so angezeigt, wie sie sollten. Da der ISR jetzt die alten Werte für die Eingänge A und B hat, kann er feststellen, welcher Eingang den Interrupt verursacht hat, ihn mit dem anderen (unveränderten) Eingang vergleichen und die Richtung bestimmen der Drehung. Alles, was die Hauptroutine tun muss, ist, das CW-Flag zu überprüfen, um zu sehen, in welche Richtung sich der Knopf gedreht hat (wenn ja) und einen Zähler, einen Sollwert oder was auch immer Sie möchten oder brauchen, zu erhöhen oder zu verringern. Ich hoffe, das hilft und war es nicht zu verwirrend. Diese Art von Schnittstelle ist besonders nützlich, wenn Ihr System bereits Interrupts verwendet, da dies nur ein weiterer Interrupt ist, der hinzugefügt werden muss. Genießen!

Empfohlen: