Daftar Isi:

Infinity Bike - Video Game Pelatihan Sepeda Dalam Ruangan: 5 Langkah
Infinity Bike - Video Game Pelatihan Sepeda Dalam Ruangan: 5 Langkah

Video: Infinity Bike - Video Game Pelatihan Sepeda Dalam Ruangan: 5 Langkah

Video: Infinity Bike - Video Game Pelatihan Sepeda Dalam Ruangan: 5 Langkah
Video: Peristiwa aneh di sebuah kamar hotel 2024, September
Anonim
Image
Image
Bahan
Bahan

Selama musim dingin, hari-hari yang dingin dan cuaca buruk, penggemar sepeda hanya memiliki beberapa pilihan untuk berolahraga melakukan olahraga favorit mereka. Kami sedang mencari cara untuk membuat pelatihan dalam ruangan dengan pengaturan sepeda/pelatih sedikit lebih menghibur tetapi sebagian besar produk yang tersedia mahal atau membosankan untuk digunakan. Inilah mengapa kami mulai mengembangkan Infinity Bike sebagai video game pelatihan Open Source. Sepeda Infinity membaca kecepatan dan arah dari sepeda Anda dan menawarkan tingkat interaktivitas yang tidak mudah ditemukan dengan pelatih sepeda.

Kami memanfaatkan kesederhanaan yang tersedia dari mikrokontroler Arduino dan beberapa komponen cetak 3D untuk mengamankan sensor murah ke sepeda yang dipasang di pelatih. Informasi tersebut diteruskan ke video game yang dibuat dengan mesin pembuat game populer, Unity. Pada akhir instruksi ini, Anda harus dapat mengatur sensor Anda sendiri di sepeda Anda dan mentransfer informasi sensor Anda ke Unity. Kami bahkan menyertakan trek tempat Anda dapat berkendara dan menguji set-up baru Anda. Jika Anda tertarik untuk berkontribusi, Anda dapat memeriksa GitHub kami.

Langkah 1: Bahan

Bahan
Bahan

Daftar materi yang Anda perlukan mungkin sedikit berbeda; untuk

contoh, ukuran sepeda Anda akan menentukan panjang kabel jumper yang Anda butuhkan, tetapi inilah bagian utama yang Anda perlukan. Anda mungkin dapat menemukan harga yang lebih murah untuk setiap bagian di situs web seperti AliExpress tetapi menunggu 6 bulan untuk pengiriman tidak selalu merupakan pilihan, jadi gunakan bagian yang sedikit lebih mahal sehingga perkiraannya tidak miring.

1 x Arduino nano ($22.00)

1 x Mini Breadboard ($ 1,33/unit)

1 x 220 Ohm resistor ($1.00/kit)

Potensiometer 1 x 10K ($1,80/unit)

1 x Sensor Hall ($0,96)

Sabuk timing printer 3D 20 cm x 6 mm ($3.33)

1 kit x Berbagai sekrup dan baut M3 Panjang ($ 6,82)

1 x Magnet speedometer sepeda ($0,98)

Kami memasang materi di atas dengan bagian cetak 3D. File yang kami gunakan tercantum di bawah dan diberi nomor dengan konvensi yang sama seperti gambar di awal bagian ini. Semua file dapat ditemukan di Thingiverse. Anda dapat menggunakannya apa adanya tetapi pastikan bahwa dimensi yang kami gunakan cocok dengan sepeda Anda.

1. FrameConnection_PotentiometerHolder_U_Holder.stl

2. FrameConnection_Spacer.stl

3. BreadboardFrameHolder.stl

4. Pulley_PotentiometerSide.stl

5. Pot_PulleyConnection.stl

6. FrameConnection.stl

7. Pulley_HandleBarSide_Print2.stl

8. FrameToHallSensorConnector.stl

9. PotHolder.stl

10. HallSensorAttach.stl

Langkah 2: Membaca dan Mentransfer Data ke Unity

Membaca dan Mentransfer Data ke Unity
Membaca dan Mentransfer Data ke Unity

Kode Arduino dan Unity akan bekerja sama untuk mengumpulkan, mentransfer dan memproses data dari sensor pada sepeda. Unity akan meminta nilai dari Arduino dengan mengirimkan string melalui serial dan menunggu Arduino untuk merespon dengan nilai yang diminta.

Pertama, kita siapkan Arduino dengan library Serial Command yang digunakan untuk mengelola permintaan dari Unity dengan memasangkan string permintaan dengan suatu fungsi. Pengaturan dasar untuk perpustakaan ini dapat dibuat sebagai berikut;

#sertakan "SerialCommand.h"

SerialCommand sCmd; void setup() { sCmd.addCommand("TRIGG", TriggHanlder); Serial.begin(9600); } void loop() { while (Serial.available() > 0) { sCmd.readSerial(); } } void TriggHandler () { /*Membaca dan mengirimkan sensor di sini*/ }

Fungsi TriggHandler dilampirkan ke objek SCmd. Jika serial menerima string yang cocok dengan perintah terlampir (dalam hal ini TRIGG), fungsi TriggHandler dijalankan.

Kami menggunakan potensiometer untuk mengukur arah kemudi dan sensor lorong untuk mengukur putaran per menit sepeda. Pembacaan dari potensiometer dapat dengan mudah dilakukan menggunakan fungsi bawaan dari Arduino. Fungsi TriggHandler kemudian dapat mencetak nilai ke serial dengan perubahan berikut.

batal TriggHandler (){

/*Membaca nilai potensiometer*/ Serial.println(analogRead(ANALOGPIN)); }

Sensor Hall memiliki sedikit pengaturan sebelum kami dapat melakukan pengukuran yang berguna. Berlawanan dengan potensiometer, nilai instan sensor hall tidak terlalu berguna. Karena mencoba mengukur kecepatan roda, waktu antara pemicu adalah yang menarik.

Setiap fungsi yang digunakan dalam kode Arduino membutuhkan waktu dan jika magnet sejajar dengan sensor Hall pada waktu yang salah, pengukuran paling baik dapat ditunda atau paling buruk dilewati seluruhnya. Ini jelas buruk karena Arduino dapat melaporkan kecepatan yang JAUH berbeda dari kecepatan roda yang sebenarnya.

Untuk menghindari hal ini, kami menggunakan fitur Arduino yang disebut attach interrupt yang memungkinkan kami untuk memicu fungsi setiap kali pin digital yang ditunjuk dipicu dengan sinyal yang meningkat. Fungsi rpm_fun dilampirkan ke interupsi dengan satu baris kode ditambahkan ke kode pengaturan.

batalkan pengaturan(){

sCmd.addCommand("TRIGG", TriggHanlder); attachInterrupt(0, rpm_fun, RISING); Serial.begin(9600); } //Fungsi rpm_fun digunakan untuk menghitung kecepatan dan didefinisikan sebagai; unsigned long lastRevolTime = 0; unsigned long revolSpeed = 0; void rpm_fun() { unsigned long revolTime = milis(); deltaTime panjang yang tidak ditandatangani = revolTime - lastRevolTime; /*revolSpeed adalah nilai yang dikirimkan ke kode Arduino*/ revolSpeed = 20000 / deltaTime; lastRevolTime = waktu putaran; } TriggHandler kemudian dapat mengirimkan sisa informasi saat diminta. void TriggHanlder () { /*Membaca nilai potensiometer*/ Serial.println(analogRead(ANALOGPIN)); Serial.println(revolSpeed); }

Kami sekarang memiliki semua blok bangunan yang dapat digunakan untuk membangun kode Arduino yang akan mentransfer data melalui serial ketika permintaan dibuat oleh Unity. Jika Anda ingin memiliki salinan kode lengkapnya, Anda dapat mengunduhnya di GitHub kami. Untuk menguji apakah kode telah diatur dengan benar, Anda dapat menggunakan monitor serial untuk mengirim TRIGG; pastikan Anda mengatur akhir baris ke Carriage return. Bagian selanjutnya akan fokus pada bagaimana skrip Unity kami dapat meminta dan menerima informasi dari Arduino.

Langkah 3: Menerima dan Memproses Data

Menerima dan Memproses Data
Menerima dan Memproses Data

Unity adalah perangkat lunak hebat yang tersedia secara gratis untuk penghobi

tertarik pada pembuatan game; ia hadir dengan sejumlah besar fungsi yang benar-benar dapat menghemat waktu untuk menyiapkan hal-hal tertentu seperti threading atau pemrograman GPU (shading AKA) tanpa membatasi apa yang dapat dilakukan dengan skrip C#. Mikrokontroler Unity dan Arduino dapat digunakan bersama untuk menciptakan pengalaman interaktif yang unik dengan anggaran yang relatif kecil.

Fokus dari instruksi ini adalah untuk membantu mengatur komunikasi antara Unity dan Arduino sehingga kami tidak akan menyelam terlalu dalam ke sebagian besar fitur yang tersedia dengan Unity. Ada banyak tutorial HEBAT untuk persatuan dan komunitas luar biasa yang dapat menjelaskan cara kerja Unity dengan lebih baik. Namun, ada hadiah khusus bagi mereka yang berhasil menyelesaikan instruksi ini yang berfungsi sebagai contoh kecil dari apa yang bisa dilakukan. Anda dapat mengunduh di Github kami upaya pertama kami membuat trek dengan fisika sepeda realistis.

Pertama, mari kita bahas minimal yang harus dilakukan untuk berkomunikasi dengan Arduino melalui serial. Akan segera terlihat bahwa kode ini tidak cocok untuk gameplay tetapi ada baiknya untuk melewati setiap langkah dan mempelajari apa batasannya.

Di Unity, buat adegan baru dengan satu GameObject kosong bernama ArduinoReceive di atase skrip C# yang juga bernama ArduinoReceive. Script ini adalah tempat kita akan menambahkan semua kode yang menangani komunikasi dengan Arduino.

Ada perpustakaan yang harus diakses sebelum kami dapat berkomunikasi dengan port serial komputer Anda; Unity harus diatur agar perpustakaan tertentu dapat digunakan. Pergi ke Edit->ProjectSerring->Player dan di sebelah Api Compatibility Level di bawah Configuration switch. NET 2.0 Subset to. NET 2.0. Sekarang tambahkan kode berikut di bagian atas skrip;

menggunakan System. IO. Ports;

Ini akan memungkinkan Anda mengakses kelas SerialPort yang dapat Anda definisikan sebagai objek ke Kelas ArduinoReceive. Jadikan pribadi untuk menghindari gangguan dari skrip lain.

arduinoPort SerialPort pribadi;

Objek arduinoPort dapat dibuka dengan memilih port yang benar (misalnya di mana USB Arduino terhubung) dan baud rate (yaitu kecepatan pengiriman informasi). Jika Anda tidak yakin di port mana Arduino terpasang, Anda dapat mengetahuinya di pengelola perangkat atau dengan membuka Arduino IDE. Untuk baud rate, nilai default pada sebagian besar perangkat adalah 9600, pastikan Anda memiliki nilai ini dalam kode Arduino Anda dan itu akan berfungsi.

Kode sekarang akan terlihat seperti ini;

menggunakan System. Collections;

menggunakan System. Collections. Generic; menggunakan UnityEngine; menggunakan System. IO. Ports; kelas publik ArduinoReceive: MonoBehaviour { private SerialPort arduinoPort; // Gunakan ini untuk inisialisasi void Start() { arduinoPort = new SerialPort("COM5", 9600); arduinoPort. Buka(); WriteToArduino("TRIGG"); } }

Nomor COM Anda kemungkinan besar akan berbeda. Jika Anda menggunakan MAC, nama COM Anda mungkin memiliki nama yang terlihat seperti ini /dev/cu.wchusbserial1420. Pastikan kode dari bagian 4 diunggah ke Arduino dan monitor serial ditutup untuk sisa bagian ini dan kode ini dikompilasi tanpa masalah.

Sekarang mari kita mengirim permintaan ke Arduino setiap frame dan menulis hasilnya ke jendela konsol. Tambahkan fungsi WriteToArduino ke kelas ArduinoReceive. Pengembalian carriage dan baris baru diperlukan agar kode Arduino dapat mengurai instruksi yang masuk dengan benar.

private void WriteToArduino(pesan string)

{ pesan = pesan + "\r\n"; arduinoPort. Tulis(pesan); arduinoPort. BaseStream. Flush(); }

Fungsi ini kemudian dapat dipanggil dalam loop Update.

batal Perbarui ()

{ WriteToArduino ("TRIGG"); Debug. Log("Nilai Pertama: " + arduinoPort. ReadLine()); Debug. Log("Nilai Kedua: " + arduinoPort. ReadLine()); }

Kode di atas adalah minimum yang Anda butuhkan untuk membaca data dari Arduino. Jika Anda memperhatikan FPS yang diberikan oleh unity, Anda akan melihat penurunan kinerja yang signifikan. Dalam kasus saya, ini berubah dari sekitar 90 FPS tanpa membaca/menulis menjadi 20 FPS. Jika proyek Anda tidak memerlukan pembaruan yang sering, itu mungkin cukup tetapi untuk video game, 20 FPS terlalu rendah. Bagian selanjutnya akan membahas bagaimana Anda dapat meningkatkan kinerja dengan menggunakan multi threading.

Langkah 4: Mengoptimalkan Transfer Data

Bagian sebelumnya membahas cara mengatur dasar

komunikasi antara program Arduino dan Unity. Masalah utama dengan kode ini adalah kinerja. Dalam implementasinya saat ini, Unity harus menunggu Arduino menerima, memproses, dan menjawab permintaan tersebut. Selama waktu itu, kode Unity harus menunggu permintaan selesai dan tidak melakukan apa pun. Kami memecahkan masalah ini dengan membuat utas yang akan menangani permintaan dan menyimpan variabel di utas utama.

Untuk memulai, kita harus menyertakan library threading dengan menambahkan;

menggunakan System. Threading;

Selanjutnya, kami mengatur fungsi yang kami mulai di utas. AsynchronousReadFromArduino dimulai dengan menulis permintaan ke Arduino dengan fungsi WrtieToArduino. Pembacaan diapit dalam blok try-catch, jika batas waktu baca, variabel tetap nol dan fungsi OnArduinoInfoFail dipanggil alih-alih OnArduinoInfoReceive.

Selanjutnya kita mendefinisikan fungsi OnArduinoInfoFail dan OnArduinoInfoReceive. Untuk instruksi ini, kami mencetak hasilnya ke konsol tetapi Anda dapat menyimpan hasilnya ke dalam variabel yang Anda butuhkan untuk proyek Anda.

kekosongan pribadi OnArduinoInfoFail()

{ Debug. Log("Pembacaan gagal"); } private void OnArduinoInfoReceived(rotasi string, kecepatan string) { Debug. Log("Baca Berhasil"); Debug. Log("Nilai Pertama: " + rotasi); Debug. Log("Nilai Kedua: " + kecepatan); }

Langkah terakhir adalah memulai dan menghentikan utas yang akan meminta nilai dari Arduino. Kita harus memastikan bahwa utas terakhir selesai dengan tugas terakhirnya sebelum memulai yang baru. Jika tidak, beberapa permintaan dapat dilakukan ke Arduino pada satu waktu yang dapat membingungkan Arduino/Unity dan menghasilkan hasil yang tidak terduga.

pribadi Thread activeThread = null;

void Update() { if (activeThread == null || !activeThread. IsAlive) { activeThread = Thread baru(AsynchronousReadFromArduino); activeThread. Mulai(); } }

Jika Anda membandingkan kinerja kode dengan yang kami tulis di bagian 5, kinerjanya harus ditingkatkan secara signifikan.

kekosongan pribadi OnArduinoInfoFail()

{ Debug. Log("Pembacaan gagal"); }

Langkah 5: Dimana Selanjutnya?

Dimana Selanjutnya?
Dimana Selanjutnya?

Kami menyiapkan demo yang dapat Anda unduh di Github kami (https://github.com/AlexandreDoucet/InfinityBike), unduh kode dan gimnya, lalu kendarai melalui trek kami. Semuanya disiapkan untuk latihan cepat dan kami berharap ini dapat memberi Anda gambaran tentang apa yang dapat Anda bangun jika Anda menggunakan apa yang kami ajarkan kepada Anda dengan instruksi ini.

Kredit

Kontributor proyek

Alexandre Doucet (_Doucet_)

Maxime Boudreau (MxBoud)

Sumber daya eksternal [Mesin game Unity](https://unity3d.com)

Proyek ini dimulai setelah kami membaca tutorial oleh Allan Zucconi "cara mengintegrasikan Arduino dengan Unity" (https://www.alanzucconi.com/2015/10/07/how-to-int…)

Permintaan dari Arduino ditangani menggunakan perpustakaan SerialCommand (https://github.com/kroimon/Arduino-SerialCommand)

Direkomendasikan: