Taster gedrückt halten und Shut down

Python auf Einplatinencomputer wie Raspberry Pi, Banana Pi / Python für Micro-Controller
Antworten
rasty
User
Beiträge: 7
Registriert: Montag 23. Juli 2018, 09:35

Hallo zusammen,
dürfte ich hier vielleicht kurz um eine professionelle Hilfestellung bitten ...

Ich bin Hobbymusiker und habe mir vor 4 Jahren ein Gehäuse für einen Computermonitor gebaut, der mir auf der Bühne meine Liedtexte anzeigt. Mit einem Fußtaster kann ich vor- und zurückblättern und angetrieben wird das von einem Raspberry Pi 2.

So sieht das Teil aus:
Bild

Es erweist mir auch regelmäßig gute Dienste, aber es gibt zwei Kleinigkeiten, die mich immer wieder daran stören.

1. Beim betätigen des Fußtasters wird immer eine Seite pro Tastendruck geblättert.
Hier würde ich mir wünschen, wenn man auf dem Taster bleibt, dass ein schnelles Vorblättern möglich ist.

2. Ich würde den Pi gerne irgendwie herunterfahren können.
D.h. wenn ich z.B. beide Taster für min. 3 Sek. gedrückt halte, soll automatisch heruntergefahren werden.


Ich habe mir vor 4 Jahren durch tagelange Recherche und rumprobieren folgendes Skript zusammengetragen.
Allerdings bin ich nach wie vor absoluter Python-Anfänger und habe eigentlich gar keine große Ahnung was da passiert.
Ehrlich gesagt wundere ich mich inzwischen, wie ich das vor 4 Jahren so geschafft habe, das zum laufen zu bringen. :lol:

Nun ja, jetzt stehen ab dem kommenden Wochenende wieder einige Auftritte meiner Band an und ich habe mal wieder darüber nachgedacht, wie toll das wäre, wenn diese beiden Kleinigkeiten endlich behoben werden.

Ich denke mir, für einen Profi kann das eigentlich gar kein großes Ding sein. Aber ich bin damit ziemlich überfordert. :roll:
Meine Stärke liegt da glaub ich eher im Bau der Kiste drumrum...


Hier nun der Code ... vielleicht ist ja jemand in der Lage und gewillt mir den anzupassen, damit meine Wünsche in Erfüllung gehen ...

Code: Alles auswählen

#!/usr/bin/env python

import RPi.GPIO as GPIO
import time
import subprocess

# SoC als Pinreferenz waehlen
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)

# Pins als Input und Pull-Down Widerstand aktivieren
GPIO.setup(23, GPIO.IN, pull_up_down = GPIO.PUD_DOWN)
GPIO.setup(24, GPIO.IN, pull_up_down = GPIO.PUD_DOWN)

# Interrupts
def Up(channel):
	if GPIO.input(24):
     		# Verzögeren und nochmal abfragen
		time.sleep(0.1)
		if GPIO.input(24):
			#Page down ausführen
			subprocess.call(["xdotool", "key", "Next"])

def Down(channel):
	if GPIO.input(23):
     		# Verzögeren und nochmal abfragen
		time.sleep(0.1)
		if GPIO.input(23):
			#Page up ausführen
			subprocess.call(["xdotool", "key", "Prior"])

# Interrupt Events hinzufuegen. Auf steigende Flanke reagieren und Bouncetime setzen
GPIO.add_event_detect(24, GPIO.RISING, callback = Up, bouncetime = 300)
GPIO.add_event_detect(23, GPIO.RISING, callback = Down, bouncetime = 300)

while True:
	time.sleep(1)

PS: Bitte nicht Kreuzigen! Ich bin echt blutiger Anfänger.
PPS: Freier Konzert-Eintritt ist natürlich drin. Allerdings spielen wir bislang nur sehr regionale Gigs in Bayern/Oberfranken. 8)
Und man sollte Hard Rock mögen... :twisted:
Sirius3
User
Beiträge: 17710
Registriert: Sonntag 21. Oktober 2012, 17:20

@rasty: es ist eine schlechte Idee, Tabs und Leerzeichen zu mischen (auch wenn Du nur Kommentare mit Leerzeichen eingerückt hast). Am besten stellst Du Deinen Editor so ein, dass er auch beim Drücken der Tabtaste 4 Leerzeichen einfügt. Warnungen sind dazu da, dass man sie behebt und nicht, dass man sie ausschaltet.

Für das Weiterblättern mußt Du einfach nur die if-Abfrage durch eine while-Schleife ersetzen.

Code: Alles auswählen

#!/usr/bin/env python
import RPi.GPIO as gpio
import time
import subprocess

PIN_UP = 23
PIN_DOWN = 24

def detect_click(channel):
    direction = "Next" if channel == PIN_UP else "Prior"
    time.sleep(0.1)
    delay = 1
    while gpio.input(channel):
        subprocess.call(["xdotool", "key", direction])
        time.sleep(delay)
        delay = 0.2

def initialize():
    gpio.setmode(gpio.BCM)
    gpio.setup([PIN_UP, PIN_DOWN], gpio.IN, pull_up_down=gpio.PUD_DOWN)
    gpio.add_event_detect([PIN_UP, PIN_DOWN], gpio.RISING, callback=detect_click, bouncetime=300)

def finalize():
    gpio.cleanup()

def main():
    initialize()
    try:
    while True:
        time.sleep(100)
    except KeyboardInterrupt:
        pass
    finally:
        finalize()

if __name__ == '__main__':
    main()
Für das Herunterfahren mußt Du eben innerhalb der while-Schleife noch eine zusätzliche Abfrage der anderen Taste einbauen. Das ist zwar nicht schön, aber ich denke, für einen Anfänger machbar.
rasty
User
Beiträge: 7
Registriert: Montag 23. Juli 2018, 09:35

Hallo Sirius3,
vorab vielen lieben Dank für Deine Antwort.

Trotzdem nochmal zum Verständnis:
Kann ich eine if-Abfrage mit "and" verknüpfen?

Also

Code: Alles auswählen

if GPIO.input(23) and GPIO.input(24):
    time.sleep(3)
        if GPIO.input(23) and GPIO.input(24):
            systemCall("sudo shutdown -h now")
Das würde doch bedeuten, dass abgefragt wird, ob an beiden Pins ein Signal anliegt, dann nach 3 Sekunden nochmal die Abfrage und wenn das zutrifft, dann fährt der Pi runter.

Oder denke ich da falsch bzw. zu laienhaft?

Hier der komplette Code:

Code: Alles auswählen

#!/usr/bin/env python
import RPi.GPIO as gpio
import time
import subprocess

PIN_UP = 23
PIN_DOWN = 24

# Mauszieger an die linke obere Ecke setzen
subprocess.call(["xdotool", "mousemove", "0", "0"])

def detect_click(channel):
    direction = "Next" if channel == PIN_UP else "Prior"
    time.sleep(0.1)
    delay = 1
    while gpio.input(channel):
	    if GPIO.input(23) and GPIO.input(24):
	        time.sleep(3)
	        if GPIO.input(23) and GPIO.input(24):
	            systemCall("sudo shutdown -h now")
        subprocess.call(["xdotool", "key", direction])
        time.sleep(delay)
        delay = 0.2

def initialize():
    gpio.setmode(gpio.BCM)
    gpio.setup([PIN_UP, PIN_DOWN], gpio.IN, pull_up_down=gpio.PUD_DOWN)
    gpio.add_event_detect([PIN_UP, PIN_DOWN], gpio.RISING, callback=detect_click, bouncetime=300)

def finalize():
    gpio.cleanup()

def main():
    initialize()
    try:
        while True:
            time.sleep(100)
    except KeyboardInterrupt:
        pass
    finally:
        finalize()

if __name__ == '__main__':
    main()
Sirius3
User
Beiträge: 17710
Registriert: Sonntag 21. Oktober 2012, 17:20

Jetzt verrätst Du mir noch, wo Du `systemCall` her hast, reparierst noch die Einrückungen, verschiebst Zeile 10 in `initialize`, benutzt die Konstaten PIN_UP und PIN_DOWN, und schon sieht das doch gar nicht so schlecht aus.
rasty
User
Beiträge: 7
Registriert: Montag 23. Juli 2018, 09:35

Oh Mann! Das klingt ja theoretisch einfach ... :cry:

Also das systemCall hab ich mir aus einem Skript zum herunterfahren mittels Taster "geklaut".
Aber ich vermute mal, dass da noch "import sys" mit rein muss.

Ich habe alle tabs mit 4 Leerzeichen ersetzt. Passt das jetzt?
Und was Du mit Konstaten PIN_UP und PIN_DOWN meinst ist mir auch gerade noch ein Rätsel.

Entschuldige bitte, wenn ich mich recht "hinterwäldlerisch" anstelle. Aber das ist echt Neuland für mich.

Code: Alles auswählen

#!/usr/bin/env python
#coding: utf8

import RPi.GPIO as GPIO
import time
import subprocess

PIN_UP = 23
PIN_DOWN = 24

def detect_click(channel):
    direction = "Next" if channel == PIN_UP else "Prior"
    time.sleep(0.1)
    delay = 1
    while gpio.input(channel):
        if GPIO.input(23) and GPIO.input(24):
            time.sleep(3)
            if GPIO.input(23) and GPIO.input(24):
                systemCall("sudo shutdown -h now")
        subprocess.call(["xdotool", "key", direction])
        time.sleep(delay)
        delay = 0.2

def initialize():
    gpio.setmode(gpio.BCM)
    gpio.setup([PIN_UP, PIN_DOWN], gpio.IN, pull_up_down=gpio.PUD_DOWN)
    gpio.add_event_detect([PIN_UP, PIN_DOWN], gpio.RISING, callback=detect_click, bouncetime=300)
    subprocess.call(["xdotool", "mousemove", "0", "0"])

def finalize():
    gpio.cleanup()

def main():
    initialize()
    try:
        while True:
            time.sleep(100)
    except KeyboardInterrupt:
        pass
    finally:
        finalize()

if __name__ == '__main__':
    main()
rasty
User
Beiträge: 7
Registriert: Montag 23. Juli 2018, 09:35

Aaaahhh...

Die Konstanten habe ich kapiert ... :lol:

Code: Alles auswählen

#!/usr/bin/env python

import RPi.GPIO as GPIO
import time
import subprocess
import sys

PIN_UP = 23
PIN_DOWN = 24

def detect_click(channel):
    direction = "Next" if channel == PIN_UP else "Prior"
    time.sleep(0.1)
    delay = 1
    while gpio.input(channel):
        if GPIO.input(PIN_UP) and GPIO.input(PIN_DOWN):
            time.sleep(3)
            if GPIO.input(PIN_UP) and GPIO.input(PIN_DOWN):
                systemCall("sudo shutdown -h now")
        subprocess.call(["xdotool", "key", direction])
        time.sleep(delay)
        delay = 0.2

def initialize():
    gpio.setmode(gpio.BCM)
    gpio.setup([PIN_UP, PIN_DOWN], gpio.IN, pull_up_down=gpio.PUD_DOWN)
    gpio.add_event_detect([PIN_UP, PIN_DOWN], gpio.RISING, callback=detect_click, bouncetime=300)
    subprocess.call(["xdotool", "mousemove", "0", "0"])

def finalize():
    gpio.cleanup()

def main():
    initialize()
    try:
        while True:
            time.sleep(100)
    except KeyboardInterrupt:
        pass
    finally:
        finalize()

if __name__ == '__main__':
    main()
Sirius3
User
Beiträge: 17710
Registriert: Sonntag 21. Oktober 2012, 17:20

Code: Alles auswählen

subprocess.call(["sudo", "shutdown", "-h", "now"])
rasty
User
Beiträge: 7
Registriert: Montag 23. Juli 2018, 09:35

Super! Vielen Dank!

Eine Frage noch:
Wäre es sehr Aufwendig da noch eine Abfrage über eine Messagebox einzubauen?

Also wenn beide Taster für 3 Sek. gedrückt, soll ein Fenster erscheinen, dass das System heruntergefahren wird...
PIN_UP für Ja
PIN_DOWN für Nein

Oder sprengt das den Rahmen?
Sirius3
User
Beiträge: 17710
Registriert: Sonntag 21. Oktober 2012, 17:20

@rasty: die Frage ist ja, ob Du das Wissen dazu hast.
rasty
User
Beiträge: 7
Registriert: Montag 23. Juli 2018, 09:35

Wohl eher nicht... :cry:
War nur ne Idee und hätte ja sein können, dass es mit ein, zwei weiteren Zeilen getan ist.

Jetzt werde ich aber heut Abend erstmal ausprobieren ob bis hierhin alles funktioniert...

@Sirius3: Wie kann ich Dir für die Hilfe danken??
rasty
User
Beiträge: 7
Registriert: Montag 23. Juli 2018, 09:35

Mist ...
Sitze vor der Kiste und komme seit Stunden nicht weiter.

Bekomme immer wieder solche Meldungen:

Traceback (most recent call last):
File "/home/pi/Desktop/taster.py", line 43, in <module>
main()
File "/home/pi/Desktop/taster.py", line 33, in main
initialize()
File "/home/pi/Desktop/taster.py", line 26, in initialize
GPIO.add_event_detect([PIN_UP, PIN_DOWN], GPIO.RISING, callback=detect_click, bouncetime=300)
TypeError: an integer is required

Und das besch... ist, dass ich es irgendwie nicht mal mehr schaffe alles wieder auf den alten Stand zu setzen.
Da hat wenigstens das einfache umblättern funktioniert.

Kann jemand helfen?
Bei mir qualmt der Kopf und ich bin anscheinend einfach zu doof dazu ...
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Dein Setup call ist verfummelt. Die Liste mit [PIN_UP, PIN_DOWN] hat da nichts verloren.

Und für die Zukunft: sichere dir deine Zwischenstände. Oder mach mindestens Vollbackups. Deine SD Karte mag irgendwann den Geist aufgeben, und dann hast du NIX mehr in den Händen.
Benutzeravatar
__blackjack__
User
Beiträge: 13003
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Der `setup()`-Aufruf ist okay, es ist `add_event_detect()` das keine Liste mit Pins mag.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ups. Ja, natürlich.
Antworten