Ich habe ein Mini-Skript erstellt, um meinen Raspberry Pi auf Knopfdruck neu zu starten. Das Skript verwendet einfach wiringPi (Befehl gpio), um Pin 0 (Pin 17 in der Raspberry Pi-Standardnummerierungsreihenfolge) für die Eingabe festzulegen, und liest dann den Wert, bis er eins ist (dh wenn die Taste gedrückt oder gedrückt gehalten wird).
Hier ist mein Skript:
gpio mode 0 in
while (true)
do
if [ `gpio read 0` -eq 1 ]
then
echo password | sudo -S reboot
break
fi
done &
Das Skript funktioniert gut und alles.
Für diejenigen unter Ihnen, die mit dem Pi nicht vertraut sind, sind jedoch nur sehr begrenzte Hardwareressourcen (einschließlich 512 MB Speicher) verfügbar, die von einer Schleife wie der von mir verwendeten problemlos verbraucht werden können.
Was ich hier erreichen möchte, ist, einen anderen Weg für bash zu finden, um herauszufinden, wann sich der Wert von 0
zu geändert hat , 1
ohne dafür eine eher bedingungslose Schleife zu reservieren. Ist das machbar? Bitte teilen Sie Ihre Ideen.
quelle
Antworten:
Analyse und moderne Lösung
Das Skript ist eine Besetztschleife: Es liest immer wieder die GPIO-Pins. Es verbraucht nicht viel Speicher, hält aber die CPU beschäftigt.
Sie sollten den GPIO-Pin in den Edge-Modus versetzen. Das
gpio
Dienstprogramm verfügt über einenwfi
Befehl (Warten auf Interrupt), mit dem Sie auf einen Flankentrigger reagieren können. (gpio wfi
existierte nicht zurück, als die Frage gestellt wurde.)Eine Python-Lösung
Es gibt eine Python-Bibliothek für den GPIO-Zugriff , die den Edge-Modus unterstützt. Hier ist ein völlig ungetesteter Python-Code, der das tun soll, was Sie wollen.
Zusätzliche Shell-Tipps
(true)
könnte gerade geschrieben werdentrue
. Die Klammern erstellen einen Unterprozess, der völlig unnötig ist.`gpio read 0`
sollte in doppelten Anführungszeichen stehen. Ohne Anführungszeichen wird die Ausgabe des Befehls als Liste von Platzhaltermustern für Dateinamen behandelt. Bei doppelten Anführungszeichen wird die Ausgabe des Befehls als Zeichenfolge behandelt. Setzen Sie immer doppelte Anführungszeichen um Befehlssubstitutionen und Variablensubstitutionen:"$(some_command)"
,"$some_variable"
. Sie sollten auch die Syntax verwenden$(…)
und nicht`…`
: Sie hat genau die gleiche Bedeutung, aber die Backquote-Syntax weist einige Parsing-Macken auf, wenn der Befehl komplex ist. Somit:if [ "$(gpio read 0)" -eq 1 ]
Fügen Sie das Root-Passwort nicht in das Skript ein. Wenn das Skript als root ausgeführt wird, benötigen Sie sudo überhaupt nicht. Wenn das Skript nicht als root ausgeführt wird, erteilen Sie dem Benutzer, der das Skript ausführt, die Berechtigung zum Ausführen,
sudo reboot
ohne ein Kennwort anzugeben. Führenvisudo
Sie die folgende Zeile aus und fügen Sie sie hinzu:Beachten Sie, dass der Eintrag folgen
NOPASSWD
muss , wenn in der sudoers-Datei ein Eintrag für denselben Benutzer vorhanden ist, für den ein Kennwort erforderlich ist .Sobald Sie einen Neustart auslösen, müssen Sie die Schleife nicht mehr unterbrechen, das System stoppt trotzdem.
Wenn Sie dieses Shell-Skript weiterhin verwenden möchten und Ihre Version von
gpio
zu alt ist, um denwfi
Unterbefehl zu verwenden, finden Sie hier eine verbesserte Version, die nur den Schaltflächenstatus jede Sekunde überprüft. Da der Pin nur einmal pro Sekunde gelesen wird, müssen Sie die Taste mindestens eine Sekunde lang gedrückt halten, um sicherzustellen, dass das Ereignis erfasst wird.quelle
0.1
oder0.2
sollte vielleicht in der Lage sein, sehr kurze Druckvorgänge zu erkennen und dennoch viel CPU-Zeit für andere Threads zu lassen.sleep(1)
die Akzeptanz einer gebrochenen Anzahl von Sekunden nicht Standard.gpio wfi 0 rising
würde auf eine ansteigende Flanke an Pin Null warten, die nicht belegt ist (gemäß der Verdrahtungs-Pi-Site ).Was Sie haben, ist als Besetztschleife bekannt . Ihre Schleife verbraucht kaum Speicher, aber viel CPU. Dies wird normalerweise durch Hinzufügen
sleep
zum Schleifenkörper gemildert .Die Beseitigung der Besetztschleife hängt davon ab, was sie
gpio
tut. Es gibt Systemaufrufe wieselect()
, die blockieren können, bis ein Dateideskriptor bereit ist.In Bezug auf die Effizienz wird der Befehl
()
um dentrue
Befehl herum tatsächlichtrue
in einer Unterschale ausgeführt. Dies ist nicht erforderlich und kann wie folgt besser ausgedrückt werden:quelle
Versuche Folgendes:
quelle