Forum: Mikrocontroller und Digitale Elektronik Drehgeber am Pi


von raspi-user (Gast)


Lesenswert?

Hi,
Ich würde gerne 2 Drehgeber diesen Typs 
(http://www.reichelt.de/Drehimpulsgeber/STEC11B03/3/index.html?&ACTION=3&LA=2&ARTICLE=73913&GROUPID=3714&artnr=STEC11B03) 
an einem Pi 2 betreiben. Da ich aber nicht den Pi mit der Entprellung 
nerven möchte, würde ich das gerne vorher realisieren.

Ich finde diese Lösung ganz sympathisch: 
https://www.mikrocontroller.net/articles/Drehgeber#Dekoder_mit_diskreten_Logik-ICs. 
Weiß jemand, wie schnell ich sowas takten sollte, dass auf der einen 
Seite der Pi mithält und auf der anderen Seite nix verloren geht? Und wo 
kriege ich einen Takt her? NE555 ist bisschen übertrieben, oder? 
Oszillatoren finde ich aber nur mit >=1MHz und weiß nicht, ob das nicht 
schon zu schnell ist. Außerdem müsste ich die eingebauten Taster dann 
anders entprellen.

Die andere Möglichkeit, die mir so in den Sinn kommt, wäre, einen 
ATtiny84 zur Auswertung zu nutzen, das ist allerdings Neuland für mich. 
Kann man den Code von hier 
(https://www.mikrocontroller.net/articles/Drehgeber#Solide_L.C3.B6sung:_Beispielcode_in_C) 
so anpassen, dass ich quasi 6x Input habe (2x A, 2x B, 2x Taster) und 6x 
Output? Wäre es da auch möglich, den Output so zu schalten, dass bei 
einer Linksdrehung ein Pin flankt, bei einer Rechtsdrehung der andere? 
Dann könnte ich mir die Auswertung des Gray Signals im Pi komplett 
sparen. Wie gesagt, das mit dem ATtiny ist Neuland für mich und ich muss 
auch gestehen, dass ich den Code oben noch nicht vollständig 
nachvollziehen kann. Bin gerade dabei, im AVR Tutorial querzulesen.

Welche Lösung würdet ihr mir empfehlen?

Viele Grüße

von raspi-user (Gast)


Lesenswert?

raspi-user schrieb:
> Dann könnte ich mir die Auswertung des Gray Signals im Pi komplett
> sparen

edit: Dann könnte ich mir die Auswertung von 2 Pins für ein Signal 
sparen und hätte einen Pin für Links und einen für Rechts am Pi

von MaWin (Gast)


Lesenswert?

raspi-user schrieb:
> Da ich aber nicht den Pi mit der Entprellung nerven möchte, würde

Was hast du an den von dir ausgesuchten Verfahren zur Erfassung von 
Drehgebern nicht verstanden ?

Die haben kein Problem mit prellenden Kontakten oder vibrierenden 
Wellen, die kann auch der rPi direkt entsprechend dem Algorithmus per 
Timer Interrupt.

Hand-gedreht reichen schon mehr als 100Hz.

von raspi-user (Gast)


Lesenswert?

Ja, aber dann muss ich immer diese Schleife mitlaufen lassen und wenn 
die Drehgeber vielleicht alle paar Stunden mal ein Signal ausgeben finde 
ich, ist das viel verschwendete Rechenzeit. Außerdem geht das doch in 
die Hose, wenn die CPU mal von anderen Prozessen stark ausgelastet wird, 
oder?

von Jens G. (jensig)


Lesenswert?

Für sowas wurden Interrupts erfunden, damit man nicht permanet und 
sinnlos pollen muß ...

von raspi-user (Gast)


Lesenswert?

Richtig, aber einen prelleneden Eingang fragt man nicht mit Interrupts 
ab. Deswegen mein Frage zu Beginn.

von m.n. (Gast)


Lesenswert?

raspi-user schrieb:
> Die andere Möglichkeit, die mir so in den Sinn kommt, wäre, einen
> ATtiny84 zur Auswertung zu nutzen, das ist allerdings Neuland für mich.

Ein Tiny25 pro Drehgeber: 
Beitrag "mini Quadraturdekoder + 32 Bit Zähler + TWI, Attiny25"

von raspi-user (Gast)


Lesenswert?

Hmm, dann bräuchte ich das I2C Interface am, richtig?

von Andreas R. (andreasr)


Angehängte Dateien:

Lesenswert?

Wenn Python eine Option ist, hätte ich folgenden Code (s. Anhang)
Beispiel für Benutzung:
1
import time
2
import RPi.GPIO as GPIO
3
from encoder import Encoder
4
5
def DrehTest(val):
6
  print('Gedreht: %+d' % (val))
7
8
9
### Main routine ###
10
11
if __name__ == "__main__":
12
  GPIO.setwarnings(False)       # Disable this line on Rev 1 boards
13
  GPIO.setmode(GPIO.BCM)       # Use BCM GPIO numbers
14
15
  e = Encoder(18, 17)      # Encoder an GPIO 17 und 18
16
  e.SetValueHandler(DrehTest, 4)
17
18
  while True:
19
    time.sleep(1)
>

Gruß Andreas

: Bearbeitet durch User
von raspi-user (Gast)


Lesenswert?

Danke, werde ich auf jeden Fall mal ausprobieren.

Ich schätze, du hast den Code im Einsatz? Einfach direkt die Pins ohne 
debounce (abgesehen von den 10ms von RPi.GPIO) angeschlossen? Und das 
läuft zuverlässig?

Vermutlich wäre der scaler bei meinem Encoder dann 2, richtig? (15 
Impulse, 30 Rastungen)

von Andreas R. (andreasr)


Lesenswert?

> Und das läuft zuverlässig?

Mehr oder weniger. Ab und zu wird ein Schritt vergessen. Kannst noch was 
an den Debounce-Zeiten rumspielen. Hatte ich mal für mein Raspi-Radio im 
Einsatz.
Für meine neuere Version des Radios habe ich dann einen ATmega als I2C 
Slave eingebaut. Das hatte den Vorteil, dass er die ganze Bitschubserei 
machen kann (LCD, Drehencoder, Taster, PWM LCD-Beleuchtung). Das läuft 
schon besser; obwohl man dann wieder das Problem hat, dass der RASPI 
kein I2C Clock-Stretching kann :-(
Aber du kannst meine Python-Lösung gern ausprobieren, kostet ja nix :-)
Für den Encoder 
https://www.reichelt.de/Drehimpulsgeber/STEC12E08/3/index.html?&ACTION=3&LA=5000&GROUP=B29&GROUPID=3714&ARTICLE=73923&START=0&SORT=-rank&OFFSET=500 
hatte ich den Teiler 4 genommen.

von raspi-user (Gast)


Lesenswert?

Hmm, habe gerade nochmal über den scaler nachgedacht, verstehe es aber 
nicht so ganz, was der tun soll, bzw was du damit vorhattest. So, wie 
ich das sehe, nullt der einfach in jedem Durchgang val. Falls dem 
nämlich nicht so wäre, würde das Programm in der letzten Zeile den 
Syntaxfehler erkennen ;-)

Wie gesagt, ich werds mal ausprobieren die Tage. Aber nochmal zu meiner 
Frage von oben: Denkst du, es wäre machbar, einen ATtiny24/44/84 zu 
spendieren, der die Auswertung macht und dann bei "Links" kurz HIGH auf 
den einen Pin gibt und bei "Rechts" kurz HIGH auf einen anderen und 
diese beiden Pins dann an den Pi anschließen? Dann könnte ich nämlich im 
Pi einfach auf Flanken an diesen beiden Pins warten.

Oder denkst du, das wird eher schlecht mit dem Timing oder so?

von Peter2 (Gast)


Lesenswert?


von Michael B. (laberkopp)


Lesenswert?

raspi-user schrieb:
> Ja, aber dann muss ich immer diese Schleife mitlaufen lassen und
> wenn
> die Drehgeber vielleicht alle paar Stunden mal ein Signal ausgeben finde
> ich, ist das viel verschwendete Rechenzeit. Außerdem geht das doch in
> die Hose, wenn die CPU mal von anderen Prozessen stark ausgelastet wird,
> oder?

Alles eine Frage der Timer-Interrupt-Priorität.

Die muss so oder so höher sein als die Priorität dieser anderen 
Prozesse, denn sonst würde das System ja nicht auf den Drehgeber 
reagieren wenn diese Prozesse ihn (über)lasten. Egal ob die Drehgeber 
direkt ausgewertet werden oder per SPI oder anderer Schnittstelle ein 
extra Auswertechip angeschlossen wird, blöd wäre eine zu geringe 
Priorität also in jeden Fall.

Es ist auch vollkommen egal, ob der rPi 0.1% seiner Rechenzeit dauerhaft 
auf die Abfrage sich nicht-bewegender Drehgeber investiert, denn auch im 
Höchstauslastungsfall muss er diese 0.1% Rechenleistung übrig haben. Er 
hat sie also sowieso übrig, und übriges kann man nutzen, immer, 
jederzeit.

Jens G. schrieb:
> Für sowas wurden Interrupts erfunden, damit man nicht permanet und
> sinnlos pollen muß ...

Oh nö, noch ein total Ahnungsloser.

Andreas R. schrieb:
> Wenn Python eine Option ist

Das iat natürlich die schlechteste Lösung von allen, eine Skriptsprache 
die nicht am Timer-Interrupt hängt und deren Priorität nicht angepasst 
werden kann. Aber erstaunlich, wenn es damit immer noch funktioniert.

Andreas R. schrieb:
> Ab und zu wird ein Schritt vergessen

Ok, funktioniert nicht, wird hier aber trotzdem als Lösung angepriesen. 
Die üblichen Mistkonstruktionen also, hätte man schon daran sehen können 
daß jemand meint, Drehgebereingänge "debouncen" zu müssen.

: Bearbeitet durch User
von Andreas R. (andreasr)


Lesenswert?

> Ok, funktioniert nicht, wird hier aber trotzdem als Lösung angepriesen.
> Die üblichen Mistkonstruktionen also, hätte man schon daran sehen können
> daß jemand meint, Drehgebereingänge "debouncen" zu müssen.

Ja nimm unbedingt meine Lösung alles andere ist Mist. Und ich bin total 
sauer wenn du sie nicht nimmst. Ich bin nämlich der einzige der Ahnung 
hat.
@laberkopp: Denkst du so?

von Michael B. (laberkopp)


Lesenswert?

Andreas R. schrieb:
> Denkst du so?

Ich denke, daß ein Lösungsvorschlag, der "ab und zu wird ein Schritt 
vergessen" nicht als Lösungsvorschlag taugt.

Sollte so was auch China kommen, wir hier gleich laut geschrieen, das 
wäre Chinapfusch.

An dir sieht man aber: Deutsche Lösungen sind noch schlimmer, aber 
arrogant behaupten Leute wie du, die Lösung wäre schon gut.

Nein, sie ist Pfusch und bleibt Pfusch, auch wenn du sie erfunden hast.

von Harald W. (wilhelms)


Lesenswert?

Andreas R. schrieb:

> Ja nimm unbedingt meine Lösung alles andere ist Mist.

Nun, Drehgeber werden extra so gebaut, das man sie mit Auswertung
der Zustände eindeutig dekodieren kann. Lösungen, die auf Flanken
reagieren, sind eindeutig "Mist", da sie bei älteren Drehgebern
eben eindeutig nicht mehr zuverlässig funktionieren. Wenn man
sowieso per Rechner auswertet, sollte es auch keinen Unterschied
machen, ob man ein "richtiges" oder ein "falsches" Programm
verwendet. Das Wissen über die richtige Auswertung von Drehgebern
ist übrigens Jahrzehnte alt und keine "neue" Erfindung.

von Andreas R. (andreasr)


Lesenswert?

Leute nun lasst mal die Kirche im Dorf.  Der TE  kann doch selbst 
entscheiden ob er den PI mal kurz per Steckbrett mit dem Encoder testet 
oder nicht. Vielleicht reicht es für manche Anwendung wenn alle 30 
Schritte einer vergessen wird. Natürlich kann man auch eine hoch.-priore 
Anfrage-Task schreiben oder den Linux-Kernel anpassen oder ein 
Echtzeit-Linux installieren. Nach oben sind da sicher keine Grenzen.

von raspi-user (Gast)


Lesenswert?

Ich habe mich grad mal ein bisschen durch den Code von PeDa gearbeitet 
und es jetzt soweit nachvollzogen, indem ich einfach mal gerechnet hab 
^^ Scheint alles zu stimmen. Nur eins irritiert mich: Warum wird in 
encode_read2 und encode_read4 die Variable encode_delta nicht auf 0 
zurück gesetzt nach dem Lesen? Es macht zwar keinen Unterschied, weil 
der Rückgabewert eh geschoben wird, aber so fürs Verständnis... Gibts da 
n Grund für?

Außerdem: Warum wird immer cli() aufgerufen? Was, wenn die Schleife in 
der main() schneller ist, als der Timer? Dann wird der Timer Interrupt 
doch nie ausgeführt, oder?

von raspi-user (Gast)


Lesenswert?

Ich beziehe mich mit obiger Frage auf den Code von hier: 
https://www.mikrocontroller.net/articles/Drehgeber#Solide_L.C3.B6sung:_Beispielcode_in_C

von Nerv (Gast)


Lesenswert?

raspi-user schrieb:
> ^^ Scheint alles zu stimmen. Nur eins irritiert mich: Warum wird in
> encode_read2 und encode_read4 die Variable encode_delta nicht auf 0
> zurück gesetzt nach dem Lesen? Es macht zwar keinen Unterschied, weil
> der Rückgabewert eh geschoben wird, aber so fürs Verständnis... Gibts da
> n Grund für?

Ich weiß es auch nicht. Wenn ich es aber wissen wollen würde, würde ich 
das einfach ausprobieren. Warum tust du das nicht? Setz sie doch auf 
Null und schau was passiert.

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.