J'ai créé un mini script pour redémarrer mon Raspberry Pi sur simple pression d'un bouton. Le script utilise simplement le câblagePi (commande gpio) pour définir la broche 0 (broche 17 dans l'ordre de numérotation standard du Raspberry Pi) pour entrer, puis lit la valeur jusqu'à ce qu'elle soit une (c'est-à-dire lorsque le bouton est enfoncé ou maintenu enfoncé).
Voici mon script:
gpio mode 0 in
while (true)
do
if [ `gpio read 0` -eq 1 ]
then
echo password | sudo -S reboot
break
fi
done &
Le script fonctionne bien et tout.
Cependant, pour ceux d'entre vous qui ne connaissent pas le Pi, il est livré avec des ressources matérielles très limitées (dont 512 Mo de mémoire) qui peuvent être facilement consommées par une boucle comme celle que j'utilise.
Ce que j'essaie de réaliser ici, c'est de trouver une autre façon pour bash de savoir quand la valeur est passée de 0
à 1
sans avoir à lui consacrer davantage une boucle inconditionnelle. Est-ce faisable? Veuillez partager vos idées.
la source
Réponses:
Analyse et solution moderne
Le script est une boucle occupée: il continue de lire les broches GPIO encore et encore. Il ne consomme pas beaucoup de mémoire mais garde le CPU occupé.
Vous devez définir la broche GPIO en mode bord. L'
gpio
utilitaire dispose d'une commandewfi
(attendre l'interruption) que vous pouvez utiliser pour réagir à un déclencheur de front. (gpio wfi
n'existait pas lorsque la question a été posée.)Une solution Python
Il existe une bibliothèque Python pour l'accès GPIO , qui prend en charge le mode Edge. Voici du code Python complètement non testé qui devrait faire ce que vous voulez.
Conseils supplémentaires sur la coque
(true)
pourrait être écrit justetrue
. Les parenthèses créent un sous-processus, ce qui est complètement inutile.`gpio read 0`
devrait être entre guillemets. Sans guillemets, la sortie de la commande est traitée comme une liste de modèles génériques de nom de fichier. Avec des guillemets doubles, la sortie de la commande est traitée comme une chaîne. Mettez toujours des guillemets autour des substitutions de commandes et des substitutions de variables:"$(some_command)"
,"$some_variable"
. En outre, vous devez utiliser la syntaxe$(…)
plutôt que`…`
: elle a exactement la même signification, mais la syntaxe backquote a quelques bizarreries d'analyse lorsque la commande est complexe. Donc:if [ "$(gpio read 0)" -eq 1 ]
Ne mettez pas le mot de passe root dans le script. Si le script s'exécute en tant que root, vous n'avez pas du tout besoin de sudo. Si le script ne s'exécute pas en tant que root, accordez à l'utilisateur exécutant le script l'autorisation de s'exécuter
sudo reboot
sans fournir de mot de passe. Exécutezvisudo
et ajoutez la ligne suivante:Notez que s'il y a une entrée pour le même utilisateur dans le fichier sudoers qui nécessite un mot de passe, l'
NOPASSWD
entrée doit venir après.Une fois que vous avez déclenché un redémarrage, vous n'avez pas besoin de rompre la boucle, le système s'arrêtera quand même.
Si vous décidez de continuer à utiliser ce script shell et que votre version de
gpio
est trop ancienne pour avoir lawfi
sous - commande, voici une version améliorée qui ne vérifie que l'état du bouton toutes les secondes. Notez que comme la broche n'est lue qu'une fois par seconde, cela signifie que vous devez maintenir le bouton enfoncé pendant au moins une seconde pour être sûr que l'événement est détecté.la source
0.1
ou peut-être0.2
devrait être capable de détecter des pressions très courtes et de laisser suffisamment de temps CPU pour les autres threads.sleep(1)
l'acceptation d'un nombre fractionnaire de secondes n'est pas standard.gpio wfi 0 rising
attendrait un front montant sur la broche zéro, qui n'est pas occupée (selon le site de câblage pi ).Ce que vous avez est connu comme une boucle occupée . Votre boucle ne consommera pratiquement pas de mémoire, mais elle consommera beaucoup de CPU. Ceci est généralement atténué en ajoutant
sleep
au corps de la boucle.Se débarrasser de la boucle occupée dépendra de ce qui se
gpio
passe. Il existe des appels système tels queselect()
, qui peuvent bloquer jusqu'à ce qu'un descripteur de fichier soit prêt.En ce qui concerne l'efficacité, la commande
()
aroundtrue
s'exécutetrue
en fait dans un sous-shell. Cela n'est pas nécessaire et peut être mieux exprimé par ce qui suit:la source
Essayez ce qui suit:
la source