Raspberry-Pi-Projekt: Drehimpulsgeber

Prof. Jürgen Plate

Raspberry Pi: Drehimpulsgeber

Allgemeines

Drehgeber sind als Rotationssensoren oder Selektoren zur Menüsteuerung nützlich. Sie sehen Potentiometern ähnlich, sind jedoch nicht wie Potentiometer regelbare Widerstände, sondern reine Schaltelemente. Diese Art von Drehimpulsgeber wird auch als "Quadraturcodierer" bezeichnet und verhält sich wie ein Paar von Schaltern, die phasenverschoben betätigt werden. Es gibt auch keine Begrenzung des Drehwinkels, sondern die Achse läßt sich beliebig immer weiter drehen. Drehgeber sind in 20 bis 30 "Segmente" unterteilt. Jedes Segment liefert ein Rast-Gefühl und jede Bewegung im Uhrzeigersinn oder dagegen bewirkt, dass sich die beiden Schalter öffnen und schließen. Die Reihenfolge, in der sie sich öffnen und schließen hängt von der Richtung ab, in der die Achse des Drehgebers bewegt wird. Es gibt keine Möglichkeit, eine aktuelle "Position" zu ermitteln, stattdessen wird gezählt, wie viele "Klicks" nach links oder rechts gedreht wurden.

Anschluß und Abfrage eines Drehimpulsgebers

Einfache Drehgeber haben drei Anschlusspins: einen gemeinsamen Anschluss und die Anschlüsse der Schalter A und B. Je nach Modell ist die Anschlußbelegung unterschiedlich, manche verwenden die mittlere Zuleitung als gemeinsamen Anschluss bei anderen ist dieser auf einer Seite. Überprüfen Sie daher die Pinbelegung im Datenblatt für den Drehgeber, den Sie verwenden. Viele Drehcodierer enthalten noch einen Druckschalter, der auf ein Paar separate Kontakte herausgeführt ist (siehe Datenblatt - Link am Ende der Seite).

Die folgende Abbildung zeigt die Folge der Impulse von den beiden Kontakten A und B. Man sieht, dass sich das Muster nach vier Schritten wiederholt (daher der Name "Quadratur-Encoder"). Je nach Modell rasten manche Encoder mechanisch nur in Phase 1, andere bei Phase 1 und Phase 3 und zeigen so ein unterschiedliches haptisches Feedback.

Ja nach Drehrichtung der Achse ergeben sich dann für die Anschlüsse A und B folgende Wertekombinationen:

Das folgende Python-Programm implementiert einen Algorithmus zur Bestimmung der Drehrichtung in der Funktion get_encoder(). Die Funktion gibt drei Werte zurück:

Das Programm verwendet zwei globale Variablen, old_a und old_b, in denen die vorherigen Zustände der Schalter A und B gespeichert werden. Durch den Vergleich mit den neu gelesenen Werten mit etwas Logik bestimmt werden, in welche Richtung sich der Encoder dreht. Nach jeder Abfrage wird 20 ms gewartet. Dies dient der Entprellung der Schalter und verhindert, dass die nächste neue Probe nicht nicht zu schnell nach der vorherigen Probe erfolgt; andernfalls können die Übergänge falsche Werte anzeigen. Je nach Rastverhalten kann es auch sein, dass immer zwei Schritte gezählt werden (mechanische Rastung nur nach Phase 1). In diesem Fall würde man das übergeornete Programm nur auf jeden zweiten oder sogar nur jeden vierten Schritt reagieren lassen.

Das Testprogramm sollte zuverlässig funktionieren, egal wie schnell Sie den Knopf des Drehgebers drehen.

#!/usr/bin/env python

import RPi.GPIO as GPIO
import time

# GPIO-Bezeichnung BCM stezen
GPIO.setmode(GPIO.BCM)

# GPIO-Pins Encoder (gemeinsamer Encoder-Pin auf GND)
in_a = 17
in_b = 27

# Merker fuer Encoder-Zustand (global)
old_a = 1
old_b = 1

# Pullup-Widerstand einschalten
GPIO.setup(in_a, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(in_b, GPIO.IN, pull_up_down=GPIO.PUD_UP)

def get_encoder():
  # liest den Encoder aus. Falls die Werte der Eingangspins
  # alten Wert abweichen, Richtung detektieren.
  # Rueckgabewert: -1, 0, +1
  global old_a, old_b
  result = 0

  # GPIO-Pins einlesen
  new_a = GPIO.input(in_a)
  new_b = GPIO.input(in_b)

  # Falls sich etwas geaendert hat, Richtung feststellen
  if (new_a != old_a or new_b != old_b):
    if (old_a == 0 and new_a == 1):
      result = (old_b * 2 - 1)
    elif (old_b == 0 and new_b == 1):
      result = -(old_a * 2 - 1)
  old_a = new_a
  old_b = new_b
  # entprellen
  time.sleep(0.02)
  return result


# Testprogramm
x = 0
while True:
  change = get_encoder()
  if change != 0:
    x = x + change
    print(x)

Links


Copyright © Hochschule München, FK 04, Prof. Jürgen Plate und die Autoren
Letzte Aktualisierung: