Saya memiliki tombol perangkat keras yang terhubung ke interupsi, tetapi masalah saya adalah memantul sedikit, membuat tombol tekan tidak dapat diandalkan. Saya pikir banyak masalah ini akan diselesaikan dengan pengambilan sampel di loop utama, tetapi itu hanya terasa salah secara teknis.
Apakah interupsi lebih tepat untuk komunikasi intra-sirkuit atau apakah interupsi juga sesuai untuk sakelar perangkat keras? Jika demikian, teknik debounce apa yang dapat saya gunakan?
Saya sudah mencoba membuat variabel timer dan mengeceknya dengan waktu saat ini, penundaan, dan teknik lainnya. Sepertinya pantulannya begitu cepat tidak masalah.
interrupts
button
sampling
OneChillDude
sumber
sumber
Jawaban:
Debouncing adalah FAQ. Anda harus dapat menemukan ... hampir tidak terbatas jumlah halaman web pada topik tersebut. Smith berkomentar tentang Jack Ganssle yang banyak membaca PDF tentang topik ini, juga. Dan dengan semua jawaban ini Anda memiliki metode perangkat keras dan perangkat lunak.
Saya akan menambahkan "literatur" ini sedikit dengan hanya berbicara tentang ide-ide yang belum dibahas dengan baik. Tetapi sebelum saya melakukannya, satu atau dua poin:
Karena saya telah menyebutkan peregangan pulsa menggunakan 74121 dan karena Jack Ganssle tidak menyebutkannya, dan juga belum ada orang di sini, saya mungkin juga menyediakan tautan tambahan ini sebagai bacaan tambahan yang disarankan tentang penggunaan 74121 atau 555 sebagai satu suntikan penghitung waktu untuk sakelar debouncing.
Sekarang, lanjutkan melakukan ini melalui pengamatan dengan mikrokontroler.
Saya biasanya menggunakan mesin negara untuk menangani debouncing. Ini hampir selalu didorong oleh timer "detak jantung" reguler yang saya atur8MS , jika memungkinkan. (Saya biasanya TIDAK menggunakan peristiwa interupsi yang dipicu oleh tepi karena beberapa alasan.)
Mesin negara terlihat seperti ini:
mensimulasikan rangkaian ini - Skema dibuat menggunakan CircuitLab
Nilai DEBOUNCED untuk switch dapat mengambil nilai "tidak aktif", "aktif", dan "tidak dikenal". Dengan cara ini, Anda dapat memastikan bahwa perangkat lunak Anda menunggu hingga nilai sakelar turun setelah inisialisasi. Tapi biasanya, saya tidak repot dengan itu. Saya mengganti nilai "tidak dikenal" dengan beberapa nilai default dan sebagai gantinya hanya menggunakan sistem nilai biner.
Mesin negara dimasukkan dengan terlebih dahulu mengatur nilai yang didebok ke standarnya dan kemudian memasukkan status "MENGUBAH" mesin negara. Pada setiap interval waktu (biasanya8MS jika saya bisa lolos begitu saja), saya akan membaca nilai sakelar saat ini dan melakukan pembaruan dari keadaan saat ini dan mungkin, nilai yang dilepaskan. Lalu aku keluar begitu saja. Kode tingkat tinggi kemudian hanya mengakses negara yang didebok.
Jika itu penting bagi saya, saya juga dapat mempertahankan status debouncing sebelumnya. Dalam kasus ini, saat memperbarui status yang didebok itu sendiri, saya pertama-tama akan menyalin status itu ke 'kondisi yang sebelumnya didebok'. Saya kemudian dapat menggunakan pasangan nilai untuk menentukan apakah telah ada transisi yang dilepaskan. Terkadang, saya tidak peduli dengan transisi. Terkadang saya melakukannya. Jadi itu tergantung. Tetapi dalam semua kasus, saya hanya ingin tahu tentang transisi yang telah ditolak. Aku tidak pernah peduli kerdil transisi. Jadi kode tingkat tinggi tidak pernah menggunakan status internal apa pun yang digunakan mesin negara untuk pekerjaannya sendiri.
Salah satu hal yang menyenangkan tentang metode ini adalah saya dapat menghapus seluruh port switch secara bersamaan. Dan saya bisa melakukannya tanpa satu cabang pun dalam kode interupsi juga. Ini berarti kode debouncing yang sangat cepat dan pendek hingga lebar port mikrokontroler (biasanya 8 bit.) Contoh dari Atmel AT90 menunjukkan bagaimana hal ini dicapai menggunakan acara interupsi Timer0:
Sekarang, contoh ini menunjukkan kesepakatan penuh, termasuk nilai sakelar yang dideboisasi sebelumnya dan saat ini. Dan itu melakukan semua transisi negara yang diperlukan, juga. Saya tidak menunjukkan inisialisasi kode ini. Tetapi di atas mendapatkan titik tentang betapa mudahnya mesin negara untuk beroperasi dan betapa sedikit kode yang diperlukan untuk melakukannya. Ini cukup cepat dan sederhana dan tidak memerlukan percabangan (yang terkadang melibatkan siklus tambahan serta ruang kode tambahan.)
Saya lebih suka menggunakan8MS pengaturan waktu karena pengujian yang sangat lama dengan berbagai orang yang menggunakan peralatan yang pernah saya kerjakan di masa lalu telah membawa saya ke sana. Saya sudah mencoba periode yang lebih lama dan ketika saya melakukannya, saya mulai membuat orang mengatakan kepada saya bahwa "responsif" tidak cukup "cepat". (Saat ini, dengan anak-anak yang tumbuh dengan bekerja secara real-time "shoot 'em" gaming, saya mungkin akan mempersingkatnya lebih jauh. Mereka akan mengeluh dengan sangat pahit tentang bahkan sedikit keterlambatan yang disebabkan oleh TV digital modern dalam mengatur dan menampilkan bingkai.)
Beberapa orang akan memiliki perasaan yang sangat jelas tentang seberapa jernih dan responsif suatu sistem seharusnya. Renyah dan responsif berarti sampel lebih sering, bukan lebih sedikit. Tetapi secara pribadi, saya menemukan20MS periode observasi dapat diterima. (Aku tidak menemukan waktu yang cukup lama bahkan untukku.)
Harap dicatat bahwa mesin keadaan yang saya sebutkan pertama-tama harus memasukkan keadaan SETTLED dan kemudian tinggal di sana untuk satu waktu sampel lagi sebelum nilai untuk DEBOUNCED diperbarui. Jadi menekan sebuah tombol dan menahannya, bahkan dalam keadaan terbaik, akan memerlukan transisi ini:
Jadi keadaan debounce baru membutuhkan minimal 3 periode waktu sampel untuk mencapai.
Sebuah tombol akan memerlukan setidaknya 6 kali sampel untuk beralih dari tidak aktif, ke aktif, dan kemudian kembali ke tidak aktif.
Saya menyebutkan detail di atas sehingga sangat jelas bahwa waktu sampel8MS berarti di suatu tempat antara 16ms <t≤24MS untuk beralih dari tidak aktif ke hasil debounce aktif yang diakui. Dan itu akan membutuhkan yang lain24MS sebelum negara dapat kembali menjadi tidak aktif. Itu minimum40ms <t≤48MS untuk melewati seluruh siklus tombol tekan.
Menggunakan waktu sampel yang lebih lama akan memiliki periode yang lebih lama. Menggunakan20MS Saya disebutkan sebagai "dapat diterima" bagi saya sudah berarti di suatu tempat di sekitar 100ms <t≤120MS untuk seluruh siklus tombol tekan. Dan yang semakin tepat sampai ke daerah di mana orang yang cenderung pemberitahuan. Saya tentu tidak suka "perasaan" jika itu lebih lama dari itu.
Jika Anda menggunakan rute ini, jangan menjadi angkuh tentang penggunaan waktu sampel yang lebih lama. Jika harus, maka saya pikir Anda juga harus melakukan banyak pengujian dengan pengguna / konsumen.
Dan jika Anda mengembangkan kode untuk mengetik keyboard, maka gunakan waktu yang lebih singkat. Catatan untuk juru ketik ditetapkan puluhan tahun yang lalu pada 217 wpm. Ini menghasilkan sekitar satu kunci setiap45MS . Pengetik seperti itu menekan beberapa kunci dalam urutan yang terkontrol. Untuk mendapatkan kinerja yang baik untuk juru ketik yang sangat cepat menggunakan sistem switching relay reed mercury-wetted, saya menemukan itu2MS bekerja dengan baik.
sumber
Debounce dapat dilakukan dalam perangkat lunak dengan menutupi IRQ untuk waktu bouncing atau dalam perangkat keras dengan menambahkan kapasitor penahan dengan RC Anda = T> waktu bouncing mulai dari 1 hingga 15 ms tergantung pada ukuran sakelar.
sumber
Untuk membuat bo-bounce SW, catat timestamp acara saat ini dan periksa penundaan dari acara yang valid terakhir:
UPD: dengan sedikit modifikasi Anda dapat mendaftar klik dua kali:
sumber
Interupsi pasti bagus untuk sakelar perangkat keras juga. Dengan menggunakan interupsi, Anda menghindari pemborosan besar sumber daya dan energi, terutama jika Anda berurusan dengan perangkat bertenaga baterai.
Selain itu, ketika kode Anda semakin besar dan lebih besar, Anda akan melihat bahwa lebih mudah untuk mengimplementasikan interupsi untuk tombol daripada melakukan polling pada loop utama Anda.
Adapun debouncing Anda, mungkin itu adalah masalah pengkodean. Saya biasanya menggunakan timer ~ 10 ms untuk debouncing, sambil memeriksa pelepasan tombol. Pastikan juga untuk sementara menonaktifkan tombol interupsi saat Anda melakukan debounce, sehingga rutin interupsi tidak dijalankan beberapa kali.
Jika Anda masih mengalami masalah, kirim kodenya di sini, sehingga kami dapat membantu.
sumber
Ini sangat mirip dengan Jawaban Tony Stewart, tetapi saya pikir itu bisa diperluas beberapa.
Skema atas adalah untuk interupsi pada low atau pada edge jatuh. Skema bawah adalah untuk interupsi di tepi tinggi atau naik.
mensimulasikan rangkaian ini - Skema dibuat menggunakan CircuitLab
secara pribadi, mengingat biaya kapasitor, sangat berharga bagi saya untuk hanya menggunakannya, daripada khawatir jika perangkat lunak saya melonggarkan buggy.
Perhatikan bahwa seperti yang dikatakan Tony Stewart, konstanta waktu di sirkuit ini adalah 10 ms( R ∗ C atau 10 k Ω ∗ 1 μ F) . Ini akan memakan waktu dari tiga hingga lima konstanta waktu (tergantung pada sensitivitas mikrokontroler Anda untuk tombol untuk mengatur ulang sendiri, jadi jika mikrokontroler Anda memiliki masalah dengan pengulangan fungsi interupsi, itu mungkin penyebabnya, dan Anda mungkin perlu sesuaikan tutup / resistor untuk membuat interupsi tidak terjadi berulang kali (Yaitu, hanya jika interupsi Anda diatur untuk bekerja pada sinyal tinggi atau rendah, dan bukan tepi naik atau turun.
Terkait dengan Hardware debouncing
sumber
Manusia lambat, kita tidak perlu perhatian segera dari mikro yang berada dalam kisaran mikrodetik.
Ini bukan, tentu saja, satu-satunya atau cara yang tepat untuk selalu melakukannya tetapi saya menemukan umumnya lebih masuk akal untuk mengatur timer (banyak mikro memiliki kutu sistem) untuk menyalakan interupsi pada interval tetap dan menggeser status pin ke dalam variabel untuk kode untuk diperiksa nanti. Anda berakhir dengan var yang penuh abu saat memantul
10010110 abu
tapi pada titik-titik tertentu dalam waktu Anda akan mendapatkan 4 nilai-nilai ini:
01.111.111 sisi kenaikan hanya debounced
11111111 tombol dalam kondisi mapan up
10000000 jatuh tepi hanya debounced
mendebol tombol 00000000 dalam kondisi mantap ke bawah
Namun, sebagian besar waktu, saya hanya menggunakan penghitung yang me-reset saat memantul. Ini cepat, teruji, dan mudah dilakukan.
Jika gagal maka saya mencoba sesuatu yang lebih pintar dari dokumen Ganssle yang disarankan orang lain!
sumber