Encoder-Script (KY040) Verständnisfrage

Python auf Einplatinencomputer wie Raspberry Pi, Banana Pi / Python für Micro-Controller
Antworten
D-Platoon
User
Beiträge: 3
Registriert: Montag 30. September 2019, 00:43

Hallo zusammen,

ich befasse mich in letzter Zeit etwas intensiver mit meinem RasPi und versuche mir gerade Python beizubringen.
Hauptberuflich bin ich SPS-Programmierer, hab also einige Programmierkenntnisse, Python ist dann aber doch eine etwas andere Welt...
Für ein etwas größeres Projekt möchte ich drei Encoder an den RasPi anschließen.
Erste Tests hab ich mit folgendem Script aus dem Netz gemacht:

Code: Alles auswählen

"""
KY040 Python Class
Martin O'Hanlon
stuffaboutcode.com


Additional code added by Conrad Storz 2015 and 2016
"""

import RPi.GPIO as GPIO
from time import sleep


class KY040:

    CLOCKWISE = 0
    ANTICLOCKWISE = 1
    DEBOUNCE = 12

    def __init__(self, clockPin, dataPin, switchPin, rotaryCallback, switchCallback):
        #persist values
        self.clockPin = clockPin
        self.dataPin = dataPin
        self.switchPin = switchPin
        self.rotaryCallback = rotaryCallback
        self.switchCallback = switchCallback

        #setup pins
        GPIO.setup(clockPin, GPIO.IN, pull_up_down=GPIO.PUD_UP)
        GPIO.setup(dataPin, GPIO.IN, pull_up_down=GPIO.PUD_UP)
        GPIO.setup(switchPin, GPIO.IN, pull_up_down=GPIO.PUD_UP)

    def start(self):
        GPIO.add_event_detect(self.clockPin, GPIO.FALLING, callback=self._clockCallback, bouncetime=self.DEBOUNCE)
        GPIO.add_event_detect(self.switchPin, GPIO.FALLING, callback=self.switchCallback, bouncetime=self.DEBOUNCE)

    def stop(self):
        GPIO.remove_event_detect(self.clockPin)
        GPIO.remove_event_detect(self.switchPin)
    
    def _clockCallback(self, pin):
        if GPIO.input(self.clockPin) == 0:
            #print(str(pin))
            #print("Callback " + str(GPIO.input(self.dataPin)))
            self.rotaryCallback(GPIO.input(self.dataPin))
        """
            data = GPIO.input(self.dataPin)
            if data == 1:
                self.rotaryCallback(self.ANTICLOCKWISE)
            else:
                self.rotaryCallback(self.CLOCKWISE)
        
        self.rotaryCallback(GPIO.input(self.dataPin))
        """

    def _switchCallback(self, pin):
        """
        if GPIO.input(self.switchPin) == 0:
            self.switchCallback()
        """
        self.switchCallback()

#test
if __name__ == "__main__":

    print('Program start.')

    CLOCKPIN = 16
    DATAPIN = 15
    SWITCHPIN = 14

    def rotaryChange(direction):
        print("turned - " + str(direction))
    def switchPressed(pin):
        print("button connected to pin:{} pressed".format(pin))

    GPIO.setmode(GPIO.BCM)
    ky040 = KY040(CLOCKPIN, DATAPIN, SWITCHPIN, rotaryChange, switchPressed)

    print('Launch switch monitor class.')

    ky040.start()
    print('Start program loop...')
    try:
        while True:
            sleep(10)
            print('Ten seconds...')
    finally:
        print('Stopping GPIO monitoring...')
        ky040.stop()
        GPIO.cleanup()
        print('Program ended.')
Das hat soweit auch ganz gut funktioniert. Mein Ziel ist es nun, das Script in eine weitere Klasse, nennen wir sie "encoder.py" zu packen, der ich die GPIO-Pins und eine Schrittweite (also um wie viel es pro "Klick" hoch oder runter zählen soll) übergebe. Als Rückgabewert (bzw. noch besser als In-Out (so nennt mans bei der SPS)) spuckt sie mir den Zählwert aus.
Doch eins nach dem Anderen: Dazu möchte ich erstmal das obige Script verstehen.

Im start wird als callback einmal self._clockCallback und beim zweiten Event self.switchCallback übergeben, bzw. ich vermute mal aufgerufen. Also einmal mit und einmal ohne Unterstrich. Was hat das zu bedeuten? Zumal die Unterprogramme ja beide mit Unterstrich definiert sind.
Ebenso word bei den beiden Unterprogrammen jeweils eine Variable "pin" übergeben. Könnt ihr mir erklären, woher die kommt?

Das wäre mal die ersten Fragen.

Viele Grüße,
Thomas alias D-Platoon
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Das ist buggy. Die callbacks die man dem GPIO Modul übergibt bekommen als Argument immer den auslösenden pin. Eigentlich hat der Autor vorgesehen, dass dieser callback eine private Methode (per Konvention mit dem unterstrich gekennzeichnet) ist. Und dann den übergebenen callback OHNE Pin aufruft. Bei der clock macht er das auch. Beim Switch hat er es verbockt & die private Methode nicht genutzt. Sie ist dementsprechend wertlos. Stattdessen ruft er gleich den nicht-privaten als Argument übergebenen callback auf.
Sirius3
User
Beiträge: 17759
Registriert: Sonntag 21. Oktober 2012, 17:20

Noch ein paar Anmerkungen zum Code. Der sieht ja schon ganz ordentlich aus. Konvention ist aber, dass man Variablen in Python klein_mit_unterstrich schreibt. Das was unter `if __name__ = "__main__":` steht sollte in eine Funktion namens main wandern.
Antworten