Peningkatan Pengekodan Arduino Rotary Encoder

Encoder berputar adalah alat masukan yang hebat untuk projek-projek elektronik - diharapkan Pengajaran ini akan memberi inspirasi dan membantu anda menggunakan satu dalam projek anda yang seterusnya.

Mengapa menulis kod pengekod berputar?

Saya mahu menggunakan pengekod berputar kos rendah kerana mekanisme masukan untuk salah satu projek saya yang akan datang dan pada mulanya dibingungkan oleh pilihan kod yang tersedia untuk mengambil bacaan dari pengekod putar dan menentukan berapa banyak "pengesan" atau kitaran pengekod yang telah diklik lalu dan dalam apa arah. Saya rasa lakaran utama saya perlu menggunakan sebahagian besar memori Arduino saya supaya saya mengelakkan pelbagai perpustakaan pengekod yang tersedia, yang sepertinya sukar untuk membuat kerja apabila saya mencuba beberapa daripada mereka. Mereka juga kelihatan menggunakan lebih banyak kod anggaran daripada pendekatan kod berasaskan lakaran yang dibincangkan dari sini.

Jika anda hanya mahu memintas pemikiran di belakang pendekatan saya dan terus ke dalam Instructable, jangan ragu untuk melangkah ke Langkah 1!

Pendekatan lain

Beberapa pendekatan berasaskan lakaran utama (iaitu mereka tidak menggunakan perpustakaan) dibincangkan dalam catatan blog rt di mana mereka menulis kod pengekod berputar yang menjadikan pengekod termurah yang boleh digunakan sebagai input Arduino. Mereka juga mempunyai contoh yang baik tentang isyarat logik yang dihasilkan oleh pengekod. rt mendapati bahawa sistem interrupt timer berfungsi paling baik untuk mereka tetapi saya khawatir bahawa kekerapan pengundian akan mengurangkan kelajuan kemas kini skrin dalam gelung utama lakaran projek saya. Memandangkan pengekod berputar akan bergerak untuk bahagian kecil masa yang saya mahu skrin mengemas kini, ini sepertinya perlawanan yang kurang baik untuk permohonan saya.

Saya memilih untuk memulakan menggunakan kod Steve Spence di sini, yang baik tetapi ia kelihatan sangat perlahan apabila saya memasukkan keseluruhan kod lakaran saya (yang melibatkan penulisan kemas kini paparan ke skrin TFT kecil). Pada mulanya saya tertanya-tanya apakah itu mungkin kerana gelung utama mengandungi pernyataan debounce.

Saya kemudian membaca artikel pengekod berputar Oleg pada versi rutin perkhidmatan interupsi jawatan terdahulu, saya juga fikir ia mungkin idea yang baik untuk menggunakan manipulasi pelabuhan langsung untuk membaca kedua-dua pin secara bersamaan dan sebaik sahaja kebakaran mengganggu. Kodnya boleh digunakan pada sebarang pin input jika kod manipulasi pelabuhan ditulis semula. Sebaliknya, saya memutuskan untuk menggunakan hanya sekatan perkakasan pada pin digital 2 dan 3, jadi kita boleh menetapkan gangguan untuk hanya menyala pada pinggir yang semakin meningkat daripada voltan pin, bukannya pada perubahan voltan pin, yang termasuk tepi yang jatuh. Ini mengurangkan bilangan kali ISR ​​dipanggil, mengganggu dari gelung utama.

Kod Oleg menggunakan jadual carian untuk mengurangkan saiz kod terkompilasi kepada saiz yang sangat kecil tetapi saya tidak dapat mendapatkan hasil yang boleh dipercayai yang akan menangkap putaran yang sangat perlahan serta putaran yang agak pantas. Perlu diingatkan bahawa perkakasan keras (lihat Langkah 2) boleh membantu banyak dengan kebolehpercayaan pembacaan tetapi saya selepas penyelesaian perisian untuk mempermudah membina perkakasan dan menjadi mudah alih kepada aplikasi perkakasan lain yang mungkin.

Ini menyimpulkan pengenalan cabaran dan pertimbangan saya. Di Langkah 2, kita akan melihat perkakasan, pengkomputeran dan beberapa pengekodan praktikal apabila anda ingin mengintegrasikan pengekod berputar ke dalam projek anda.

Langkah 1: Bit Mengenai Pengekod Rotary

Kenapa encoders putar begitu keren?

  1. Tidak seperti resistor berputar / potensiometer mereka mempunyai perjalanan tak terhingga di mana-mana arah dan kerana mereka menghasilkan digital "Kod kelabu", anda boleh skala pembacaan mereka kepada julat yang anda suka.
  2. Arah dua menjadikan mereka berguna untuk meningkatkan atau mengurangkan nilai dalam menu pemboleh ubah atau navigasi.
  3. Akhirnya, kebanyakan pengekod putar ini mempunyai butang tekan pusat, yang boleh digunakan untuk memilih item menu, menetapkan semula kaunter atau melakukan apa sahaja yang anda boleh fikirkan yang mungkin sesuai dengan butang tekan yang seketika.

Terma

  1. PPR: denyutan setiap pusingan - biasanya 12, 20 atau 24. Anda juga mungkin melihat spesifikasi untuk putaran maksimum dalam rpm dan lain-lain. Ini mungkin ditentukan oleh kecenderungan pengekod untuk melantun kenalan - lihat di bawah.
  2. Detent: klik sedikit tindakan itu kerana ia memunculkan titik rehat semulajadi antara denyutan. Mungkin ada satu deten per nadi / kitaran (tidak sama dengan putaran aci) atau dua.
  3. Bouncing: kenalan mekanikal di dalam pengekod secara literal melantun cukup untuk melompat dan kembali pada sentuhan apabila berputar, berpotensi membawa kepada terlalu banyak pembacaan disebabkan oleh fasa perjalanan antara penahan.
  4. Debounce: Ini boleh dilakukan dalam perkakasan, mungkin dengan kapasitor seramik nilai rendah antara setiap pin dan Ground, atau dalam perisian, mungkin dengan penangguhan. Dalam kedua-dua kes, matlamatnya adalah untuk mewujudkan sistem yang mengabaikan hubungan memantul.

Petua

  1. Cari bahagian sekeliling yang dekat dengan pangkal batang dan kacang sepadan jika anda mahu memasang pengekod anda dalam panel atau kandang.
  2. Banyak tombol tersedia untuk pengekod putar, dengan yang paling mudah tersedia di dalam aci diameter 6mm.
  3. Beri perhatian sama ada aci pengekod anda menggunakan muka rata atau splin untuk mencapai patut yang sesuai dengan tombol.
  4. Badan encoder berputar mungkin juga dilengkapi dengan pin / stub yang dibangkitkan, bertujuan untuk mengaitkan dengan indent / lubang kecil di panel anda (mungkin tersembunyi oleh tombol anda) dan mencegah encoder anda dari berputar ketika anda menghidupkan tombol. Anda mungkin mendapati anda ingin mengeluarkan ini jika anda boleh membuat geseran yang mencukupi untuk mengelakkan putaran badan pengekod menggunakan bolt pemasangan untuk mengikis pengekod dalam panel atau kandang.
  5. Pastikan anda mengetahui di mana keadaan tahanan adalah untuk encoder anda dan menyesuaikan kod anda dengan sewajarnya. Contoh saya menggunakan encoder yang pin kedua-duanya terputus dari tanah dan ditarik tinggi oleh perintang pullup input masing-masing. Ini mendorong saya memilih satu gangguan RISING. Sekiranya kedua-dua pin disambungkan ke tanah apabila ditahan, mereka memerlukan kod yang sedang mencari voltan pin FALLING.

Langkah 2: Litar

Litar sangat mudah. Anda perlu:



• Arduino berasaskan ATMEGA328P, seperti Uno, Pro Mini atau Nano.
• Pengekod kuadratik mekanik (berbanding dengan optik) - ini adalah jenis yang paling biasa jadi jangan terlalu risau jika tidak dinyatakan. Penyenaraian eBay dan Aliexpress sering menyebut Arduino dalam keterangannya dan ini merupakan penunjuk yang baik yang sesuai.
• Kawalan dawai / jumper.
• Pilihan: papan pemancingan prototaip.


Pertama sekali, cari kumpulan tiga pin di satu sisi pengekod. Ini adalah tiga untuk mengukur putaran dengan kod kami. Sekiranya terdapat dua pin bersama-sama di sisi lain, ini mungkin untuk butang pusat tekan. Kami akan mengabaikannya sekarang.

Daripada tiga pin bersama-sama, pin tanah pengekod disambungkan ke pin tanah Arduino. Sama ada dua pin lain disambungkan ke pin digital 2 dan selebihnya disambungkan ke pin digital 3. Jika arah putaran anda tidak seperti yang anda mahu, tukar dua pin bukan tanah.

Pins 2 dan 3 adalah penting kerana pada arduinos berasaskan ATMEGA328P mereka adalah satu-satunya pin yang mempunyai keupayaan untuk mengesan penggantian pin perubahan RISING dan FALLING. Papan MEGA 2560 dan lain-lain mempunyai pin gangguan perkakasan lain yang boleh melakukan ini.

Nota: Di dalam rajah pin tanah adalah salah satu pin utama. Pada hakikatnya, pin tanah sering menjadi pin tengah tetapi ini tidak selalu berlaku jadi membaca lembaran data atau menguji encoder anda untuk mengetahui pin mana yang digunakan.

Nota lain: ArneTR memberikan komen yang baik tentang tidak mempunyai sambungan kabel secara berasingan kepada voltan positif logik (contohnya 5V atau 3.3V) untuk litar pengekod putar yang ditunjukkan. Arduino tidak dapat membaca pengekod putar tanpa kedua-dua isyarat tanah (yang kita telah menyambung wayar ke) dan voltan logik (kadang-kala dijelaskan sebagai Vcc atau Vdd), jadi bagaimana Arduino membaca logik dari pengekod ini tanpa positif wayar voltan? Jawapannya ialah cip ATMEGA328P di Arduino mempunyai mod khas yang boleh anda tetapkan pada pin digital (yang kami gunakan) di mana pin secara automatik menarik "tinggi" kepada voltan logik oleh perintang dalaman. Lihatlah kod untuk "pinMode (pinX, INPUT_PULLUP)" untuk melihat kami memberitahu Arduino bahawa kami ingin memanfaatkan mod ini. Setelah ditetapkan, kami hanya perlu menyediakan pengekod dengan dawai tanah sebagai wayar penginderaan dari pin digital sudah menyediakan voltan logik.

SATU LAGI ... Githyuk mendapati bahawa pengekod bermerek tertentu tidak berfungsi dengan cara ini melakukan perkara (iaitu kod di bawah). Sila lihat seksyen komen untuk butiran tetapi secara umum, cuba pengekod yang berbeza akan menjadi langkah debugging yang baik apabila anda telah habis langkah lebih mudah / lebih cepat / lebih murah.

Langkah 3: Kod

Jika anda tidak biasa dengan Arduinos pengaturcaraan, sila dapatkan kelajuan dengan sumber ini dari Arduino sendiri.

Kod ini adalah percuma untuk kegunaan anda (seperti kos dan tidak diubah seperti yang anda lakukan), atribut di mana anda perlu.


/ ******* Lukisan Pengekod Rotary Encoder berasaskan *******
oleh Simon Merrett, berdasarkan pandangan dari Oleg Mazurov, Nick Gammon, rt, Steve Spence
* /

statik int pinA = 2; / // Pin peranti pintar pertama kami ialah pin digital 2
statik int pinB = 3; // Pin gangguan pintar kedua kami adalah pin digital 3
volatile byte aFlag = 0; // mari kita ketahui apabila kita menjangkakan kelebihan yang meningkat di pinA untuk memberi isyarat bahawa encoder telah tiba di penjara
bait yang tidak menentu bFlag = 0; // mari kita ketahui apabila kita menjangkakan kelebihan yang semakin meningkat pada pinB untuk memberi isyarat bahawa pengekod telah tiba di penahanan (arah bertentangan dengan apabila aFlag ditetapkan)
encoderPop = 0; / / pembolehubah ini menyimpan nilai semasa kami pengekod posisi. Ubah ke int atau uin16_t bukan bait jika anda mahu merakam julat yang lebih besar daripada 0-255
volatile byte oldEncPos = 0; // menyimpan nilai kedudukan pengekod terakhir sehingga kita dapat membandingkan dengan bacaan semasa dan melihat apakah ia telah berubah (jadi kita tahu bila hendak mencetak ke monitor siri)
baca bacaan yang tidak menentu = 0; // tempat untuk menyimpan nilai langsung yang kita baca dari pin gangguan kami sebelum memeriksa untuk melihat apakah kami telah memindahkan penahanan keseluruhan

void setup () {
pinMode (pinA, INPUT_PULLUP); // set pinA sebagai input, ditarik TINGGI ke voltan logik (5V atau 3.3V untuk kebanyakan kes)
pinMode (pinB, INPUT_PULLUP); // set pinB sebagai input, ditarik TINGGI ke voltan logik (5V atau 3.3V untuk kebanyakan kes)
attachInterrupt (0, PinA, RISING); // menetapkan gangguan pada PinA, mencari isyarat yang semakin meningkat dan melaksanakan Rutin Perkhidmatan Interrupt "PinA" (di bawah)
lampirkanInterrupt (1, PinB, RISING); // menetapkan gangguan pada PinB, mencari isyarat yang semakin meningkat dan melaksanakan Rutin Perkhidmatan Interrupt "PinB" (di bawah)
Serial.begin (115200); // mulakan pautan monitor siri
}

tidak sah PinA () {
cli (); / / hentikan interupsi sebelum kita membaca nilai pin
membaca = PIND & 0xC; / / baca semua lapan nilai pin kemudian hapus semua nilai pinA dan pinB
jika (membaca == B00001100 && aFlag) {// semak bahawa kita mempunyai kedua-dua pin pada penahanan (HIGH) dan bahawa kita menjangkakan penahanan pada kelebihan pin ini
encoderPos -; // Mengurangkan kiraan posisi pengekod
bFlag = 0; / // menaikkan bendera untuk giliran seterusnya
aFlag = 0; / // menaikkan bendera untuk giliran seterusnya
}
lain jika (membaca == B00000100) bFlag = 1; / isyarat bahawa kami menjangkakan pinB untuk menandakan peralihan untuk menahan dari putaran bebas
sei (); / / restart interrupts
}

tidak sah PinB () {
cli (); / / hentikan interupsi sebelum kita membaca nilai pin
membaca = PIND & 0xC; / / baca semua lapan nilai pin kemudian hapus semua nilai pinA dan pinB
jika (membaca == B00001100 && bFlag) {// semak bahawa kita mempunyai kedua-dua pin di detent (HIGH) dan bahawa kita menjangkakan penahanan pada kelebihan pin ini
encoderPos ++; // tambah bilangan penghitung pengekod
bFlag = 0; / // menaikkan bendera untuk giliran seterusnya
aFlag = 0; / // menaikkan bendera untuk giliran seterusnya
}
lain jika (membaca == B00001000) aFlag = 1; / isyarat bahawa kami menjangkakan pinA untuk menandakan peralihan untuk menahan dari putaran bebas
sei (); / / restart interrupts
}

kekosongan gelung () {
jika (oldEncPos! = encoderPos) {
Serial.println (encoderPos);
oldEncPos = encoderPos;
}
}

Itu sahaja!

Lampiran

  • rotaryEncoder.ino Muat turun

Langkah 4: Kesimpulan

Saya harap anda mendapati kod ini berguna untuk projek anda yang seterusnya yang menggunakan pengekod putar atau bahawa ia telah memberi inspirasi kepada anda untuk mempertimbangkan pengekod putar sebagai input untuk projek anda yang seterusnya.

Ringkasan Matlamat

Saya telah cuba menulis beberapa kod yang mencapai keseimbangan yang baik:

  • Portability (kod manipulasi pelabuhan adalah kompromi ketika berpindah ke cip lain)
  • Kelajuan (manipulasi pelabuhan sangat membantu)
  • Saiz kod terkompil rendah (manipulasi pelabuhan dan bitmath membantu)
  • Pasti mencatatkan putaran manual perlahan dan cepat
  • Mengurangkan panggilan rutin perkhidmatan penggantian nugatory (menggunakan gangguan RISING dan sementara melumpuhkan gangguan)

Kaedah dan Idea untuk Penambahbaikan

Kod ini tidak sempurna dengan apa-apa cara dan anda mungkin mahu menukarnya menggunakan pin lain. Saya menguji kod ini dengan lakaran yang menyebabkan kelewatan dan pembacaan yang paling tidak boleh dipercayai dengan pendekatan lain yang dibincangkan - saya pastinya tidak membandingkannya dengan pemasa untuk melihat kod mana yang menghasilkan lebih kurang rutin perkhidmatan gangguan pengguguran, mengambil masa yang paling sedikit untuk melaksanakan atau menapis peratusan lonjakan tertinggi. Mungkin seseorang mungkin melakukan ujian penanda aras terhadap pendekatan lain di luar sana.

Artikel Berkaitan