Kontrol komputer melalui remote control dari amplifier menggunakan Arduino dan Node.js

Kata Pengantar


Cerita dimulai dengan fakta bahwa setengah tahun yang lalu saya membeli amplifier Yamaha A-S501.


Yamaha A-S501


Termasuk adalah remote control yang bisa mengendalikan amplifier dan pemutar CD Yamaha, yang tentu saja tidak saya miliki. Oleh karena itu, sebagian besar tombol pada remote control sama sekali tidak digunakan. Dan secara umum, konsol itu sendiri tidak perlu, dan selalu diletakkan di rak.


Namun, menatapnya, saya dihantui oleh gagasan untuk menggunakan remote control sepenuhnya. Misalnya, akan lebih nyaman untuk berbaring di sofa dan menonton film, mundur dengan gerakan tangan yang cepat, menjeda, dll. Tentu saja, untuk keperluan ini, saya biasa menggunakan aplikasi pada smartphone saya untuk mengontrol program MPC-HC, Foobar2000, tetapi remote control akan lebih cepat dan lebih nyaman.


Seperti yang mereka katakan, mata takut, dan tangan melakukannya. Dengan pilihan teknologi, semuanya langsung jelas. Arduino - Saya sudah lama ingin bermain dengannya, dan ini hanya kesempatan besar. Untuk penangan tombol, Node.js, karena Saya berspesialisasi dalam javascript, dan tidak ingin beralih konteks.


Jadi, ayo pergi ...


Solusi siap pakai


Salah satu analog yang ada yang bisa saya temukan adalah Flirc . Dengan menggunakannya, Anda dapat meniru penekanan tombol pada keyboard fisik komputer.



Penerima inframerah semacam itu berharga 100 zlotys (β‰ˆ $ 28). Ke depan, harganya dua kali lebih mahal dari yang saya dapatkan. Selain itu, dalam hal fungsionalitas, ternyata lebih baik (secara subyektif).


Membeli Bagian



Saya membutuhkan:


  • Sebenarnya, papan Arduino Uno itu sendiri. Perlu dicatat bahwa ini bukan papan asli, tetapi semacam klon Polandia. Menurut deskripsi - ini benar-benar mirip dengan aslinya. (27,90 zΕ‚)
  • Penerima inframerah VS1838B HX1838 (tegangan: 3,3–5 V, frekuensi: 38 kHz, sudut: 90 Β°) (1,30 zΕ‚)
  • Papan prototipe + kabel (13,90 zΕ‚)
  • Papan kosong untuk menyolder semuanya (2.10 zΕ‚)
  • Konektor untuk papan penghubung (2,51 zΕ‚)

Total: 47,71 zΕ‚ (β‰ˆ $ 14)


Perangkat lunak


Sambil menunggu pengiriman, saya mulai menulis "driver", yang seharusnya membaca data dari port serial dari Arduino dan melakukan tindakan tertentu untuk tombol yang ditekan pada remote control.


Idenya adalah untuk dapat menyesuaikan segalanya dan segalanya. Setiap tombol pada kendali jarak jauh dapat ditetapkan tindakan tertentu dari beberapa jenis:



{ "key": "space" } 

  • Menjalankan program arbitrer dengan parameter:

 { "exec": ["c:\\Program Files (x86)\\foobar2000\\foobar2000.exe", "/play"] } 


 { "if": { "running": "mpc-hc.exe" }, "then": [ ... ], "else": [ ... ] } 

Setiap jenis memiliki penangannya sendiri, yang memiliki API yang sama, dan oleh karena itu dimungkinkan untuk memecah semuanya menjadi satu loop sederhana yang memulai semua penangan secara berurutan.


 const runHandlers = require('./handlers') module.exports = async function run(actions) { if (!Array.isArray(actions)) { actions = [actions] } for (const act of actions) { await runHandlers(act) } } 

Alih-alih seribu kata dokumentasi, tes memberi tahu Anda segalanya:


 run when "exec" action √ executes the specified file without args (as array) (4ms) √ executes the specified file without args (as string) (1ms) √ executes the specified file with args √ rejects if "exec" has wrong type (5ms) when "key" action √ sends the specified key press if passed string (1ms) √ sends the specified key combination if passed array √ rejects if "key" has wrong type (1ms) when "if" action √ rejects if no "then" (1ms) √ rejects if operator is not supported when operator if "running" √ runs "then" actions if the condition is true (1ms) √ runs "else" actions if the condition is false √ does not run anything if the condition is false and no "else" statement (1ms) when multiple actions √ executes all actions (1ms) when multiple actions are mixed into one √ runs only first one alphabetically 

Masih menunggu detail yang disayangi.


Besi


Saya akui, saya tidak menemukan sesuatu yang baru, semuanya sudah dilakukan sebelum saya. Saya baru saja menggunakan diagram yang sudah jadi dari artikel Cara Mengatur Remote IR dan Penerima pada Arduino .


Skema ini cukup sederhana:



Dalam praktek:




Firmware


Saya juga dengan jujur ​​meminjam firmware dari artikel , untuk pekerjaannya saya akan membutuhkan Perpustakaan IRremote Arduino .


Saya mengganti kode tombol dengan yang sebenarnya dari remote control saya:


 void loop() { if (irrecv.decode(&results)) { if (results.value == 0xFFFFFFFF) { results.value = key_value; } switch (results.value) { case 0x9E6140BF: Serial.println("play"); break; case 0x9E61AA55: Serial.println("pause"); break; /* ...*/ case 0x5EA1A857: Serial.println("cd"); break; default: Serial.println(results.value, HEX); break; } key_value = results.value; irrecv.resume(); } } 


Segera setelah nama-nama tombol yang ditekan muncul di jendela Monitor port di Arduino IDE, perlu untuk menambahkan komponen untuk bekerja dengan port serial ke driver.


Hasilnya adalah pembungkus di atas perpustakaan serialport dan, pada kenyataannya, aliran data dari port:


 const SerialPort = require('serialport') module.exports = class SerialPortReader { constructor(port) { const serialPort = new SerialPort(port) this.lineStream = serialPort.pipe(new SerialPort.parsers.Readline()) } start(handler) { this.lineStream.on('readable', () => { const data = this.lineStream.read().trim() handler(data) }) } } 

Kemudian, ada kebutuhan untuk mengubah penangan menjadi fungsi "debounce", karena kendali jarak jauh menerima sinyal yang berulang dengan cepat, yang, bahkan dengan menekan sebentar tombolnya, berhasil berbunyi beberapa kali. Namun, menghapus opsi seperti itu untuk semua tombol juga tidak sepenuhnya sesuai, misalnya untuk volume.


Kode akhir terlihat seperti ini:


 const debounce = require('debounce') const settings = require('./lib/settings') const run = require('./lib/run') const SerialPortReader = require('./lib/SerialPortReader') const simpleHandle = async button => { const actions = settings.mappings[button] if (!actions) { console.warn(`Action not found for remote control button "${button}"`) return } try { await run(actions) } catch (e) { console.error(e.message) process.exit(1) } } const debouncedHandle = debounce(simpleHandle, settings.debounceDelay, true) const callHandleFn = button => { return (settings.noDebounce.includes(button) ? simpleHandle : debouncedHandle)(button) } const reader = new SerialPortReader(settings.serialPort) reader.start(callHandleFn) 

Membuat Dewan Independen


Setelah memastikan bahwa prototipe berfungsi, saya mulai membuat papan. Perlu dicatat bahwa bagi saya ini adalah pengalaman pertama dalam masalah seperti itu. Saya tidak punya besi solder yang cocok dengan jarum kecil - hanya yang besar Soviet tua dengan kawat yang rapat.


Dengan kesedihan menjadi dua, saya berhasil menyolder "kaki" (dari dua konektor besar 8 pin, hanya 2 pin yang selamat). Segalanya lebih mudah.



(Bengkok. Kemungkinan besar karena klon Arduino. Sarang relatif tidak sama satu sama lain.)



Saya sengaja meletakkan penerima inframerah di sela-sela papan. Jadi perangkat mudah masuk di bawah amplifier. Saya memutuskan untuk membuat jalur dengan menghubungkan lubang-lubang di papan dengan timah, bukannya menghubungkannya dengan kabel. Dan akhirnya, saya menempelkan selotip ke atas agar papan tidak menutup casing logam dari amplifier.




Hasilnya: perangkat dan perangkat lunak yang berfungsi penuh untuk for $ 14. Pengalaman yang didapat dan kegembiraan dari pekerjaan yang dilakukan dan hasilnya sangat berharga! :-)


Terima kasih atas perhatian anda!




Demo:



Sumber di Github .




PS Terima kasih ramanchik 'u untuk konsultasi :)

Source: https://habr.com/ru/post/id453474/


All Articles