Python-Programm für einen Zähler
Gefragt war ein Impulszähler mit einer graphischen Oberfläche. Wenn der Zähler einen Grenzwert erreicht, soll ein Ausgang geschaltet werden.
Weil tkinter in meiner Code-Sammlung noch fehlte, habe ich mich dahinter geklemmt:
tkinter ist etwas gewöhnungsbedürftig, aber nicht unüberwindbar.
Das Script
Nutzt die "Interrupts" von RPi.GPIO, um auch recht kurze Impulse zu erfassen. Weil es auf Flanken reagiert, ist es auf saubere Impulse angewiesen. Jegliches Prellen würde gnadenlos mitgezählt so lange die "Interrupts" schnell genug sind.
Wegen der Kohäsion sollte der Code für die GPIOs sollte eigentlich nicht in MainWindow stehen, aber der Einfachheit halber ist er trotzdem dort eingebaut. Bei einer Erweiterung müsste das refactored werden.
Die verwendeten GPIO-Pins und das Update-Intervall werden bei der Instanzierung der Klasse übergeben.
Das Limit wird im Konstruktor gesetzt. Das ist wahrscheinlich nicht passend für eine praktische Anwendung, kann aber einfach geändert werden.
from tkinter import Tk, Label, Button, E, X
import RPi.GPIO as GPIO
class MainWindow:
"""The GUI for this system
It implements all the functions which are necessary for the application.
"""
def __init__( self, inputpin, outputpin, interval ):
"""Sets up the GPIOs and constructs the Window.
Parameters
----------
inputpin: integer
the GPIO pin used as input
outputpin: integer
the GPIO pin used as output
interval: integer
the interval between updates (ms)
"""
# Initialize the member variables
self.limit = 10000
self.counter = 0
self.interval = interval
self.outputpin = outputpin
# Sets up the GPIOs
GPIO.setmode( GPIO.BCM )
GPIO.setup( inputpin, GPIO.IN )
GPIO.setup( outputpin, GPIO.OUT )
GPIO.add_event_detect( inputpin, GPIO.RISING, callback=self.count )
GPIO.output( outputpin, GPIO.LOW )
# Constructs the Window
self.root = Tk()
self.root.title( "Found at http://blog.heimetli.ch" )
lbl = Label( self.root, text="Counter", font=("Helvetica",40,"bold") )
lbl.pack( fill=X )
self.label = Label( self.root, text=str(self.counter), anchor=E, width=7, font=("Helvetica",120,"bold") )
self.label.pack()
lbl = Label( self.root, text="Limit", font=("Helvetica",40,"bold") )
lbl.pack( fill=X )
lbl = Label( self.root, text=str(self.limit), anchor=E, width=7, font=("Helvetica",120,"bold") )
lbl.pack()
btn = Button( self.root, text="Reset", command=self.reset, font=("Helvetica",40,"bold") )
btn.pack()
# Starts the update mechanism
self.root.after( self.interval, self.update )
# Shows the window and runs the application
self.root.mainloop()
def update( self ):
"""Displays the current counter value and schedules a call to itself."""
self.label["text"] = str(self.counter)
self.root.after( self.interval, self.update )
def count( self, channel ):
"""Counts the pulses."""
self.counter = self.counter + 1
# Turn off the machine if the limit is reached
if self.counter >= self.limit:
GPIO.output( self.outputpin, GPIO.HIGH )
def reset( self ):
"""Resets the counter."""
self.counter = 0
# Starts the application
#
# The GPIO used as input is GPIO4
# The GPIO used as output is GPIO18
# The window is updated every 100ms
app = MainWindow( 4, 18, 100 )
Update 25.03.2020
Variablen umbenannt und die globalen Variablen zu Attributen der Klasse gemacht.