Bantuan atau petunjuk untuk mendekode protokol IR

10

Beberapa waktu lalu saya membeli helikopter mainan kecil yang dikontrol IR yang murah dan sederhana (sama seperti yang ini - disebut "Diamond Gyro" atau "Diamond Force"). Untuk bersenang-senang, saya telah mencari cara mengendalikannya melalui Arduino.

Pembaruan: Mendapat protokolnya; Lihat jawaban

Yang lain telah berbagi hasil tentang meretas helikopter mainan IR yang berbeda dan mendekode protokol IR-nya. Sangat keren, tapi sayangnya helikopter saya menggunakan protokol yang berbeda. Salah satu yang saya tidak tahu. (Saya harus menambahkan bahwa elektronik semata-mata merupakan hobi bagi saya, jadi saya mungkin mengabaikan sesuatu yang sudah jelas).

Sama seperti pada tautan ke-2 di atas, saya mengambil pengontrol terpisah, menemukan pin IC yang mengendalikan LED (tanda IC telah dihapus, by the way), dan menghubungkan penganalisis logika.

Punya banyak data bagus, tapi saya masih belum tahu protokolnya. Situs ini adalah sumber yang bagus, tetapi tidak ada satupun protokol yang terdaftar yang cocok. Dan tidak ada lagi yang saya temukan yang cocok dengan sinyal yang saya tangkap. Namun, saya harus membayangkan bahwa ini adalah protokol sederhana yang tersedia, hanya karena itu adalah mainan kecil yang murah.

Jadi saya menghargai ide yang mungkin Anda miliki. Mungkin saya salah melihatnya.
(Info lebih lanjut di bawah gambar)

Sampel dari saluran A

Karakteristik sinyal / protokol

Saya menangkap ini pada 16MHz dengan controller diatur ke saluran A; harus akurat, tepat waktu. (Ada 3 saluran IR yang dapat Anda pilih, tetapi menggunakan dua saluran lainnya tidak mengubah karakteristik, hanya bagian-bagian dari paket itu sendiri.) Pengaturan waktunya sangat konsisten (+/- 10μs maks). Paket diulangi dengan interval yang bervariasi tetapi minimal berjarak sekitar 100 ms.

Operator: 38kHz @ 50% siklus tugas

Terendah:
- Pendek: 285μs
- Panjang: 795µs

Tertinggi:
- Pendek: 275μs
- Panjang: 855μs

Selalu 17 tertinggi per paket.

Kontrol / input

Heli memiliki 3 kontrol: "Throttle" (yaitu kecepatan angkat / rotor), pitch (maju / belakang), dan yaw (rotasi di sekitar sumbu rotor) semuanya dikontrol dengan 2 thumbsticks. Mereka semua memiliki beberapa jenis jangkauan (tidak hanya on / off) dan sejauh yang saya tahu, semuanya ditransmisikan dalam satu paket. Input kiri / kanan hanya dikirim jika ada sesuatu yang lain dikirim, jadi saya menerapkan kecepatan maksimum ketika mengambil sampel itu. Masukan throttle dan pitch pada paket pemicunya sendiri yang dikirim, segera setelah Anda mendorong ibu jari melewati beberapa ambang batas / deadband (dalam grafik di bawah label "min" adalah untuk paket pertama yang dikirim ketika perlahan-lahan mendorong kontrol melewati deadband-nya).

Ini juga punya tombol untuk memotong kiri & kanan, karena heli itu bukan instrumen presisi ( sama sekali ) dan cenderung berputar lambat jika tidak. Sayangnya tombol trim kiri / kanan sepertinya tidak mengirim sinyal yang menambah / mengurangi sesuatu untuk setiap pers (yang akan berguna untuk mencari protokol); tampaknya hanya perintah tunggal, menyuruh helikopter untuk memotong kiri / kanan, dan kemudian melacaknya.

rev Flambino
sumber
Mengapa tidak menggunakan jejak sinyal yang sudah Anda miliki untuk menuliskan paket-paket mentah?
Ignacio Vazquez-Abrams
@ IgnacioVazquez-Abrams Maksud Anda hanya memutar ulang sinyal yang direkam ke helikopter?
Flambino
Tentu. Ini tidak seperti helikopter akan dapat membedakannya ...
Ignacio Vazquez-Abrams
@ IgnacioVazquez-Abrams Benar tapi sejauh yang saya tahu, paket berisi semua 3 kontrol (throttle / pitch / yaw) dan kontrol heli, tidak ada yang hanya on / off. Untuk mengarahkan hal itu dengan memutar ulang, saya harus menangkap setiap konfigurasi tunggal ... Selain itu saya ingin memahami protokol
Flambino
@ IgnacioVazquez-Abrams Ups, saya entah bagaimana mengacaukan komentar terakhir saya. Dimaksudkan untuk mengatakan: "... paket berisi semua 3 kontrol (throttle / pitch / yaw) dan tidak ada yang hanya on / off".
Flambino

Jawaban:

8

Saya mengambil kebebasan untuk menjawab pertanyaan saya sendiri karena saya mendapatkan sebagian besar jawabannya dan ini adalah cara yang baik untuk berbagi temuan saya. Terima kasih saya kepada Olin Lathrop karena telah memberi saya tempat untuk memulai dan beberapa ide untuk dicoba, tetapi pada akhirnya, protokolnya ternyata sangat berbeda dari dugaan Olin, maka saya memposting jawaban ini.


Pembaruan: Saya memposting pertanyaan tindak lanjut mengenai 8 bit terakhir, yang saya tidak sepenuhnya mengerti, dan Dave Tweed menemukan jawabannya . Saya akan memasukkan detailnya di sini, jadi jawaban ini dapat berfungsi sebagai spesifikasi protokol lengkap, tetapi periksa jawaban Dave.


Saya harus mencoba beberapa hal yang berbeda untuk mendapatkan ini, tetapi saya cukup yakin bahwa saya mendapatkannya. Anehnya, saya belum menemukan sesuatu yang menyerupai protokol ini di tempat lain, tetapi mungkin itu merupakan protokol umum yang tidak saya ketahui.

Bagaimanapun, inilah yang saya temukan:

Protokol / pengkodean

Kedua pulsa dan ruang di antaranya digunakan untuk menyandikan data. Pulsa / spasi panjang adalah biner satu (1), dan pulsa / spasi pendek adalah biner nol (0). Pulsa dikirim menggunakan modulasi inframerah 38kHz konsumen standar @ 50% duty-cycle.

Pengaturan waktu denyut / ruang ada di pertanyaan awal, tapi saya akan mengulanginya di sini untuk kelengkapan:

 Bit    Pulse     Space
-----+---------+---------
  0  |  275µs  |  285µs
  1  |  855µs  |  795µs

Semua ± 10μs maks., ± 5µs typ .. Ini didasarkan pada sampel yang ditangkap dengan penganalisa logika pada 16MHz; Saya tidak memiliki osiloskop, jadi saya tidak tahu profil pastinya (yaitu waktu naik / turun).

Paket diulang selama input kontrol diterapkan dan tampak berjarak minimal 100 ms.

Transmisi paket dimulai dengan pembukaan "pulsa 1", yang diperbaiki dan bukan bagian dari data. Spasi berikut mengkode bit data pertama dari paket, dan pulsa terakhir mengkodekan bit terakhir.

Setiap paket panjangnya 32 bit, dan berisi setiap input yang dapat disediakan oleh kendali jarak jauh. Nilai dibaca sebagai endian kecil, yaitu MSB pertama.

Struktur data

Di bawah ini adalah struktur dasar dari paket individu. 8 bit terakhir membuat saya bingung, tapi itu sudah diketahui sekarang (lihat di bawah).

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2
--+---------------------------+-----------+---+-------+-----------
 P|    Yaw    |   Throttle    |   Pitch   | T | Chan. |   Check

P: Preamble (always a pulse-1), T: Trim, Chan.: Channel

Bit    Length    Description (see note below)
-----------------------------------------------
0      1         Preamble. High 1
1-6    6         Yaw. Range 0-36 for left-right, 17 being neutral
7-14   8         Throttle. Range 0-134
15-20  6         Pitch. Range 0-38 for forward-back, 17 being neutral
21-22  2         Trim. Left = 1, right = 2, no trim = 0
23-26  4         Channel. A = 5, B = 2, C = 8
27-32  6         Check bits

Catatan: Kisaran didasarkan pada pembacaan tertinggi yang saya dapatkan. Protokol ini mampu rentang yang lebih besar - hingga 255 untuk throttle, 63 untuk pitch / yaw - tetapi tutup sekitar setengahnya.
Nilai nada tampaknya memiliki deadband dari 14-21 (termasuk); hanya nilai-nilai di atas atau di bawah yang benar-benar membuat helikopter bereaksi. Saya tidak tahu apakah itu sama untuk menguap (sulit untuk mengatakan, karena helikopter itu tidak stabil, dan mungkin hanya berputar sedikit sendiri).

Ini dalam istilah grafis (bandingkan dengan grafik pada pertanyaan awal)

struktur paket

6 bit cek dihitung dengan XOR'ing semua nilai sebelumnya. Setiap nilai diperlakukan sebagai 6 bit. Ini berarti bahwa 2 MSB dari nilai throttle 8-bit diabaikan begitu saja. Yaitu

check = yaw ^ (throttle & 0x3F) ^ pitch ^ trim ^ channel

Catatan praktis

Pengaturan waktu dan modulasi sinyal tidak harus super akurat. Bahkan timing Arduino saya yang tidak akurat sama sekali bekerja dengan baik meskipun modulasi cerdik dan sedikit hit and miss pada durasi pulsa / ruang dibandingkan dengan remote control yang sebenarnya.

Saya percaya - tetapi belum diuji - bahwa helikopter hanya akan menempel pada saluran sinyal pertama yang ditemukannya. Jika dibiarkan tanpa sinyal terlalu lama (beberapa detik), tampaknya kembali ke mode "pencarian", sampai memperoleh sinyal lagi.

Helikopter akan mengabaikan nilai pitch dan yaw jika throttlenya nol.

Perintah trim dikirim hanya sekali per tombol-tekan pada remote control. Agaknya nilai trim hanya menambah / mengurangi nilai di controller helikopter sendiri; itu bukan sesuatu yang dilacak oleh remote control. Jadi setiap implementasi dari ini mungkin harus tetap berpegang pada skema itu, dan hanya mengirim nilai trim kiri / kanan sesekali, tetapi jika tidak default ke nilai trim nol dalam paket.

Saya sarankan memiliki saklar mematikan yang hanya menetapkan throttle ke nol. Ini akan menyebabkan helikopter jatuh dari langit, tetapi ia akan mengalami kerusakan lebih sedikit ketika tidak memutar motornya. Jadi, jika Anda akan menabrak atau menabrak sesuatu, tekan tombol bunuh untuk menghindari melepaskan gigi atau merusak bilah.

LED IR remote control asli tampaknya memiliki panjang gelombang> 900nm, tapi saya tidak punya masalah menggunakan ~ 850nm LED.

Penerima IR helikopter tidak apa-apa, tetapi tidak super sensitif, jadi semakin terang sumber IR Anda, semakin baik. Remote control menggunakan 3 LED secara seri, duduk di rel 9V bukannya rel 5V yang digunakan oleh logika. Belum memeriksa undian mereka saat ini dengan sangat tepat, tapi saya berani bertaruh itu adalah 50mA.

Contoh data

Berikut adalah banyak paket, untuk siapa saja yang tertarik (ya, saya membuat skrip dekoder; saya tidak mendekodekan semua ini). Paket saluran A berasal dari tangkapan yang sama dengan grafik pada pertanyaan awal.

Channel A                                                       
Yaw     Throttle  Pitch   Tr  Chan  Check     Description
-----------------------------------------------------------
000100  10000100  000000  00  0101  000101    Left Mid + Throttle
000000  10000110  010001  00  0101  010010    Left Max + Throttle 
100001  10000110  000000  00  0101  100010    Right Mid + Throttle 
100100  10000100  010001  00  0101  110100    Right Max + Throttle
010001  00000000  001011  00  0101  011111    Forward Min 
010001  00000000  000000  00  0101  010100    Forward Max 
010001  00000000  011000  00  0101  001100    Back Min 
010001  00000000  100101  00  0101  110001    Back Max
010001  00000000  010001  01  0101  010101    Left Trim 
010001  00000000  010001  10  0101  100101    Right Trim 
010001  00000011  010001  00  0101  000110    Throttle 01 (min)
010001  00010110  010001  00  0101  010011    Throttle 02
010001  00011111  010001  00  0101  011010    Throttle 03
010001  00101111  010001  00  0101  101010    Throttle 04
010001  00111110  010001  00  0101  111011    Throttle 05
010001  01010101  010001  00  0101  010000    Throttle 06
010001  01011111  010001  00  0101  011010    Throttle 07
010001  01101100  010001  00  0101  101001    Throttle 08
010001  01111010  010001  00  0101  111111    Throttle 09
010001  10000101  010001  00  0101  000000    Throttle 10 (max)

Channel B
Yaw     Throttle  Pitch   Tr  Chan  Check     Description
-----------------------------------------------------------
000000  10000110  010001  00  0010  010101    Left Max + Throttle 
100100  10000110  010001  00  0010  110001    Right Max + Throttle 
010001  00000000  001001  00  0010  011010    Forward Min 
010001  00000000  000000  00  0010  010011    Forward Max 
010001  00000000  010111  00  0010  000100    Back Min 
010001  00000000  100110  00  0010  110101    Back Max
010001  00000000  010001  01  0010  010010    Left Trim 
010001  00000000  010001  10  0010  100010    Right Trim 
010001  00000001  010001  00  0010  000011    Throttle Min 
010001  00110100  010001  00  0010  110110    Throttle Mid 
010001  01100111  010001  00  0010  100101    Throttle High 
010001  10001111  010001  00  0010  001101    Throttle Max 

Channel C
Yaw     Throttle  Pitch   Tr  Chan  Check     Description
-----------------------------------------------------------
000000  10000101  010001  00  1000  011100    Left Max + Throttle 
100100  10000101  010001  00  1000  111000    Right Max + Throttle 
010001  00000000  001010  00  1000  010011    Forward Min 
010001  00000000  000000  00  1000  011001    Forward Max 
010001  00000000  010111  00  1000  001110    Back Min 
010001  00000000  100110  00  1000  111111    Back Max
010001  00000000  010001  01  1000  011000    Left Trim 
010001  00000000  010001  10  1000  101000    Right Trim 
010001  00000001  010001  00  1000  001001    Throttle Min 
010001  00110100  010001  00  1000  111100    Throttle Mid 
010001  01100110  010001  00  1000  101110    Throttle High 
010001  10000101  010001  00  1000  001101    Throttle Max

Seperti disebutkan di atas, 8 bit terakhir telah ditemukan, tetapi hanya untuk anak cucu, inilah pemikiran asli saya. Jangan ragu untuk mengabaikannya sama sekali, karena dugaan saya salah besar.

8 bit terakhir

8 bit terakhir dari paket masih sedikit misteri.

4 bit dari bit 23 hingga 26 semuanya tampaknya sepenuhnya ditentukan oleh pengaturan saluran remote control. Mengubah saluran pada kendali jarak jauh tidak mengubah protokol atau modulasi dengan cara apa pun; itu hanya mengubah 4 bit itu.

Tetapi 4 bit adalah dua kali lipat dari yang sebenarnya dibutuhkan untuk menyandikan pengaturan saluran; hanya ada tiga saluran, jadi 2 bit banyak. Oleh karena itu, dalam uraian struktur di atas, saya hanya memberi label 2 bit pertama sebagai "Saluran", dan meninggalkan dua lainnya berlabel "X", tetapi ini dugaan.

Di bawah ini adalah contoh bit yang relevan untuk setiap pengaturan saluran.

Chan.   Bits 23-26
-----+-------------
  A  |  0  1  0  1
  B  |  0  0  1  0
  C  |  1  0  0  0

Pada dasarnya, ada 2 bit lebih dari yang dibutuhkan untuk mengirimkan pengaturan saluran. Mungkin protokol memiliki 4 bit yang disisihkan untuk memungkinkan lebih banyak saluran nanti, atau lebih tepatnya protokol dapat digunakan dalam mainan yang sama sekali berbeda, tapi saya tidak tahu. Untuk nilai yang lebih besar, protokol tidak menggunakan bit tambahan yang bisa ditinggalkan (yaw / throttle / pitch bisa bertahan dengan sedikit lebih sedikit masing-masing), tetapi untuk trim - yang juga memiliki 3 status - hanya 2 bit yang digunakan. Jadi orang bisa curiga bahwa saluran tersebut juga hanya 2 bit, tetapi itu membuat 2 berikutnya tidak terhitung.

Kemungkinan lain adalah bahwa checksum paket adalah 8 bit, dimulai dengan "bit X", dan - melalui keajaiban checksumming - mereka kebetulan mencerminkan pengaturan saluran. Tetapi sekali lagi: Saya tidak tahu.

Dan berbicara tentang: Saya tidak tahu bagaimana bit-bit cek terbentuk. Maksudku, mereka adalah bit check, karena mereka tidak sesuai dengan input kendali tunggal, dan helikopter tampaknya tidak merespon jika saya bermain-main dengan mereka. Saya kira ini semacam CRC, tapi saya belum bisa mengetahuinya. Cek tersebut panjangnya 6-8 bit, tergantung pada bagaimana Anda mengartikan "bit X", jadi ada banyak cara yang bisa disatukan.

Flambino
sumber
6

Ini tidak terlihat terlalu buruk. Pemberitahuan pertama bahwa semua pesan berisi persis 17 pulsa. Ini segera memberi kita petunjuk kuat bahwa ruang pendek di dalam pesan tidak relevan. Tampaknya data dikodekan oleh pulsa yang pendek atau panjang, dan bahwa beberapa rentang jarak antara pulsa ini dapat diterima.

Jelas, setiap pesan dimulai dengan pulsa panjang sebagai bit awal. Itu menyisakan 16 bit data. Mungkin beberapa bit awal adalah opcode, mungkin panjang variabel. Jika saya melakukan ini, beberapa bit akhir akan menjadi sebuah checksum. Gambar para insinyur yang menulis firmware ingin membuat hal-hal sederhana untuk diri mereka sendiri, sehingga Anda dapat mulai dengan mengasumsikan ada 8 bit data di suatu tempat. Sekarang lihat apakah ada pesan yang masuk akal.

Mari kita sebut panjang 1 dan pendek 0. Mungkin sebaliknya, tapi kita harus mulai dari suatu tempat. Melepas bit awal mulai:

1010001101011010 mnt throttle
1010011101011000 maks throttle
1010000001011111 menit ke depan
Maks 1010000000011110 maju
Maks 1010000011011101 kembali
1010000100011010 kembali
0000010101011100 max tersisa + throttle maksimal
0100010101011110 maks. Kanan + maks throttle
1010000101111111 potong ke kiri
1010000101011011 potong kanan

Beberapa hal segera muncul. Jelas bit 0 adalah bit paritas. Kalau tidak, tampaknya ada bidang 3 bit <15:13>, nilai data 8 bit <12: 5>, dan bidang 4 bit lainnya <4: 1>.

Sepertinya nilai data sedang dikirim dalam urutan bit rendah ke tinggi, jadi mungkin lebih masuk akal untuk menginterpretasikan keseluruhan 16 bit yang dibalik dari apa yang saya perlihatkan.

Saya merasa tidak ingin menghabiskan lebih banyak waktu untuk hal ini, tetapi mudah-mudahan ini memberi Anda awal. Saya akan melanjutkan dengan menulis ulang daftar di atas dengan sedikit paritas dilucuti, seluruh angka membalik LSB ke MSB, dan masing-masing bidang diasumsikan ditampilkan secara terpisah dengan ruang di antara itu dan bidang berbatasan. Itu mungkin memungkinkan lebih banyak muncul pada Anda. Juga perlu diingat bahwa kita mungkin memiliki indera 1/0 dari setiap bit mundur. Mungkin menulis tabel baru setiap jalan dan melihat apakah sesuatu lebih masuk akal satu arah.

Olin Lathrop
sumber
Terima kasih, ini luar biasa! Saya akan benar, dan melihat apa yang saya temukan. Setelah melihat protokol lain, saya mulai berpikir bahwa mungkin ruang tidak relevan, tetapi karena mereka memiliki dua timing yang sangat konsisten, saya tidak begitu yakin. Saya pikir mereka akan lebih bervariasi jika tidak penting. Bagaimanapun, saya akan mencobanya. Terima kasih lagi
Flambino
Huh ... sejauh yang saya tahu, ruang itu penting. Saya memfokuskan pada throttle, dan menangkap beberapa sampel lagi di 10 posisi throttle yang berbeda. Mengecualikan spasi tidak memberi saya angka yang berarti terlepas dari bagaimana saya melakukan konversi. Tetapi termasuk mereka selama = 1, pendek = 0 menghasilkan perkembangan halus dari nilai throttle dari 1 menjadi 134 (little endian). Masih bekerja pada parameter lainnya
Flambino
Saya sudah mendapatkan protokol yang hampir seluruhnya diketahui, tetapi masih ada sedikit misteri. Menambahkan banyak hal ke pertanyaan saya, jika Anda ingin mencobanya. Bagaimanapun, terima kasih atas bantuan Anda sejauh ini! Membuat saya bekerja ke arah yang benar.
Flambino
@ Flambino: Sepertinya Anda jauh di depan dari apa yang saya lakukan untuk memulainya, yang ternyata sebagian besar tebakan salah di belakang. Saya membaca pertanyaan Anda yang diperbarui tetapi masih tidak mengerti bagaimana tepatnya panjang spasi digunakan. Apakah hanya kebetulan bahwa semua pola yang Anda tunjukkan memiliki tepat 17 pulsa dan yang terakhir menunjukkan paritas jika hanya pulsa yang dianggap 0 atau 1?
Olin Lathrop
Jujur, itu sebagian besar trial and error di pihak saya. Karena 2 timing yang digunakan untuk spasi sama persis dengan timing pulsa, saya pikir mereka mungkin bermakna. Dan, ketika mengabaikan spasi tidak menghasilkan data biner yang berguna, saya hanya mengasumsikan pulsa panjang = 1 dan ruang panjang = 1 (dan ruang pendek / pulsa = 0), yang segera memberi saya data yang sangat berguna. Jadi spasi pertama setelah pulsa pembukaan adalah bit pertama (grafik kanan max + throttle max menunjukkan "spasi 1" sebagai bit pertama) diikuti oleh 16 pulsa, dengan 15 ruang lebih di antaranya; 32 bit.
Flambino