He creado un mini script para reiniciar mi Raspberry Pi con solo presionar un botón. La secuencia de comandos simplemente usa cableadoPi (comando gpio) para establecer el pin 0 (pin 17 en el orden de numeración estándar de Raspberry Pi) para ingresar, y luego lee el valor hasta que sea uno (es decir, cuando se presiona o mantiene presionado el botón).
Aquí está mi guión:
gpio mode 0 in
while (true)
do
if [ `gpio read 0` -eq 1 ]
then
echo password | sudo -S reboot
break
fi
done &
El guión funciona bien y todo.
Sin embargo, para aquellos de ustedes que no están familiarizados con el Pi, viene con recursos de hardware muy limitados (que incluyen 512 MB de memoria) que pueden ser fácilmente consumidos por un bucle como el que estoy usando.
Lo que estoy tratando de lograr aquí es encontrar otra forma para que bash descubra cuándo el valor ha cambiado de 0
a 1
sin tener que dedicarle un ciclo más incondicional. ¿Es esto factible? Por favor comparte tus ideas.
fuente
Respuestas:
Análisis y solución moderna.
El script es un ciclo ocupado: sigue leyendo los pines GPIO una y otra vez. No consume mucha memoria pero mantiene ocupada la CPU.
Debe configurar el pin GPIO en modo borde. La
gpio
utilidad tiene unwfi
comando (esperar interrupción) que puede usar para reaccionar a un disparador de borde. (gpio wfi
no existía cuando se hizo la pregunta).Una solución Python
Hay una biblioteca de Python para acceso GPIO , que admite el modo de borde. Aquí hay un código de Python completamente no probado que debería hacer lo que quieras.
Consejos de carcasa adicionales
(true)
podría escribirse solotrue
. Los paréntesis crean un subproceso, que es completamente innecesario.`gpio read 0`
debe estar entre comillas dobles. Sin comillas, la salida del comando se trata como una lista de patrones comodín de nombre de archivo. Con comillas dobles, la salida del comando se trata como una cadena. Siempre ponga comillas dobles alrededor de las sustituciones de comandos y las sustituciones de variables:"$(some_command)"
,"$some_variable"
. Además, debe usar la sintaxis en$(…)
lugar de`…`
: tiene exactamente el mismo significado, pero la sintaxis de la comilla inversa tiene algunas peculiaridades de análisis cuando el comando es complejo. Así:if [ "$(gpio read 0)" -eq 1 ]
No ponga la contraseña de root en el script. Si el script se ejecuta como root, no necesita sudo en absoluto. Si el script no se está ejecutando como root, entonces otorgue al usuario que ejecuta el script el permiso para ejecutarse
sudo reboot
sin proporcionar una contraseña. Ejecutevisudo
y agregue la siguiente línea:Tenga en cuenta que si hay una entrada para el mismo usuario en el archivo sudoers que requiere una contraseña, la
NOPASSWD
entrada debe aparecer después.Una vez que activa un reinicio, no necesita romper el ciclo, el sistema se detendrá de todos modos.
Si decide seguir usando este script de shell y su versión de
gpio
es demasiado antigua para tener elwfi
subcomando, aquí hay una versión mejorada que solo comprueba el estado del botón cada segundo. Tenga en cuenta que dado que el pin solo se lee una vez por segundo, esto significa que debe mantener el botón presionado durante al menos un segundo para asegurarse de que el evento se detecte.fuente
0.1
o tal vez0.2
debería ser capaz de detectar prensas muy cortas y aún así dejar suficiente tiempo de CPU para otros hilos.sleep(1)
la aceptación de un número fraccionario de segundos no es estándar.gpio wfi 0 rising
esperaría un flanco ascendente en el pin cero, que no está ocupado (según el sitio de cableado pi ).Lo que tienes se conoce como un circuito ocupado . Su bucle no consumirá apenas memoria, pero consumirá mucha CPU. Esto normalmente se mitiga agregando
sleep
al cuerpo del bucle.Deshacerse del ciclo ocupado dependerá de lo que
gpio
haga. Hay llamadas del sistema comoselect()
, que pueden bloquearse hasta que un descriptor de archivo esté listo.En cuanto a la eficiencia,
()
eltrue
comando alrededor del comando realmente se ejecutatrue
en una subshell. Esto no es necesario y se puede expresar mejor con lo siguiente:fuente
Intenta lo siguiente:
fuente