Raspberry Pi – przycisk zasilania dla malinki
Odkąd zacząłem używać malinki rzeczą której najbardziej mi brakowało (szczególnie, kiedy już odłączyłem się od SSH) był przycisk, którym mógłbym malinkę włączyć, wyłączyć lub zresetować. W dzisiejszym artykule dowiemy się jak w prosty sposób zrobić sobie taki elegancki guziczek :)
Robimy przycisk
Fizyczny przycisk postanowiłem zrobić z tact-switcha oraz 2 pinowego żeńskiego złącza goldpin.
Zaginamy piny przycisku do środka, a oba piny złącza goldpin w przeciwne strony:
Teraz wsuwamy piny złącza pomiędzy zagięte piny przycisku
a następnie używając nieco kalafonii lutujemy złącza ze sobą.
Ja postanowiłem obkurczyć jeszcze całość koszulką termokurczliwą w ten sposób:
Teraz nasz przycisk jest już gotowy. Możemy go nasunąć na trzecią parę pinów tak jak u mnie:
Skrypt pythona
Mózgiem naszego przesięwzięcia będzie python, który poczeka na wciśnięcie przycisku, a następnie poczeka na jego zwolnienie. Po tych dwóch zdarzeniach obliczy czas przez jaki przycisk był wciśnięty i na tej podstawie zadecyduje czy wydać polecenie restartu malinki, czy też wyłączenia.
Aby utworzyć skrypt przechodizmy do folderu /usr/local/bin/, następnie tworzymy w nim katalog o nazwie powerbtn, a w owym katalogu plik powerbtn.py i edytujemy go.
cd /usr/local/bin/ sudo mkdir powerbtn cd powerbtn sudo touch powerbtn.py sudo nano powerbtn.py
Wpisujemy do niego następującą treść:
#!/usr/bin/env python import RPi.GPIO as GPIO import time import subprocess SHUTDOWN_PIN = 3 LONG_PRESS_TIME_IN_SECONDS = 2.0 GPIO.setmode(GPIO.BCM) GPIO.setup(SHUTDOWN_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP) GPIO.wait_for_edge(SHUTDOWN_PIN, GPIO.FALLING) buttonPressStart = time.time() GPIO.wait_for_edge(SHUTDOWN_PIN, GPIO.RISING) buttonPressedTime = time.time() - buttonPressStart GPIO.cleanup() if LONG_PRESS_TIME_IN_SECONDS > buttonPressedTime: subprocess.call(["shutdown", "-h", "now"]) else: subprocess.call(["shutdown", "-r", "now"])
gdzie SHUTDOWN_PIN to numer pinu według numeracji na stronie https://pinout.xyz/ (numerki oznaczone BCM x). Polecam zostać przy pinue numer 3, gdyż jest on w pewnien sposób specjalny. Jeżeli zewrzemy go do masy kiedy Raspberry jest wyłączone, to spowoduje uruchomienie komputerka. Tym samym załątwimy sobie jednym przyciskiem 3 różne funkcje (wyłączenie, restart oraz włączenie).
LONG_PRESS_TIME_IN_SECONDS to jak sama nazwa wskazuje czas długiego wciśnięcia przycisku wyrażony w sekundach. Jeżeli wciśnięcie przycisku będzie krótsze od tej wartości to malinka się wyłączy, a w przeciwnym wypadku zrestartuje.
Kiedy zapiszemy plik nadajemy jeszcze tylko uprawnienia do wykonywania:
sudo chmod +x powerbtn.py
Tworzymy serwis dla naszego skryptu
W poszukiwaniu informacji o tworzeniu własnego daemona natknąłem się na wpis, w którym autor przedstawił ciekawy wzór skryptu daemona:
Na podstawie tego skryptu robimy nasz zmieniając kilka linijek.
Najpierw przechodzimy do /etc/init.d i tworzymy tam plik powerbtn.sh
cd /etc/init.d/ sudo touch powerbtn.sh sudo nano powerbtn.sh
I wpisujemy do niego taką zawartość:
#!/bin/sh ### BEGIN INIT INFO # Provides: powerbtn # Required-Start: $remote_fs $syslog # Required-Stop: $remote_fs $syslog # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: Power button service # Description: Invokes system restart on long button press or system shutdown on short button press ### END INIT INFO DIR=/usr/local/bin/powerbtn DAEMON=$DIR/powerbtn.py DAEMON_NAME=powerbtn DAEMON_OPTS="" DAEMON_USER=root PIDFILE=/var/run/$DAEMON_NAME.pid . /lib/lsb/init-functions do_start () { log_daemon_msg "Starting system $DAEMON_NAME daemon" start-stop-daemon --start --background --pidfile $PIDFILE --make-pidfile --user $DAEMON_USER --chuid $DAEMON_USER --startas $DAEMON -- $DAEMON_OPTS log_end_msg $? } do_stop () { log_daemon_msg "Stopping system $DAEMON_NAME daemon" start-stop-daemon --stop --pidfile $PIDFILE --retry 10 log_end_msg $? } case "$1" in start|stop) do_${1} ;; restart|reload|force-reload) do_stop do_start ;; status) status_of_proc "$DAEMON_NAME" "$DAEMON" && exit 0 || exit $? ;; *) echo "Usage: /etc/init.d/$DAEMON_NAME {start|stop|restart|status}" exit 1 ;; esac exit 0
Po czym ustawiamy chmoda:
sudo chmod +x powerbtn.sh
Usuwamy powroty karetek
Jeżeli edytowaliśmy nasze pliki na systmie Windows prawdopodobnie na końcu każdej linii są tam znaki \r\n. Niestety linux i windows mają nieco odmienne zdanie na temat kodowania końca linii i aby nasze pliki dało się uruchomić pod linuxem musimy usunąć znak powrotku karetki \r.
Robimy to za pomocą sed’a:
sudo sed -i -e 's/\r//g' /etc/init.d/powerbtn.sh sudo sed -i -e 's/\r//g' /usr/local/bin/powerbtn/powerbtn.py
Uruchamiamy serwis
Teraz możemy ręcznie uruchomić serwis wpisując do wiersza poleceń następującą komendę:
sudo /etc/init.d/powerbtn.sh start
a także zakomunikować malince, aby uruchamiała serwis automatycznie po starcie systemu:
sudo update-rc.d powerbtn.sh defaults
i sprawdzamy czy wszystko działa przyciskając na krótko lub przytrzymując na dłużej nasz przycisk :)
Kiedy uruchomimy ponownie naszą malinkę serwis powinien wystartować automatycznie. Od teraz możemy cieszyć się eleganckim przyciskiem zasilania.
Rewelacja! Bardzo fajne, proste rozwiązanie.
Proszę tylko dodać w sekcji „Uruchamiamy serwis” informację, że żeby usługa rzeczywiście startowała wraz z systemem, trzeba ją jeszcze przypisać do odpowiednich (domyślnych) runmodów:
sudo update-rc.d powerbtn.sh defaults
Dziękuję i pozdrawiam!
Wykonałem wszystko według instrukcji i mam taki komunikat przy starcie serwisu: Starting powerbtn.sh (via systemctl): powerbtn.serviceFailed to start powerbtn.service: Unit powerbtn.service failed to load: No such file or directory.
Może dlatego, że robię to na Volumio?