Perbedaan antara Interupsi dan pengambilan sampel untuk tombol perangkat keras?


8

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.



Tidak ada yang salah dengan pengambilan sampel di loop utama, jika Anda bereaksi dalam loop utama. Interupsi lebih tepat jika Anda ingin bereaksi secara tidak sinkron. Terkadang Anda melakukannya, dan kadang tidak.
Eugene Ryabtsev

Cara terbaik untuk melakukan debounce adalah filter low-pass sederhana.
lucas92

Jawaban:


8

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:

  1. Debouncing dalam perangkat keras analog dapat mencapai hasil yang tidak dapat Anda capai dengan sakelar "yang diamati" hanya secara digital secara berkala dengan polling atau bahkan oleh peristiwa pergantian pin perangkat keras. Tetapi Anda dapat melakukan "cukup baik" untuk semua maksud dan tujuan, secara digital. Hampir tidak seorang pun hari ini menggunakan solusi debouncing analog eksternal. Tapi saya telah menggunakan semuanya mulai dari peregangan pulsa menggunakan satu tembakan (74121) ke teknik yang disebutkan oleh Jack Ganssle di sini .
  2. Bagi mereka yang melakukan pemrograman tertanam saja dan sama sekali tidak tertarik untuk belajar tentang elektronik, switch debouncing mungkin salah satu dari dua set keterampilan dasar yang diperlukan. LED operasi mungkin yang lain. Dan dengan ini, saya tidak bermaksud hanya memiliki satu keterampilan dalam hal ini. Maksud saya bisa melakukannya dalam beberapa cara. Jadi, Anda benar - benar perlu memahami sepenuhnya apa yang ditulis Jack Ganssle, dan lebih lagi, tentang sakelar.

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:

skema

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 (biasanya8MSjika 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:

.equ    SWPORTPINS  =   PINB
.def    SwRawCurr   =   r4
.def    SwRawPrev   =   r5
.def    SwState     =   r6
.def    SwDebCurr   =   r7
.def    SwDebPrev   =   r8

            ; Debounce the input switches.

                mov     SwRawPrev, SwRawCurr
                in      SwRawCurr, SWPORTPINS
                mov     Timer0Tmp1, SwRawCurr
                eor     Timer0Tmp1, SwRawPrev
                mov     Timer0Tmp0, Timer0Tmp1
                or      Timer0Tmp1, SwState
                mov     SwState, Timer0Tmp0
                mov     Timer0Tmp0, Timer0Tmp1
                com     Timer0Tmp0
                and     Timer0Tmp1, SwDebCurr
                and     Timer0Tmp0, SwRawCurr
                or      Timer0Tmp1, Timer0Tmp0
                mov     SwDebPrev, SwDebCurr
                mov     SwDebCurr, Timer0Tmp1

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 menggunakan 8MSpengaturan 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 menemukan20MSperiode 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:

  1. ubah dari SETTLED ke CHANGING
  2. ubah dari CHANGING ke SETTLED
  3. tetap dalam SETTLED, memperbarui DILUNCURKAN

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 sampel 8MS berarti di suatu tempat antara 16MS<t24MSuntuk beralih dari tidak aktif ke hasil debounce aktif yang diakui. Dan itu akan membutuhkan yang lain24MSsebelum negara dapat kembali menjadi tidak aktif. Itu minimum40MS<t48MS 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<t120MSuntuk 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.


waktu bouncing bervariasi dari 0 untuk sakelar merkuri hingga "beberapa" ms typ untuk sakelar mikro tactile ke 30ms untuk sakelar sakelar yang kikuk, jadi 8ms adalah angka yang baik mengingat kenaikan waktu pentalan seiring bertambahnya usia.
Tony Stewart Sunnyskyguy EE75

@ TonyStewart.EEsince'75 Saya memilih untuk melakukan pengujian ekstensif dengan pengguna menggunakan peralatan dengan berbagai jenis switch dan angka 8 ms berasal dari distilasi semua yang berfungsi. (Saya tidak terlalu khawatir tentang "teori" sejak praktik membangun dan membuat sakelar, dan keragamannya, membuat pengumpulan dan analisis data itu tampak menakutkan.) Saya selalu menggunakan 8 ms, jika mungkin, karena tampaknya menjadi sweet spot yang diberikan pengalaman panjang menulis perangkat lunak yang hanya bekerja dan di mana keluhan purnajual menjadi nol (pada titik itu, bagaimanapun.)
jonk

@ TonyStewart.EEsince'75 Ngomong-ngomong, pengujian ini TERMASUK penggunaan merkuri dibasahi reed relay sebagai bagian dari saklar kunci yang digunakan di keyboard (yang, saya pikir, sepertinya tidak dibuat lagi.) Dalam kasus ini, meskipun, Saya pergi ke 1-2 ms sampling (tergantung pada unit.)
Jonon

Lampu taman laser yang saya sebutkan satu kali yang lalu .. memiliki sakelar kendali jarak jauh membran taktil dengan waktu pentalan rendah tetapi pemrogram membuatnya beralih pada tingkat 10Hz sehingga seseorang harus melepaskannya dalam <100 ms jika tidak, daya akan menyala. pada catatan lain .. Keyboard piano Yamaha sangat cepat dan mendukung 10 kunci rollover sedangkan hanya keyboard PC IBM asli yang didukung rollover tepi terdepan yang sebenarnya. Sejak saat itu, semua keyboard adalah stroke pertama yang unggul dan kemudian membuntuti rollover tepi yang merupakan PITA untuk keterampilan mengetik yang buruk seperti milik saya
Tony Stewart Sunnyskyguy EE75

@ TonyStewart.EEsince'75 Bidang pengambilan sampel sakelar ini merupakan titik sakit. Munculnya micros murah dengan nol debouncing eksternal dan saklar siapa-tahu-apa yang diterapkan, ditambahkan ke ketidaktahuan programmer tertanam, berarti bahwa saya benar-benar menemukan masalah dengan hampir SETIAP instrumen tertanam SEMUA TUNGGAL dengan tombol atau tombol push. Mereka SEMUA bekerja sangat, dalam pilihan saya. Dan saya pikir itu sebagian besar karena programmer memiliki sedikit atau tanpa pengalaman, hanya 'google it up and apply it' tanpa berpikir. Kadang-kadang, salting kode mereka dengan titik pemungutan suara acak, bahkan. Ini sampah. Menjengkelkan. Sangat mudah untuk mendapatkan yang benar.
jonk

5

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.

  • misalnya 100k pullup dan 0,1μF lintas switch = 10ms @ 63% atau ~ 8ms pada 50% Vdd atau jika menggunakan gerbang Schmitt Trigger @ 1.33V = Vil dari 5V atau ~ 73% V + ~ 12ms

4

Untuk membuat bo-bounce SW, catat timestamp acara saat ini dan periksa penundaan dari acara yang valid terakhir:

#define DELAY_DEBOUNCE       150

uint32_t    __ts_lastpress = 0;

ISR(some_vector)
{
    uint32_t    now = millis(); // some timer tick counter

    if ( now - __ts_lastpress < DELAY_DEBOUNCE )
        return; // ignore it

    __ts_lastpress = now;
    // do the job here
}

UPD: dengan sedikit modifikasi Anda dapat mendaftar klik dua kali:

#define DELAY_DEBOUNCE       150
#define DELAY_DOUBLE_CLICK   600

uint32_t    __ts_lastpress = 0;

ISR(some_vector)
{
    uint32_t    now = millis(); // some timer tick counter

    if ( now - __ts_lastpress < DELAY_DEBOUNCE )
        return; // ignore it

    // do the job here
    if ( now - __ts_lastpress < DELAY_DOUBLE_CLICK )
    {
        // it is double click
    }
    else
    {
        // it is single click
    }

    __ts_lastpress = now;
}

2

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.


1

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.

skema

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 (RC atau 10kΩ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


1
Baik versi berfungsi untuk + ve atau -ve edge, terutama jika pin interrupt memiliki karakteristik input gaya schmitt (banyak yang melakukannya). Baik SW1 & SW2 mengalami lonjakan saat ini ketika menutup. Beberapa tombol karbon mungkin memberikan hasil yang berbeda dari tombol logam-kubah.
glen_geek

1

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!

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.