Saat ini, sketsa saya sedang memeriksa pin input setiap kali sepanjang loop utama. Jika mendeteksi perubahan, ia memanggil fungsi khusus untuk meresponsnya. Berikut kodenya (dipangkas hingga yang penting):
int pinValue = LOW;
void pinChanged()
{
//...
}
void setup()
{
pinMode(2, INPUT);
}
void loop()
{
// Read current input
int newValue = digitalRead(2);
// Has the input changed?
if (newValue != pinValue) {
pinValue = newValue;
pinChanged();
}
}
Sayangnya, ini tidak selalu berfungsi dengan baik untuk perubahan yang sangat singkat pada input (mis. Pulsa singkat), terutama jika loop()
berjalan agak lambat.
Apakah ada cara untuk membuat Arduino mendeteksi perubahan input dan memanggil fungsi saya secara otomatis?
Jawaban:
Anda dapat melakukan ini menggunakan interupsi eksternal. Sebagian besar Arduino hanya mendukung ini pada jumlah pin yang terbatas. Untuk detail lengkap, lihat dokumentasi di
attachInterrupt()
.Dengan asumsi Anda menggunakan Uno, Anda bisa melakukannya seperti ini:
Ini akan memanggil
pinChanged()
setiap kali perubahan terdeteksi pada interupsi eksternal 0. Pada Uno, yang sesuai dengan pin GPIO 2. Penomoran interupsi eksternal berbeda pada papan lain, jadi penting untuk memeriksa dokumentasi yang relevan.Namun ada beberapa keterbatasan dalam pendekatan ini. Fungsi kustom
pinChanged()
sedang digunakan sebagai Interrupt Service Routine (ISR). Itu berarti sisa kode (semua yang ada diloop()
) dihentikan sementara saat panggilan sedang dijalankan. Untuk mencegah gangguan pada waktu penting, Anda harus berusaha membuat ISR secepat mungkin.Penting juga untuk dicatat bahwa tidak ada interupsi lain yang berjalan selama ISR Anda. Itu berarti apa pun yang mengandalkan interupsi (seperti inti
delay()
danmillis()
fungsi) mungkin tidak berfungsi dengan baik di dalamnya.Terakhir, jika ISR Anda perlu mengubah variabel global apa pun dalam sketsa, mereka biasanya harus dinyatakan sebagai
volatile
, misalnya:Itu penting karena memberitahu kompiler bahwa nilainya dapat berubah secara tiba-tiba, jadi harus berhati-hati untuk tidak menggunakan salinan / cache yang ketinggalan zaman.
sumber
pinChanged()
harus sesingkat mungkin. Maka biasanya waktu minimum adalah waktu untuk menjalankanpinChanged()
fungsi itu sendiri.volatile
, jika variabel global lebih lebar dari 1 byte, seperti angka berapa pun, Anda harus melindungi terhadap interupsi pin-perubahan yang terjadi antara akses byte oleh program. Pernyataan sepertisomeNumber +=5;
melibatkan menambahkan byte rendah dan menambahkan byte tinggi dengan carry yang disertakan. Kedua (lebih banyak, untuk variabel yang lebih luas) tidak boleh dibagi dengan interupsi. Mematikan interupsi dan mengembalikannya sebelum dan sesudah operasi (masing-masing) sudah cukup.Keadaan perubahan apa pun pada pin yang dikonfigurasi sebagai input digital dapat membuat interupsi. Berbeda dengan vektor unik untuk penyebab interupsi oleh INT1 atau INT2, fitur PinChangeInt menggunakan vektor umum dan kemudian Interrupt Service Routine (alias ISR) untuk vektor ini perlu menentukan pin yang diubah.
Untungnya PinChangeInt Library memudahkan ini.
sumber
Jika Anda ingin mendeteksi tegangan yang melewati ambang batas , alih-alih menjadi TINGGI atau RENDAH, Anda dapat menggunakan komparator analog. Contoh sketsa:
Ini bisa berguna untuk hal-hal seperti detektor cahaya, di mana Anda mungkin perlu mendeteksi perubahan dari (katakanlah) 1V ke 2V pada input.
Contoh rangkaian:
Anda juga dapat menggunakan Unit Pengambilan Input pada prosesor, yang akan mengingat waktu yang tepat dari input tertentu, dengan menyimpan hitungan Timer / Penghitung saat ini. Ini memungkinkan Anda menyimpan momen yang tepat (yah, hampir persis) saat peristiwa minat terjadi, daripada memperkenalkan penundaan (mungkin beberapa mikrodetik) sebelum ISR dapat digunakan untuk menangkap waktu saat ini.
Untuk aplikasi kritis waktu, ini dapat memberikan akurasi yang sedikit meningkat.
Contoh aplikasi: Ubah Arduino Anda menjadi kapasitor tester
sumber