Eu criei um mini script para reiniciar o meu Raspberry Pi com o pressionar de um botão. O script simplesmente usa o wirePi (comando gpio) para definir o pino 0 (pino 17 na ordem de numeração padrão do Raspberry Pi) para inserir e, em seguida, lê o valor até que seja um (ou seja, quando o botão é pressionado ou pressionado).
Aqui está o meu script:
gpio mode 0 in
while (true)
do
if [ `gpio read 0` -eq 1 ]
then
echo password | sudo -S reboot
break
fi
done &
O script funciona bem e tudo.
No entanto, para aqueles que não conhecem o Pi, ele possui recursos de hardware muito limitados (incluindo 512 MB de memória) que podem ser facilmente consumidos por um loop como o que estou usando.
O que estou tentando conseguir aqui é encontrar outra maneira de o bash descobrir quando o valor mudou de 0
para 1
sem ter que dedicar um loop mais como um incondicional. Isso é factível? Por favor, compartilhe suas idéias.
fonte
Respostas:
Análise e solução moderna
O script é um loop ocupado: ele continua lendo os pinos do GPIO repetidamente. Não consome muita memória, mas mantém a CPU ocupada.
Você deve definir o pino GPIO no modo de borda. O
gpio
utilitário possui umwfi
comando (aguarde interrupção) que você pode usar para reagir a um gatilho de borda. (gpio wfi
não existia quando a pergunta foi feita.)Uma solução Python
Há uma biblioteca Python para acesso ao GPIO , que suporta o modo de borda. Aqui está um código Python completamente não testado que deve fazer o que você deseja.
Dicas adicionais de shell
(true)
poderia ser escrito apenastrue
. Os parênteses criam um subprocesso, que é completamente desnecessário.`gpio read 0`
deve estar entre aspas duplas. Sem aspas, a saída do comando é tratada como uma lista de padrões curinga do nome do arquivo. Com aspas duplas, a saída do comando é tratada como uma sequência. Sempre coloque aspas duplas em torno das substituições de comandos e substituições de variáveis:"$(some_command)"
,"$some_variable"
. Além disso, você deve usar a sintaxe em$(…)
vez de`…`
: ela tem exatamente o mesmo significado, mas a sintaxe de aspas retroativas possui algumas peculiaridades de análise quando o comando é complexo. Portanto:if [ "$(gpio read 0)" -eq 1 ]
Não coloque a senha root no script. Se o script estiver sendo executado como root, você não precisará do sudo. Se o script não estiver sendo executado como root, dê ao usuário que está executando o script a permissão para executar
sudo reboot
sem fornecer uma senha. Executevisudo
e adicione a seguinte linha:Observe que, se houver uma entrada para o mesmo usuário no arquivo sudoers que exija uma senha, a
NOPASSWD
entrada deverá ser posterior.Depois de iniciar uma reinicialização, você não precisa interromper o ciclo, o sistema será interrompido de qualquer maneira.
Se você decidir continuar usando esse script de shell, e sua versão
gpio
for muito antiga para ter owfi
subcomando, aqui está uma versão aprimorada que verifica apenas o estado do botão a cada segundo. Observe que, como o pino é lido apenas uma vez por segundo, isso significa que você deve manter o botão pressionado por pelo menos um segundo para garantir que o evento seja selecionado.fonte
0.1
ou talvez0.2
seja capaz de detectar pressões muito curtas e ainda deixar bastante tempo de CPU para outros threads.sleep(1)
a aceitação de um número fracionário de segundos não é padrão.gpio wfi 0 rising
esperaria uma borda ascendente no pino zero, que não está ocupada (de acordo com o site de fiação pi ).O que você tem é conhecido como um loop ocupado . Seu loop não consumirá quase nenhuma memória, mas consumirá bastante CPU. Isso geralmente é atenuado pela adição
sleep
ao corpo do loop.Livrar-se do loop ocupado depende do que
gpio
faz. Existem chamadas de sistema comoselect()
, que podem bloquear até que um descritor de arquivo esteja pronto.Quanto à eficiência,
()
otrue
comando around é executadotrue
em um subshell. Isso não é necessário e pode ser melhor expresso com o seguinte:fonte
Tente o seguinte:
fonte