Saya telah membuat skrip mini untuk mem-boot ulang Raspberry Pi saya dengan menekan satu tombol. Script hanya menggunakan wiringPi (perintah gpio) untuk mengatur pin 0 (pin 17 dalam urutan penomoran Raspberry Pi standar) untuk memasukkan, dan kemudian membaca nilainya sampai satu (ketika tombol ditekan atau ditekan).
Ini skrip saya:
gpio mode 0 in
while (true)
do
if [ `gpio read 0` -eq 1 ]
then
echo password | sudo -S reboot
break
fi
done &
Script berfungsi dengan baik dan semuanya.
Namun, bagi Anda yang tidak terbiasa dengan Pi, ia datang dengan sumber daya perangkat keras yang sangat terbatas (termasuk memori 512 MB) yang dapat dengan mudah dikonsumsi oleh loop seperti yang saya gunakan.
Apa yang saya coba capai di sini adalah menemukan cara lain untuk bash untuk mengetahui kapan nilainya telah berubah dari 0
menjadi 1
tanpa harus mendedikasikan lebih seperti loop tanpa syarat untuk itu. Apakah ini bisa dilakukan? Silakan bagikan ide Anda.
sumber
Jawaban:
Analisis dan solusi modern
Script adalah loop sibuk: ia terus membaca pin GPIO berulang kali. Tidak memakan banyak memori tetapi membuat CPU sibuk.
Anda harus mengatur pin GPIO dalam mode tepi. The
gpio
utilitas memilikiwfi
(menunggu interrupt) perintah yang dapat Anda gunakan untuk bereaksi terhadap pemicu tepi. (gpio wfi
Tidak ada kembali ketika pertanyaan diajukan.)Solusi Python
Ada perpustakaan Python untuk akses GPIO , yang mendukung mode tepi. Berikut adalah beberapa kode Python yang belum teruji yang harus melakukan apa yang Anda inginkan.
Kiat shell tambahan
(true)
bisa dituliskan sajatrue
. Kurung membuat subproses, yang sama sekali tidak perlu.`gpio read 0`
harus dalam tanda kutip ganda. Tanpa tanda kutip, output perintah diperlakukan sebagai daftar pola wildcard nama file. Dengan tanda kutip ganda, output dari perintah diperlakukan sebagai string. Selalu beri tanda kutip ganda di sekitar pergantian perintah dan pergantian variabel:"$(some_command)"
,"$some_variable"
. Juga, Anda harus menggunakan sintaks$(…)
daripada`…`
: itu memiliki arti yang persis sama, tetapi sintaks backquote memiliki beberapa kebiasaan parsing ketika perintah kompleks. Jadi:if [ "$(gpio read 0)" -eq 1 ]
Jangan letakkan kata sandi root di skrip. Jika skrip berjalan sebagai root, Anda tidak perlu sudo sama sekali. Jika skrip tidak berjalan sebagai root, maka beri pengguna izin menjalankan skrip
sudo reboot
tanpa memberikan kata sandi. Jalankanvisudo
dan tambahkan baris berikut:Perhatikan bahwa jika ada entri untuk pengguna yang sama dalam file sudoers yang memerlukan kata sandi,
NOPASSWD
entri tersebut harus muncul setelah itu.Setelah Anda memicu reboot, Anda tidak perlu memutus loop, sistem akan tetap berhenti.
Jika Anda memutuskan untuk tetap menggunakan skrip shell ini, dan versi Anda
gpio
terlalu tua untuk memilikiwfi
sub- perintah , inilah versi yang disempurnakan yang hanya memeriksa status tombol setiap detik. Perhatikan bahwa karena pin hanya dibaca sekali per detik, ini berarti Anda harus terus menekan tombol setidaknya selama satu detik untuk memastikan bahwa acara tersebut diambil.sumber
0.1
atau mungkin0.2
harus dapat mendeteksi penekanan yang sangat singkat dan masih menyisakan banyak waktu CPU untuk utas lainnya.sleep(1)
penerimaan fraksional detik tidak standar.gpio wfi 0 rising
akan menunggu kenaikan tepi pada pin nol, yang tidak sibuk (menurut situs pi kabel ).Apa yang Anda miliki dikenal sebagai loop sibuk . Loop Anda tidak akan menghabiskan hampir semua memori, tetapi akan mengkonsumsi banyak CPU. Ini biasanya dikurangi dengan menambahkan
sleep
ke tubuh loop.Menyingkirkan loop yang sibuk akan tergantung pada apa yang
gpio
dilakukan. Ada panggilan sistem sepertiselect()
, yang dapat memblokir hingga deskriptor file siap.Sejauh efisiensi, perintah
()
di sekitartrue
sebenarnya dijalankantrue
dalam subkulit. Ini tidak diperlukan, dan dapat diungkapkan dengan lebih baik dengan yang berikut:sumber
Coba yang berikut ini:
sumber