Talaan ng mga Nilalaman:

Infinity Bike - Sa Loob ng Laro sa Bike Video Game: 5 Hakbang
Infinity Bike - Sa Loob ng Laro sa Bike Video Game: 5 Hakbang

Video: Infinity Bike - Sa Loob ng Laro sa Bike Video Game: 5 Hakbang

Video: Infinity Bike - Sa Loob ng Laro sa Bike Video Game: 5 Hakbang
Video: Kapuso Mo, Jessica Soho: Kilalanin ang munting Stephen Curry ng Bulacan 2024, Setyembre
Anonim
Image
Image
Mga Kagamitan
Mga Kagamitan

Sa panahon ng taglamig, malamig na araw at masamang panahon, ang mga mahilig sa siklista ay mayroon lamang ilang mga pagpipilian upang mag-ehersisyo ang paggawa ng kanilang paboritong isport. Kami ay naghahanap ng isang paraan upang gumawa ng panloob na pagsasanay na may isang bike / trainer setup na medyo mas nakakaaliw ngunit ang karamihan sa magagamit na produkto ay maaaring magastos o simpleng nakakainis na gamitin. Ito ang dahilan kung bakit nagsimula kaming bumuo ng Infinity Bike bilang isang Open Source na video game na pagsasanay. Binabasa ng Infinity bike ang bilis at direksyon mula sa iyong bisikleta at nag-aalok ng antas ng kakayahang makipag-ugnay na hindi madaling makita sa mga trainer ng bisikleta.

Sinasamantala namin ang pagiging simple na magagamit mula sa Arduino microcontroller at ilang mga 3D na naka-print na bahagi upang ma-secure ang mga murang sensor sa isang bisikleta na naka-mount sa isang trainer. Ang impormasyon ay naipadala sa isang video game na ginawa gamit ang sikat na engine sa paggawa ng laro, Unity. Sa pagtatapos ng pagtuturo na ito, dapat mong i-set-up ang iyong sariling mga sensor sa iyong bisikleta at ilipat ang impormasyon ng iyong mga sensor sa Unity. Nagsama pa kami ng isang track kung saan maaari kang sumakay kasama at subukan ang iyong bagong set-up. Kung interesado ka sa pagbibigay maaari kang mag-checkout sa aming GitHub.

Hakbang 1: Mga Kagamitan

Mga Kagamitan
Mga Kagamitan

Ang listahan ng materyal na kakailanganin mo ay maaaring mag-iba nang kaunti; para sa

halimbawa, ang laki ng iyong bisikleta ay magdidikta ng haba ng mga jumper cables na kailangan mo ngunit narito ang mga pangunahing bahagi na kakailanganin mo. Marahil maaari kang makahanap ng mas murang mga presyo para sa bawat piraso sa website tulad ng AliExpress ngunit ang paghihintay ng 6 na buwan para sa pagpapadala ay hindi palaging isang pagpipilian kaya gumagamit ng bahagyang mas mamahaling mga bahagi kaya't ang pagtatantya ay hindi matipid.

1 x Arduino nano ($ 22.00)

1 x Mini Breadboard ($ 1.33 / yunit)

1 x 220 Ohm risistor ($ 1.00 / kit)

1 x 10K Potensyomiter ($ 1.80 / yunit)

1 x Hall sensor ($ 0.96)

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

1 kit x Iba't ibang mga Lenght M3 na turnilyo at bolt ($ 6.82)

1 x Magnet ng speedometer ng bisikleta ($ 0.98)

Inilagay namin ang materyal sa itaas na may mga naka-print na bahagi ng 3D. Ang mga file na ginamit namin ay nakalista sa ibaba at ang mga ito ay may bilang na parehong kombensyon tulad ng imahe sa simula ng seksyong ito. Ang lahat ng mga file ay matatagpuan sa Thingiverse. Maaari mong gamitin ang mga ito bilang-ay ngunit siguraduhin na ang mga sukat na ginamit namin ay tumutugma sa iyong bisikleta.

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

Hakbang 2: Pagbasa at Paglipat ng Data sa Pagkakaisa

Pagbasa at Paglipat ng Data sa Unity
Pagbasa at Paglipat ng Data sa Unity

Ang Arduino at Unity code ay magtutulungan upang mangolekta, ilipat at iproseso ang data mula sa mga sensor sa bisikleta. Hihiling ng pagkakaisa ang halaga mula sa Arduino sa pamamagitan ng pagpapadala ng isang string sa pamamagitan ng serial at maghintay para sa Arduino na tumugon sa mga hiniling na halaga.

Una, ihinahanda namin ang Arduino sa library ng Serial Command na ginagamit upang pamahalaan ang mga kahilingan mula sa Unity sa pamamagitan ng pagpapares ng isang string ng kahilingan na may isang pagpapaandar. Ang isang pangunahing pag-set up para sa library na ito ay maaaring gawin bilang sumusunod;

# isama ang "SerialCommand.h"

SerialCommand sCmd; void setup () {sCmd.addCommand ("TRIGG", TriggHanlder); Serial.begin (9600); } void loop () {habang (Serial.available ()> 0) {sCmd.readSerial (); }} void TriggHandler () {/ * Basahin at ihatid ang mga sensor dito * /}

Ang pagpapaandar na TriggHandler ay nakakabit sa object SCmd. Kung ang serial ay nakakatanggap ng isang string na tumutugma sa nakalakip na utos (sa kasong ito TRIGG), ang function na TriggHandler ay naisakatuparan.

Gumagamit kami ng potentiometer upang sukatin ang direksyon ng pagpipiloto at isang sensor ng bulwagan upang masukat ang pag-ikot bawat minuto ng bisikleta. Ang mga pagbasa mula sa potensyomiter ay maaaring madaling gawin gamit ang mga function na build-in mula sa Arduino. Ang pagpapaandar na TriggHandler ay maaaring i-print ang halaga sa serial na may sumusunod na pagbabago.

walang bisa TriggHandler () {

/ * Pagbasa ng halaga ng potentiometer * / Serial.println (analogRead (ANALOGPIN)); }

Ang sensor ng Hall ay may kaunti pang pagse-set up bago kami magkaroon ng mga kapaki-pakinabang na sukat. Taliwas sa potensyomiter, ang instant na halaga ng sensor ng bulwagan ay hindi masyadong kapaki-pakinabang. Dahil sinusubukang sukatin ang bilis ng gulong, ang oras sa pagitan ng mga nagpapalit ay ang interesado.

Ang bawat pag-andar na ginamit sa Arduino code ay tumatagal ng oras at kung ang mga linya ng magnet kasama ang sensor ng Hall sa maling oras ang pagsukat ay maaaring maantala nang pinakamahusay o lumaktaw ng lubos sa pinakamasama. Malinaw na masama ito sapagkat ang Arduino ay maaaring mag-ulat ng isang bilis na MAHAL na naiiba kaysa sa aktwal na bilis ng gulong.

Upang maiwasan ito, gumagamit kami ng isang tampok ng Arduinos na tinatawag na attach interrupt na nagbibigay-daan sa amin upang magpalitaw ng isang function tuwing ang isang itinalagang digital pin ay na-trigger ng isang tumataas na signal. Ang pagpapaandar rpm_fun ay nakakabit sa isang nakakagambala sa isang solong linya ng code na naidagdag sa setup code.

walang bisa ang pag-setup () {

sCmd.addCommand ("TRIGG", TriggHanlder); attachInterrupt (0, rpm_fun, RISING); Serial.begin (9600); } // Ang pagpapaandar rpm_fun ay ginagamit upang makalkula ang bilis at tinukoy bilang; unsigned long lastRevolTime = 0; unsigned mahabang revolSpeed = 0; void rpm_fun () {unsigned long revolTime = millis (); unsigned mahabang deltaTime = revolTime - lastRevolTime; / * Ang revolSpeed ay ang halagang nailipat sa Arduino code * / revolSpeed = 20000 / deltaTime; lastRevolTime = revolTime; } Pagkatapos ay maipadala ng TriggHandler ang natitirang impormasyon kapag hiniling. void TriggHanlder () {/ * Pagbasa ng halaga ng potentiometer * / Serial.println (analogRead (ANALOGPIN)); Serial.println (revolSpeed); }

Mayroon na kaming lahat ng mga bloke ng gusali na maaaring magamit upang mabuo ang Arduino code na maglilipat ng data sa pamamagitan ng serial sa kapag ang isang kahilingan ay ginawa ng Unity. Kung nais mong magkaroon ng isang kopya ng buong code, maaari mo itong i-download sa aming GitHub. Upang masubukan kung maayos ang pag-set up ng code, maaari mong gamitin ang serial monitor upang magpadala ng TRIGG; tiyaking itinakda mo ang linya na nagtatapos sa pagbabalik ng Karwahe. Ang susunod na seksyon ay magtutuon sa kung paano maaaring humiling ang aming mga script ng Unity at matanggap ang impormasyon mula sa Arduino.

Hakbang 3: Pagtanggap at Pagproseso ng Data

Pagtanggap at Pagproseso ng Data
Pagtanggap at Pagproseso ng Data

Ang Unity ay isang mahusay na magagamit na software nang libre sa hobbyist

interesado sa paggawa ng laro; ito ay may isang malaking bilang ng mga pag-andar na maaaring talagang bawasan ang oras sa pag-set up ng ilang mga bagay tulad ng threading o GPU program (AKA shading) nang hindi nililimitahan ang maaaring gawin sa mga C # script. Ang Unity at Arduino microcontrollers ay maaaring magamit nang magkasama upang lumikha ng natatanging mga interactive na karanasan na may isang maliit na badyet.

Ang pokus ng itinuturo na ito ay upang matulungan ang pag-set up ng komunikasyon sa pagitan ng Unity at ng Arduino kaya't hindi kami masyadong sumisid sa karamihan sa mga tampok na magagamit sa Unity. Mayroong maraming mga DAKILANG mga tutorial para sa pagkakaisa at isang hindi kapani-paniwala na pamayanan na maaaring gumawa ng isang mas mahusay na trabaho na nagpapaliwanag kung paano gumagana ang Unity. Gayunpaman, mayroong isang espesyal na premyo para sa mga namamahala upang gumana ang kanilang paraan sa pamamagitan ng pagtuturo na ito na nagsisilbing isang maliit na showcase ng kung ano ang maaaring gawin. Maaari mong i-download sa aming Github ang aming unang pagtatangka ng paggawa ng isang track na may makatotohanang pisika ng bisikleta.

Una, dumaan tayo sa walang bayad na minimum na dapat gawin upang makipag-usap sa isang Arduino sa pamamagitan ng serial. Mabilis na malilinaw na ang code na ito ay hindi angkop sa gameplay ngunit mahusay na dumaan sa bawat hakbang at alamin kung ano ang mga limitasyon.

Sa Unity, lumikha ng isang bagong eksena na may isang solong walang laman na GameObject na pinangalanang ArduinoReceive sa paglakip ng isang C # script na pinangalanang ArduinoReceive din. Ang script na ito ay kung saan idaragdag namin ang lahat ng code na humahawak sa komunikasyon sa Arduino.

Mayroong isang silid-aklatan na dapat na ma-access bago kami makipag-usap sa mga serial port ng iyong computer; Ang pagkakaisa ay dapat na-set-up upang payagan ang ilang mga aklatan na magamit. Pumunta sa Edit-> ProjectSerring-> Player at sa tabi ng Antas ng Api Compatibility sa ilalim ng Configuration switch. NET 2.0 Subset sa. NET 2.0. Idagdag ngayon ang sumusunod na code sa tuktok ng script;

gamit ang System. IO. Ports;

Papayagan ka nitong ma-access ang klase ng SerialPort na maaari mong tukuyin bilang isang object sa ArduinoReceive Class. Gawin itong pribado upang maiwasan ang anumang pagkagambala mula sa ibang script.

pribadong SerialPort arduinoPort;

Ang object arduinoPort ay maaaring mabuksan sa pamamagitan ng pagpili ng tamang port (hal. Kung saan ang USB ay nakakonekta ang Arduino) at isang rate ng baud (ibig sabihin ang bilis kung saan ipinadala ang impormasyon). Kung hindi ka sigurado sa aling port ang Arduino ay naka-plug in maaari mong malaman alinman sa manager ng aparato o sa pamamagitan ng pagbubukas ng Arduino IDE. Para sa rate ng baud, ang default na halaga sa karamihan ng aparato ay 9600, tiyakin lamang na mayroon ka ng halagang ito sa iyong Arduino code at dapat itong gumana.

Ang code ay dapat magmukhang ganito;

gamit ang System. Collection;

gamit ang System. Collection. Generic; gamit ang UnityEngine; gamit ang System. IO. Ports; pampublikong klase ArduinoReceive: MonoBehaviour {pribadong SerialPort arduinoPort; // Use this for initialization void Start () {arduinoPort = new SerialPort ("COM5", 9600); arduinoPort. Open (); IsulatToArduino ("TRIGG"); }}

Ang iyong numero sa COM ay malamang na magkakaiba. Kung nasa isang MAC ka, ang pangalan mo sa COM ay maaaring magkaroon ng isang pangalan na katulad nito /dev/cu.wchusbserial1420. Tiyaking ang code mula sa seksyon 4 ay na-upload sa Arduino at ang serial monitor ay sarado para sa natitirang bahagi ng seksyon na ito at ang code na ito ay naiipon nang walang problema.

Magpadala na tayo ng isang kahilingan sa Arduino bawat frame at isulat ang mga resulta sa window ng console. Idagdag ang pagpapaandar ng WritingToArduino sa klase ng ArduinoReceive. Ang pagbalik ng karwahe at bagong linya ay kinakailangan para sa Arduino code upang ma-parse nang maayos ang papasok na tagubilin.

pribadong walang bisa na WritingToArduino (mensahe ng string)

{message = message + "\ r / n"; arduinoPort. Write (mensahe); arduinoPort. BaseStream. Flush (); }

Ang pagpapaandar na ito ay maaaring tawaging sa Update loop.

walang bisa ang Pag-update ()

{WritingToArduino ("TRIGG"); Debug. Log ("Unang Halaga:" + arduinoPort. ReadLine ()); Debug. Log ("Pangalawang Halaga:" + arduinoPort. ReadLine ()); }

Ang code sa itaas ay ang hubad na minimum na kailangan mo upang mabasa ang data mula sa isang Arduino. Kung bigyang-pansin mo ang FPS na ibinigay ng pagkakaisa, dapat mong makita ang isang makabuluhang pagbaba ng pagganap. Sa aking kaso, nagmumula ito sa paligid ng 90 FPS nang hindi binabasa / sumusulat sa 20 FPS. Kung ang iyong proyekto ay hindi nangangailangan ng madalas na pag-update maaaring sapat ito ngunit para sa isang video game, ang 20 FPS ay masyadong mababa. Saklaw ng susunod na seksyon kung paano mo mapapabuti ang pagganap sa pamamagitan ng paggamit ng multi threading.

Hakbang 4: Pag-optimize ng Paglipat ng Data

Saklaw ng nakaraang seksyon kung paano mag-set-up ng pangunahing kaalaman

komunikasyon sa pagitan ng Arduino at Unity program. Ang pangunahing problema sa code na ito ay ang pagganap. Sa kasalukuyang pagpapatupad nito, kailangang maghintay ang Unity para matanggap, maproseso at sagutin ng Arduino ang kahilingan. Sa panahong iyon, ang code ng Unity ay kailangang maghintay para matapos ang kahilingan at wala nang iba pa. Nalutas namin ang isyung ito sa pamamagitan ng paglikha ng isang thread na hahawak sa mga kahilingan at maiimbak ang variable sa pangunahing thread.

Upang magsimula, dapat naming isama ang threading library sa pamamagitan ng pagdaragdag;

gamit ang System. Threading;

Susunod, na-set up namin ang pagpapaandar na nagsisimula kami sa mga thread. Nagsisimula ang AsynchronousReadFromArduino sa pamamagitan ng pagsulat ng kahilingan sa Arduino gamit ang paggana ng WrtieToArduino. Ang pagbabasa ay nakapaloob sa isang try-catch bloc, kung ang readout timeout, mananatiling null ang mga variable at ang OnArduinoInfoFail function ay tinawag sa halip na OnArduinoInfoReceive.

Susunod na tinukoy namin ang mga pagpapaandar ng OnArduinoInfoFail at OnArduinoInfoReceive. Para sa pagtuturo na ito, nai-print namin ang mga resulta sa console ngunit maaari mong iimbak ang mga resulta sa mga variable na kailangan mo para sa iyong proyekto.

pribadong walang bisa ang OnArduinoInfoFail ()

{Debug. Log ("Nabigo ang pagbabasa"); } pribadong walang bisa na OnArduinoInfoReceived (pag-ikot ng string, bilis ng string) {Debug. Log ("Readin Sucessfull"); Debug. Log ("Unang Halaga:" + pag-ikot); Debug. Log ("Pangalawang Halaga:" + bilis); }

Ang huling hakbang ay upang simulan at ihinto ang mga thread na hihilingin ang mga halaga mula sa Arduino. Dapat naming tiyakin na ang huling thread ay tapos na sa huling gawain nito bago magsimula ng bago. Kung hindi man, maraming mga kahilingan ang maaaring gawin sa Arduino sa isang solong oras na maaaring malito ang Arduino / Unity at magbunga ng hindi mahuhulaan na mga resulta.

pribadong Thread na aktiboThread = null;

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

Kung ihinahambing mo ang pagganap ng code sa sinulat namin sa seksyon 5, dapat na napabuti nang mahusay ang pagganap.

pribadong walang bisa ang OnArduinoInfoFail ()

{Debug. Log ("Nabigo ang pagbabasa"); }

Hakbang 5: Saan Susunod?

Saan Susunod
Saan Susunod

Naghanda kami ng isang demo na maaari mong i-download sa aming Github (https://github.com/AlexandreDoucet/InfinityBike), i-download ang code at ang laro at sumakay sa aming track. Naka-set up na ang lahat para sa isang mabilis na pag-eehersisyo at inaasahan naming mabibigyan ka nito ng isang lasa ng kung ano ang maitatayo mo kung gagamitin mo ang itinuro namin sa iyo sa pagtuturo na ito.

Mga Kredito

Mga nagbibigay ng proyekto

Alexandre Doucet (_Doucet_)

Maxime Boudreau (MxBoud)

Mga panlabas na ressource [Ang engine ng laro ng Unity] (https://unity3d.com)

Nagsimula ang proyektong ito pagkatapos naming mabasa ang tutorial ni Allan Zucconi "kung paano isama ang Arduino sa Unity" (https://www.alanzucconi.com/2015/10/07/how-to-int…)

Ang kahilingan mula sa Arduino ay pinangangasiwaan gamit ang SerialCommand library (https://github.com/kroimon/Arduino-SerialCommand)

Inirerekumendang: