Sumber inspirasi
Di pameran game, pengembang
Object in Space menunjukkan demo permainan mereka dengan pengontrol di kokpit pesawat ruang angkasa besar. Itu dilengkapi dengan tombol menerangi, perangkat analog, indikator lampu status, switch, dll ... Ini sangat mempengaruhi perendaman dalam permainan:
Tutorial Arduino telah diposting di situs web game dengan deskripsi
protokol komunikasi untuk pengontrol seperti itu.
Saya ingin membuat yang sama untuk permainan sayaDalam contoh ini, saya akan menghabiskan sekitar $ 40 untuk menambahkan saklar yang indah, besar dan berat ke kokpit simulator balap. Biaya utama terkait dengan sakelar ini - jika saya menggunakan sakelar / tombol sederhana, harganya akan setengahnya! Ini adalah peralatan nyata yang dapat menahan daya 240 watt, dan saya hanya akan mengeluarkan sekitar 0,03 watt.
Peringatan: Saya memutuskan untuk menghemat uang, jadi saya meninggalkan tautan ke situs web China yang murah tempat saya membeli banyak komponen / alat yang berbeda. Salah satu kelemahan dari membeli komponen murah adalah seringnya mereka tidak memiliki dokumentasi, jadi pada artikel ini saya akan menyelesaikan masalah ini.
Komponen utama
Alat Unggulan
Perangkat lunak
- Arduino IDE untuk pemrograman prosesor Arduino
- Untuk membuat pengontrol yang muncul sebagai pengontrol / joystick USB nyata:
- FLIP untuk menginstal firmware baru di pengontrol USB Arduino
- Perpustakaan Arduino-usb di github
- Untuk membuat pengontrol yang berkomunikasi game secara langsung ( atau yang muncul sebagai pengontrol / joystick USB virtual )
- Perpustakaan ois_protocol saya di github
- Driver VJoy jika Anda ingin menggunakan controller sebagai pengendali USB virtual / joystick.
Peringatan
Saya belajar elektronik di sekolah menengah, belajar cara menggunakan besi solder, belajar bahwa kabel merah harus terhubung ke merah, dan hitam ke hitam ... Volts, ampere, resistance dan persamaan yang menghubungkan mereka - itu saja yang pelatihan formal saya di elektronik telah habis.
Bagi saya itu adalah proyek pelatihan, jadi mungkin ada saran atau kesalahan buruk!
Bagian 1. Menyatukan pengontrol!
Kami bekerja dengan sakelar tanpa dokumentasi ...
Seperti yang dinyatakan di atas, saya membeli suku cadang murah dari pengecer dengan margin rendah, jadi hal pertama yang harus dilakukan adalah mencari tahu bagaimana sakelar / tombol ini bekerja.
Tombol / sakelar sederhana
Dengan tombol, semuanya sederhana - tidak ada LED di dalamnya dan hanya dua kontak. Alihkan multimeter ke mode kontinuitas / panggilan (

) dan sentuh probe dari kontak yang berbeda - OL (loop terbuka, sirkuit terbuka) akan ditampilkan di layar: ini berarti tidak ada koneksi antara kedua probe. Kemudian kami menekan tombol, masih menyentuh probe kontak - sesuatu seperti 0.1Ξ© sekarang akan muncul di layar dan multimeter akan mulai berbunyi bip (
menunjukkan bahwa ada resistansi yang sangat rendah antara probe - sirkuit tertutup ).
Sekarang kita tahu bahwa ketika tombol ditekan, sirkuit menutup, dan ketika ditekan, itu terbuka. Dalam diagram, ini dapat digambarkan sebagai saklar sederhana:

Kami menghubungkan sakelar ke Arduino
Temukan dua pin pada papan Arduino: berlabel GND dan berlabel "2" (atau nomor sewenang-wenang lainnya - ini adalah pin I / O tujuan umum yang dapat kita kontrol melalui perangkat lunak).
Jika kita menghubungkan saklar dengan cara ini, dan kemudian kita memesan Arduino untuk mengkonfigurasi pin "2" sebagai pin INPUT, kita mendapatkan sirkuit yang ditunjukkan di sebelah kiri (pada gambar di bawah). Ketika tombol ditekan, pin 2 akan langsung terhubung ke ground / 0V, dan ketika ditekan, pin 2 tidak akan terhubung ke apa pun. Keadaan ini (
tidak terhubung dengan apa pun ) disebut "mengambang" (keadaan impedansi tinggi) dan, sayangnya, ini bukan kondisi yang sangat baik untuk tujuan kami. Ketika kami membaca data dari kontak di perangkat lunak (
menggunakan digitalRead (2) ), kami mendapatkan RENDAH jika kontak di-ground, dan hasil yang tidak terduga (RENDAH atau TINGGI) jika kontaknya mengambang!
Untuk memperbaikinya, kita dapat mengonfigurasi kontak agar berada dalam mode INPUT_PULLUP, yang terhubung ke resistor di dalam prosesor dan membuat sirkuit yang ditunjukkan di sebelah kanan. Di sirkuit ini, dengan sakelar terbuka, pin 2 memiliki lintasan + 5V, jadi ketika terbaca, hasilnya akan selalu TINGGI. Ketika sakelar ditutup, kontak masih akan memiliki jalur dengan resistansi tinggi ke + 5V, serta jalur tanpa resistansi ke ground / 0V, yang βmenangβ, jadi ketika kita membaca kontak, kita mendapatkan RENDAH.
Untuk pengembang perangkat lunak, urutannya mungkin terbalik - ketika kita mengklik tombol, kita membaca false / LOW, dan ketika tertekan, kita membaca true / HIGH.
Anda dapat melakukan yang sebaliknya, tetapi prosesor hanya memiliki resistor pull-up bawaan dan tidak ada resistor pull-down, jadi kami akan tetap menggunakan model ini.
Program paling sederhana untuk Arduino, yang membaca status sakelar dan memberi tahu PC tentang statusnya, terlihat seperti yang ditunjukkan di bawah ini. Anda dapat mengklik tombol unduh di IDE Arduino dan kemudian membuka Serial Monitor (di menu Tools) untuk melihat hasilnya.
void setup() { Serial.begin(9600); pinMode(2, INPUT_PULLUP); } void loop() { int state = digitalRead(pin); Serial.println( state == HIGH ? "Released" : "Pressed" ); delay(100);
Switch lain dengan hampir tidak ada dokumentasi ...
Saklar LED tiga pin
Untungnya, pada sakelar utama panel saya ada tiga tanda kontak:
Saya tidak sepenuhnya yakin cara kerjanya, jadi kami akan mengalihkan multimeter kembali ke mode kontinu dan menyentuh semua pasangan kontak saat sakelar dihidupkan dan dimatikan ... namun, kali ini multimeter tidak berbunyi bip sama sekali ketika kami menyentuh probe [GND] dan [+] dengan β nyalakan! Satu-satunya konfigurasi di mana multimeter berbunyi bip (
mendeteksi koneksi ) adalah ketika sakelar "aktif" dan probe menyala [+] dan [lampu].
LED di dalam sakelar memblokir pengukuran kontinuitas, jadi dari pengujian di atas kita dapat mengasumsikan bahwa LED terhubung langsung ke pin [GND], dan bukan ke kontak [+] dan [lampu]. Selanjutnya, kita akan mengalihkan multimeter ke mode uji dioda (simbol

) dan periksa kembali pasangan kontak, tetapi kali ini polaritas penting (
probe merah dan hitam ). Sekarang jika kita menghubungkan probe merah ke [lampu], dan hitam ke [GND], maka LED akan menyala dan 2.25V akan ditampilkan pada multimeter. Ini adalah tegangan langsung dari dioda, atau tegangan minimum yang diperlukan untuk menyalakannya. Terlepas dari posisi sakelar, 2.25V dari [lampu] ke [GND] menyebabkan LED menyala. Jika kita menghubungkan probe merah ke [+], dan hitam ke [GND], maka LED hanya akan menyala ketika sakelar dihidupkan.
Dari bacaan ini, kita dapat mengasumsikan bahwa bagian dalam saklar ini terlihat seperti diagram di bawah ini:
- [+] dan [lampu] dihubung pendek saat sakelar hidup / tertutup.
- Tegangan positif dari [lampu] ke [GND] selalu menyalakan LED.
- Tegangan positif dari [+] ke [GND] menyalakan LED hanya ketika sakelar dihidupkan / ditutup.
Jujur saja, kita hanya bisa menebak tentang keberadaan resistor. LED
harus terhubung ke resistor yang sesuai untuk membatasi arus yang disediakan padanya, atau akan terbakar. Milik saya tidak terbakar dan sepertinya berfungsi dengan benar. Di forum situs web penjual, saya menemukan posting yang membahas tentang resistor yang dipasang yang mendukung hingga 12 V, dan ini menghemat waktu saya dalam memeriksa / menghitung resistor yang sesuai.
Kami menghubungkan sakelar ke Arduino
Cara termudah adalah menggunakan sakelar dengan Arduino, mengabaikan pin [lampu]: hubungkan [GND] ke GND di Arduino dan hubungkan [+] ke salah satu kontak Arduino yang bernomor, misalnya 3.
Jika kita mengonfigurasi pin 3 sebagai INPUT_PULLUP (
sama seperti untuk tombol sebelumnya ), maka kita akan mendapatkan hasil yang ditunjukkan di bawah ini. Kiri atas menunjukkan nilai yang akan kita terima dengan mengeksekusi "digitalRead (3)" dalam kode Arduino.
Saat sakelar hidup / tertutup, kita membaca RENDAH dan LED menyala! Untuk menggunakan sakelar seperti itu dalam konfigurasi ini, kita dapat menggunakan kode Arduino yang sama seperti pada contoh tombol.
Masalah solusi ini
Setelah terhubung ke Arduino, sirkuit penuh terlihat seperti ini:
Namun, di sini kita dapat melihat bahwa ketika saklar ditutup, di samping resistor pembatas arus kecil di depan LED (saya berasumsi bahwa resistansi adalah 100 Ohm), ada juga resistor pull-up sebesar 20 kΞ©, yang selanjutnya mengurangi jumlah arus yang mengalir melalui LED. Ini berarti bahwa meskipun rangkaian berfungsi, LED tidak akan terlalu terang.
Kelemahan lain dari skema ini adalah bahwa kita tidak memiliki kontrol perangkat lunak atas LED - itu dinyalakan ketika saklar dihidupkan, dan dinonaktifkan dalam kasus yang berlawanan.
Anda dapat melihat apa yang terjadi jika kami menghubungkan pin [lampu] ke 0V atau + 5V.
Jika [lampu] terhubung ke 0V, maka LED selalu mati (
terlepas dari posisi sakelar ), dan pengenalan posisi Arduino masih dilakukan. Ini memungkinkan kita untuk menonaktifkan LED secara terprogram!
Jika [lampu] terhubung ke + 5V, maka LED terus menyala (
terlepas dari posisi sakelar ),
namun, pengakuan posisi Arduino rusak - TINGGI akan selalu dibaca dari kontak.
Kami menghubungkan saklar ini ke Arduino dengan benar
Kita dapat mengatasi keterbatasan yang dijelaskan di atas (
arus rendah / kecerahan LED dan kurangnya kontrol program terhadap LED ) dengan menulis lebih banyak kode! Untuk menyelesaikan konflik antara kemampuan mengontrol LED dan pengenalan posisi yang rusak karena itu, kita dapat memisahkan dua tugas tepat waktu, yaitu mematikan sementara LED saat membaca kontak sensor (3).
Pertama, hubungkan pin [lampu] ke pin Arduino yang bertujuan umum lainnya, misalnya, ke 4 sehingga Anda dapat mengontrol lampu.
Untuk membuat program yang akan dengan benar membaca posisi sakelar dan mengontrol LED (kita akan membuatnya berkedip), kita hanya perlu mematikan LED sebelum membaca status sakelar. LED akan mati hanya dalam sepersekian milidetik, sehingga flicker tidak akan terlihat:
int pinSwitch = 3; int pinLed = 4; void setup() {
Dalam Arduino Mega, pin 2-13 dan 44-46 dapat menggunakan fungsi analogWrite, yang sebenarnya tidak menghasilkan tegangan dari 0V ke + 5V, tetapi diperkirakan menggunakan gelombang persegi. Jika diinginkan, Anda dapat menggunakannya untuk mengontrol kecerahan LED! Kode ini akan membuat cahaya berdenyut, bukan hanya berkedip:
void loop() { int lampState = (millis()>>1)&0xFF;
Tips Perakitan
Posnya sudah cukup besar, jadi saya tidak akan menambahkan tutorial solder, Anda dapat google itu!
Namun, saya akan memberikan tips paling mendasar:
- Saat menghubungkan kabel dengan kontak logam besar, pertama-tama pastikan bahwa besi solder panas dan kontak logam untuk sementara waktu. Arti penyolderan adalah untuk membentuk koneksi permanen dengan membuat paduan, tetapi jika hanya satu bagian dari koneksi yang panas, maka Anda dapat dengan mudah mendapatkan "koneksi dingin" yang terlihat seperti koneksi, tetapi sebenarnya tidak terhubung.
- Saat menyambungkan kedua kabel, pasanglah salah satu di antaranya sepotong tabung panas-menyusut - setelah sambungan, pipa tidak dapat dipasang. Ini terlihat jelas, tetapi saya terus-menerus melupakannya dan saya harus menggunakan pita listrik sebagai ganti tabung ... Tarik tabung menyusut dari sambungan sehingga tidak memanas di depan waktu. Setelah memeriksa sambungan yang disolder, geser tabung ke atasnya dan panaskan.
- Kabel penghubung kecil tipis yang saya sebutkan di awal sangat cocok untuk koneksi tanpa solder (misalnya, ketika terhubung ke Arduino!), Tapi agak rapuh. Setelah menyolder, gunakan lem untuk memperbaikinya dan menghilangkan semua tekanan dari koneksi itu sendiri. Misalnya, kabel merah pada gambar di bawah ini dapat ditarik secara tidak sengaja selama operasi, jadi setelah menyolder saya memperbaikinya dengan setetes lem panas:
Bagian 2. Kami mengubah perangkat menjadi pengontrol permainan!
Agar OS mengenali perangkat sebagai pengontrol permainan USB, Anda memerlukan kode yang cukup sederhana, tetapi, sayangnya, Anda juga perlu mengganti firmware chip USB Arduino dengan yang lain, yang dapat diambil di sini:
https://github.com/harlequin-tech/arduino-usb .
Tetapi setelah mengunggah firmware ini ke Arduino, perangkat menjadi USB joystick dan tidak lagi menjadi Arduino. Oleh karena itu, untuk memprogram ulang, Anda perlu mem-flash firmware Arduino yang asli. Iterasi ini cukup menyakitkan - muat kode Arduino, flash firmware joystick, tes, flash firmware Arduino, ulangi ...
Contoh program untuk Arduino yang dapat digunakan dengan firmware ini ditunjukkan di bawah ini - ini mengkonfigurasi tiga tombol sebagai input, membaca nilainya, menyalin nilai-nilai ke struktur data yang diharapkan oleh firmware ini, dan kemudian mengirimkan data. Cuci bersih, sabun, ulangi.
Bagian 3. Kami mengintegrasikan perangkat dengan permainan kami sendiri!
Jika Anda memiliki kendali atas gim yang berinteraksi dengan perangkat, maka sebagai alternatif Anda dapat berkomunikasi dengan pengontrol secara langsung - tidak perlu membuatnya terlihat oleh OS sebagai joystick! Di awal posting, saya menyebutkan Object In Space; ini adalah pendekatan yang digunakan pengembangnya. Mereka menciptakan protokol komunikasi ASCII sederhana yang memungkinkan pengontrol dan permainan untuk berkomunikasi satu sama lain. Cukup daftarkan port serial sistem (ini
adalah port COM pada Windows; ngomong-ngomong, lihat betapa buruknya tampilannya di C ), cari port yang terhubung dengan perangkat yang disebut "Arduino", dan mulai membaca / menulis ASCII dari tautan ini.
Di sisi Arduino, kami hanya menggunakan fungsi Serial.print yang digunakan dalam contoh di atas.
Di awal posting ini, saya juga menyebutkan perpustakaan saya untuk menyelesaikan masalah ini:
https://github.com/hodgman/ois_protocol .
Ini berisi kode C ++ yang dapat diintegrasikan ke dalam game dan digunakan sebagai "server", dan kode Arduino yang dapat dieksekusi di controller untuk menggunakannya sebagai "klien".
Sesuaikan Arduino
Di
example_hardware.h, saya membuat kelas untuk mengabstraksi tombol individu / tombol radio; misalnya, "Beralih" adalah tombol sederhana dari contoh pertama, dan "LedSwitch2Pin" adalah saklar dengan LED yang dikendalikan dari contoh kedua.
Kode contoh untuk bilah tombol saya di
example.ino .
Sebagai contoh kecil, katakanlah kita memiliki satu tombol yang perlu dikirim ke gim, dan satu LED yang dikendalikan gim. Kode Arduino yang diperlukan terlihat seperti ini:
#include "ois_protocol.h"
Sesuaikan gim
Kode permainan ditulis dalam gaya "tajuk tunggal". Untuk mengimpor perpustakaan, sertakan
oisdevice.h dalam game.
Dalam file CPP tunggal, sebelum mengeksekusi header #include, tulis #define OIS_DEVICE_IMPL dan #define OIS_SERIALPORT_IMPL - ini akan menambahkan kode sumber kelas ke file CPP. Jika Anda memiliki pernyataan, log, string atau vektor Anda sendiri, maka ada beberapa makro OIS_ * lain yang dapat Anda tentukan sebelum mengimpor header untuk memanfaatkan kapabilitas mesin.
Untuk daftar port COM dan membuat koneksi dengan perangkat tertentu, Anda dapat menggunakan kode berikut:
OIS_PORT_LIST portList; OIS_STRING_BUILDER sb; SerialPort::EnumerateSerialPorts(portList, sb, -1); for( auto it = portList.begin(); it != portList.end(); ++it ) { std::string label = it->name + '(' + it->path + ')'; if( ) { int gameVersion = 1; OisDevice* device = new OisDevice(it->id, it->path, it->name, gameVersion, "Game Title"); ... } }
Setelah menerima instance OisDevice, Anda harus secara teratur memanggil fungsi anggota Poll-nya (misalnya, di setiap frame), Anda bisa mendapatkan status saat ini dari output pengontrol menggunakan DeviceOutputs (), menggunakan peristiwa perangkat menggunakan PopEvents () dan mengirim nilai ke perangkat menggunakan SetInput ().
Contoh aplikasi melakukan semua ini dapat ditemukan di sini:
example_ois2vjoy / main.cpp .
Bagian 4. Bagaimana jika saya ingin bagian 2 dan 3 secara bersamaan?
Agar pengontrol bekerja di gim lain (bagian 2), Anda perlu menginstal firmware Anda sendiri dan satu program Arduino, tetapi agar pengontrol dapat diprogram sepenuhnya oleh gim, kami menggunakan firmware Arduino standar dan program Arduino lainnya. Tetapi bagaimana jika kita ingin memiliki kedua kemungkinan sekaligus?
Contoh aplikasi yang saya berikan tautan di atas (
ois2vjoy ) menyelesaikan masalah ini.
Aplikasi ini berkomunikasi dengan perangkat OIS (program dari Bagian 3), dan kemudian pada PC mengubah data ini menjadi data pengontrol / joystick normal, yang kemudian ditransfer ke perangkat pengontrol
virtual / joystick. Ini berarti Anda dapat mengizinkan pengontrol Anda untuk terus menggunakan pustaka OIS (tidak ada firmware lain yang diperlukan), dan jika kami ingin menggunakannya sebagai pengontrol / joystick biasa, maka jalankan saja aplikasi ois2vjoy di PC, yang melakukan konversi.
Bagian 5. Penyelesaian
Saya harap seseorang menemukan artikel ini bermanfaat atau menarik. Terima kasih sudah membaca sampai akhir!
Jika Anda penasaran, maka saya mengundang Anda untuk berpartisipasi dalam pengembangan perpustakaan
ois_protocol ! Saya pikir akan bagus untuk mengembangkan protokol tunggal untuk mendukung semua jenis pengendali buatan sendiri dalam game dan mendorong game untuk secara langsung mendukung pengendali buatan sendiri!