Я создал мини-скрипт для перезагрузки моего Raspberry Pi по нажатию кнопки. Сценарий просто использует wiringPi (команда gpio), чтобы установить на вход вывод 0 (вывод 17 в стандартном порядке нумерации Raspberry Pi), а затем считывает значение до единицы (то есть, когда кнопка нажата или удерживается нажатой).
Вот мой сценарий:
gpio mode 0 in
while (true)
do
if [ `gpio read 0` -eq 1 ]
then
echo password | sudo -S reboot
break
fi
done &
Скрипт работает отлично и все.
Тем не менее, для тех из вас, кто не знаком с Pi, он имеет очень ограниченные аппаратные ресурсы (включая 512 МБ памяти), которые можно легко использовать в цикле, подобном тому, который я использую.
Здесь я пытаюсь добиться другого способа, чтобы bash мог определить, когда значение изменилось с 0
на 1
без необходимости выделять для него более похожий на безусловный цикл. Это выполнимо? Пожалуйста, поделитесь своими идеями.
источник
Ответы:
Анализ и современное решение
Скрипт является занятым циклом: он продолжает читать выводы GPIO снова и снова. Он не потребляет много памяти, но загружает процессор.
Вы должны установить вывод GPIO в режиме края.
gpio
Утилита имеетwfi
(ожидание прерывания) команды , которые вы можете использовать , чтобы реагировать на спусковой крючок края. (gpio wfi
не существовало назад, когда был задан вопрос.)Решение Python
Существует библиотека Python для доступа к GPIO , которая поддерживает граничный режим. Вот некоторый полностью непроверенный код Python, который должен делать то, что вы хотите.
Дополнительные подсказки раковины
(true)
может быть написано простоtrue
. Скобки создают подпроцесс, который совершенно не нужен.`gpio read 0`
должно быть в двойных кавычках. Без кавычек вывод команды обрабатывается как список шаблонов имен файлов. В двойных кавычках вывод команды обрабатывается как строка. Всегда ставьте двойные кавычки вокруг подстановок команд и подстановок переменных:"$(some_command)"
,"$some_variable"
. Кроме того, вы должны использовать синтаксис,$(…)
а не`…`
: он имеет точно такое же значение, но синтаксис обратной кавычки имеет некоторые причуды синтаксического анализа, когда команда сложна. Таким образом:if [ "$(gpio read 0)" -eq 1 ]
Не помещайте пароль root в скрипт. Если скрипт выполняется от имени пользователя root, вам вообще не нужен sudo. Если сценарий не запущен от имени пользователя root, предоставьте пользователю, запускающему сценарий, разрешение на запуск
sudo reboot
без указания пароля. Запуститеvisudo
и добавьте следующую строку:Обратите внимание, что если в файле sudoers есть запись для того же пользователя, для которой требуется пароль, то
NOPASSWD
запись должна идти после.Как только вы запускаете перезагрузку, вам не нужно прерывать цикл, система все равно остановится.
Если вы решите продолжать использовать этот сценарий оболочки, а ваша версия
gpio
слишком старая, чтобы иметьwfi
подкоманду, вот улучшенная версия, которая проверяет состояние кнопки каждую секунду. Обратите внимание, что, поскольку пин-код считывается только один раз в секунду, это означает, что вам нужно удерживать кнопку нажатой не менее одной секунды, чтобы быть уверенным, что событие зафиксировано.источник
0.1
или, возможно,0.2
должно быть в состоянии обнаруживать очень короткие нажатия и при этом оставлять достаточно времени ЦП для других потоков.sleep(1)
принятие дробного числа секунд не является стандартным.gpio wfi 0 rising
ожидание нарастающего фронта на нулевом выводе, который не занят (в соответствии с сайтом подключения проводки ).То, что у вас есть, известно как занятая петля . Ваш цикл не будет потреблять почти никакой памяти, но он будет потреблять много процессора. Обычно это смягчается добавлением
sleep
в тело цикла.Избавление от занятой петли будет зависеть от того, что
gpio
делает. Существуют системные вызовы, такие какselect()
, которые могут блокировать, пока дескриптор файла не будет готов.Что касается эффективности, команда
()
вокругtrue
фактически выполняетсяtrue
в подоболочке. Это не нужно и может быть лучше выражено с помощью следующего:источник
Попробуйте следующее:
источник