Turinys:

„Infinity Bike“- dviračių treniruočių patalpose vaizdo žaidimas: 5 žingsniai
„Infinity Bike“- dviračių treniruočių patalpose vaizdo žaidimas: 5 žingsniai

Video: „Infinity Bike“- dviračių treniruočių patalpose vaizdo žaidimas: 5 žingsniai

Video: „Infinity Bike“- dviračių treniruočių patalpose vaizdo žaidimas: 5 žingsniai
Video: E-Fit Infinity cycling 2024, Rugsėjis
Anonim
Image
Image
Medžiagos
Medžiagos

Žiemos sezonų, šaltų dienų ir blogo oro metu dviratininkų entuziastai turi tik keletą galimybių sportuoti užsiimdami mėgstama sporto šaka. Mes ieškojome būdų, kaip padaryti treniruotes patalpose su dviračių/treniruoklių sąranka šiek tiek linksmesnėmis, tačiau dauguma turimų produktų yra brangūs arba tiesiog nuobodūs. Štai kodėl mes pradėjome kurti „Infinity Bike“kaip atvirojo kodo mokomąjį vaizdo žaidimą. „Infinity“dviratis nuskaito greitį ir kryptį iš jūsų dviračio ir siūlo interaktyvumo lygį, kurio negalima lengvai rasti naudojant dviračių treniruoklius.

Mes naudojame paprastumą, kurį siūlo „Arduino“mikrovaldiklis, ir keletą 3D spausdintų dalių, kad nebrangūs jutikliai būtų pritvirtinti prie treniruoklio pritvirtinto dviračio. Informacija perduodama vaizdo žaidimui, sukurtam naudojant populiarų žaidimų kūrimo variklį „Unity“. Pasibaigus šiai instrukcijai, turėtumėte sugebėti savo dviračiu nustatyti savo jutiklius ir perduoti jutiklių informaciją „Unity“. Mes netgi įtraukėme takelį, kuriuo galite važiuoti ir išbandyti savo naują sąranką. Jei norite prisidėti, galite patikrinti mūsų „GitHub“.

1 žingsnis: medžiagos

Medžiagos
Medžiagos

Medžiagų sąrašas, kurio jums reikės, gali šiek tiek skirtis; dėl

Pavyzdžiui, jūsų dviračio dydis diktuos jums reikalingų jungiamųjų kabelių ilgį, tačiau čia yra pagrindinės dalys, kurių jums reikės. Tikriausiai svetainėje, pvz., „AliExpress“, galite rasti pigesnių kainų už kiekvieną gabalą, tačiau laukti pristatymo 6 mėnesius ne visada yra galimybė, todėl naudojote šiek tiek brangesnes dalis, todėl įvertinimas nėra iškreiptas.

1 x „Arduino nano“(22,00 USD)

1 x mini duonos lenta (1,33 USD už vienetą)

1 x 220 omų rezistorius (1,00 USD/rinkinys)

1 x 10K potenciometras (1,80 USD už vienetą)

1 x salės jutiklis (0,96 USD)

20 cm x 6 mm 3D spausdintuvo paskirstymo diržas (3,33 USD)

1 komplektas x įvairaus ilgio M3 varžtai ir varžtai (6,82 USD)

1 x dviračio spidometro magnetas (0,98 USD)

Aukščiau esančią medžiagą sumontavome 3D spausdintomis dalimis. Mūsų naudojami failai yra išvardyti žemiau ir sunumeruoti ta pačia tvarka kaip ir paveikslėlis šio skyriaus pradžioje. Visus failus galite rasti „Thingiverse“. Galite juos naudoti tokius, kokie yra, tačiau įsitikinkite, kad mūsų naudojami matmenys atitinka jūsų dviratį.

1. FrameConnection_PotentiometerHolder_U_Holder.stl

2. FrameConnection_Spacer.stl

3. BreadboardFrameHolder.stl

4. Skriemulys_PotentiometerSide.stl

5. Pot_PulleyConnection.stl

6. FrameConnection.stl

7. Skriemulio_ rankenosBarSide_Print2.stl

8. FrameToHallSensorConnector.stl

9. PotHolder.stl

10. HallSensorAttach.stl

2 žingsnis: duomenų skaitymas ir perkėlimas į „Unity“

Duomenų skaitymas ir perdavimas „Unity“
Duomenų skaitymas ir perdavimas „Unity“

„Arduino“ir „Unity“kodas veiks kartu, kad surinktų, perduoti ir apdoroti dviračio jutiklių duomenis. „Unity“paprašys vertės iš „Arduino“, išsiųsdama eilutę per seriją ir palauks, kol „Arduino“atsakys nurodytomis vertėmis.

Pirma, mes paruošiame „Arduino“su bibliotekos serijos komanda, kuri naudojama „Unity“užklausoms valdyti, suporuojant užklausos eilutę su funkcija. Pagrindinė šios bibliotekos sąranka gali būti atlikta taip;

#include "SerialCommand.h"

SerialCommand sCmd; void setup () {sCmd.addCommand ("TRIGG", TriggHanlder); Serial.begin (9600); } void loop () {while (Serial.available ()> 0) {sCmd.readSerial (); }} void TriggHandler () { /*Čia skaitykite ir perduokite jutiklius* /}

Funkcija TriggHandler pridedama prie objekto SCmd. Jei serialas gauna eilutę, atitinkančią pridėtą komandą (šiuo atveju TRIGG), vykdoma funkcija TriggHandler.

Mes naudojame potenciometrą vairo krypčiai matuoti, o salės jutiklį - dviračio sukimosi per minutę matavimui. Potenciometro rodmenis galima lengvai atlikti naudojant „Arduino“integruotas funkcijas. Funkcija „TriggHandler“gali atspausdinti serijos vertę, atlikus šiuos pakeitimus.

void TriggHandler () {

/*Potenciometro vertės skaitymas*/ Serial.println (analogRead (ANALOGPIN)); }

„Hall“jutiklis turi šiek tiek daugiau nustatymų, kad galėtume atlikti naudingus matavimus. Priešingai nei potenciometras, momentinė salės jutiklio vertė nėra labai naudinga. Bandant išmatuoti rato greitį, domina laikas tarp paleidiklių.

Kiekviena „Arduino“kodu naudojama funkcija užtrunka ir, jei magnetas netinkamu laiku sutampa su „Hall“jutikliu, matavimas geriausiu atveju gali būti atidėtas arba blogiausiu atveju visiškai praleistas. Akivaizdu, kad tai blogai, nes „Arduino“gali pranešti greitį, kuris yra daug kitoks nei tikrasis rato greitis.

Norėdami to išvengti, mes naudojame „Arduinos“funkciją, vadinamą prijungimo pertraukimu, kuri leidžia mums suaktyvinti funkciją, kai suaktyvinamas signalas, kai įjungiamas nurodytas skaitmeninis kaištis. Funkcija rpm_fun pridedama prie pertraukos, prie sąrankos kodo pridedama viena kodo eilutė.

void setup () {

sCmd.addCommand („TRIGG“, „TriggHanlder“); attachInterrupt (0, rpm_fun, RISING); Serial.begin (9600); } // Funkcija rpm_fun naudojama greičiui apskaičiuoti ir apibrėžiama kaip; unsigned long lastRevolTime = 0; nepasirašytas ilgas apsisukimų greitis = 0; void rpm_fun () {unsigned long revolTime = millis (); nepasirašytas ilgas deltaTime = revolTime - lastRevolTime; /*revolSpeed yra vertė, perduodama Arduino kodui* / revolSpeed = 20000 / deltaTime; lastRevolTime = revolTime; } Tada „TriggHandler“paprašius gali perduoti likusią informaciją. void TriggHanlder () { /*Potenciometro vertės skaitymas* / Serial.println (analogRead (ANALOGPIN)); Serial.println (revolSpeed); }

Dabar mes turime visus statybinius blokus, kurie gali būti naudojami kuriant „Arduino“kodą, kuris perduos duomenis serijiniu būdu į „Unity“užklausą. Jei norite turėti viso kodo kopiją, galite ją atsisiųsti iš mūsų „GitHub“. Norėdami patikrinti, ar kodas buvo tinkamai nustatytas, galite naudoti serijinį monitorių, kad išsiųstumėte TRIGG; būtinai nustatykite eilutės pabaigą į vežimo grįžimą. Kitame skyriuje bus kalbama apie tai, kaip mūsų „Unity“scenarijai gali prašyti ir gauti informacijos iš „Arduino“.

3 žingsnis: Duomenų priėmimas ir apdorojimas

Duomenų priėmimas ir apdorojimas
Duomenų priėmimas ir apdorojimas

„Unity“yra puiki programinė įranga, prieinama nemokamai mėgėjams

domisi žaidimų kūrimu; jis turi daugybę funkcijų, kurios tikrai gali sutrumpinti laiką nustatant tam tikrus dalykus, tokius kaip sriegis ar GPU programavimas (AKA šešėlis), neribojant to, ką galima padaryti naudojant „C#“scenarijus. „Unity“ir „Arduino“mikrovaldikliai gali būti naudojami kartu, kad būtų sukurta unikali interaktyvi patirtis su palyginti nedideliu biudžetu.

Šios instrukcijos tikslas yra padėti užmegzti ryšį tarp „Unity“ir „Arduino“, kad mes pernelyg nesigilintume į daugumą „Unity“funkcijų. Yra daug puikių vienybės ir neįtikėtinos bendruomenės vadovėlių, kurie galėtų padaryti daug geresnį darbą, paaiškindami, kaip veikia „Unity“. Tačiau tiems, kurie sugeba įveikti šią pamoką, yra specialus prizas, kuris parodo, ką galima padaryti. Iš mūsų „Github“galite atsisiųsti mūsų pirmąjį bandymą sukurti takelį su tikroviška dviračių fizika.

Pirma, pereikime prie minimalaus minimumo, kurį reikia padaryti norint bendrauti su „Arduino“per serialą. Greitai paaiškės, kad šis kodas netinka žaidimui, tačiau gerai pereiti kiekvieną žingsnį ir sužinoti, kokie yra apribojimai.

„Unity“sukurkite naują sceną naudodami vieną tuščią „GameObject“, pavadintą „ArduinoRecept“, pridėdami C# scenarijų, taip pat pavadintą „ArduinoRecept“. Šiame scenarijuje pridėsime visą kodą, kuris tvarko ryšį su „Arduino“.

Yra biblioteka, prie kurios reikia turėti prieigą, kad galėtume bendrauti su jūsų kompiuterio nuosekliais prievadais; „Unity“turi būti nustatyta tam, kad būtų galima naudoti tam tikras bibliotekas. Eikite į Redaguoti-> „ProjectSerring-> Player“ir šalia „Api“suderinamumo lygio, esantį konfigūracijos jungiklyje. NET 2.0 pogrupis į. NET 2.0. Dabar pridėkite šį kodą scenarijaus viršuje;

naudojant System. IO. Ports;

Tai leis jums pasiekti „SerialPort“klasę, kurią galėtumėte apibrėžti kaip „ArduinoRecept“klasės objektą. Padarykite jį privačiu, kad išvengtumėte bet kokio kito scenarijaus trukdžių.

privatus SerialPort arduinoPort;

Objektą arduinoPort galima atidaryti pasirinkus tinkamą prievadą (pvz., Prie kurio USB prijungtas „Arduino“) ir duomenų perdavimo spartą (t. Y. Informacijos siuntimo greitį). Jei nesate tikri, kuriame prievade yra prijungtas „Arduino“, tai galite sužinoti įrenginių tvarkytuvėje arba atidarę „Arduino IDE“. Numatytoji duomenų perdavimo spartos vertė daugelyje įrenginių yra 9600, tiesiog įsitikinkite, kad ši vertė yra jūsų „Arduino“kode ir ji turėtų veikti.

Kodas dabar turėtų atrodyti taip;

naudojant System. Collections;

naudojant System. Collections. Generic; naudojant „UnityEngine“; naudojant System. IO. Ports; viešoji klasė ArduinoRecept: MonoBehaviour {private SerialPort arduinoPort; // Naudokite tai inicijuodami void Start () {arduinoPort = new SerialPort ("COM5", 9600); arduinoPort. Open (); „WriteToArduino“(„TRIGG“); }}

Jūsų COM numeris greičiausiai bus kitoks. Jei naudojate MAC, jūsų COM pavadinimas gali atrodyti taip /dev/cu.wchusbserial1420. Įsitikinkite, kad kodas iš 4 skyriaus yra įkeltas į „Arduino“, o serijinis monitorius yra uždarytas likusiai šio skyriaus daliai ir kad šis kodas susideda be problemų.

Dabar siųskime užklausą „Arduino“kiekvienam kadrui ir įrašykite rezultatus į konsolės langą. Pridėkite „WriteToArduino“funkciją prie klasės „ArduinoRecept“. Vežimo grąžinimas ir nauja eilutė yra būtini, kad „Arduino“kodas tinkamai išanalizuotų gaunamą instrukciją.

private void WriteToArduino (eilutės pranešimas)

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

Šią funkciją galima iškviesti atnaujinimo cikle.

negaliojantis atnaujinimas ()

{WriteToArduino („TRIGG“); Debug. Log ("Pirma vertė:" + arduinoPort. ReadLine ()); Debug. Log ("Antroji vertė:" + arduinoPort. ReadLine ()); }

Aukščiau pateiktas kodas yra minimalus minimumas, kurio reikia norint perskaityti „Arduino“duomenis. Jei daug dėmesio skirsite vienybės FPS, turėtumėte pastebėti didelį našumo sumažėjimą. Mano atveju jis svyruoja nuo maždaug 90 kadrų per sekundę be skaitymo/rašymo iki 20 kadrų per sekundę. Jei jūsų projektui nereikia dažnai atnaujinti, to gali pakakti, tačiau vaizdo žaidimui 20 kadrų per sekundę yra per mažai. Kitame skyriuje bus aptarta, kaip galite pagerinti našumą naudodami kelių sriegių sriegimą.

4 žingsnis: optimizuokite duomenų perdavimą

Ankstesniame skyriuje buvo aprašyta, kaip nustatyti pagrindinius

bendravimas tarp „Arduino“ir „Unity“programos. Pagrindinė šio kodo problema yra našumas. Šiuo metu „Unity“turi laukti, kol „Arduino“gaus, apdoros ir atsakys į užklausą. Per tą laiką „Unity“kodas turi laukti, kol bus įvykdytas prašymas, ir nieko daugiau nedaro. Mes išsprendėme šią problemą sukurdami giją, kuri apdoros užklausas ir išsaugos kintamąjį pagrindinėje gijoje.

Norėdami pradėti, turime įtraukti siūlų biblioteką pridėdami;

naudojant „System. Threading“;

Tada mes nustatome funkciją, kurią pradedame gijose. AsynchronousReadFromArduino prasideda rašant užklausą „Arduino“naudojant funkciją „WrtieToArduino“. Skaitymas yra įtrauktas į „try-catch“bloką, jei nuskaitymo laikas baigėsi, kintamieji lieka nuliniai ir vietoj „OnArduinoInfoRecept“iškviečiama „OnArduinoInfoFail“funkcija.

Toliau apibrėžiame „OnArduinoInfoFail“ir „OnArduinoInfoRecept“funkcijas. Norėdami tai padaryti, spausdiname rezultatus konsolėje, tačiau galite išsaugoti rezultatus kintamuosiuose, kurių jums reikia projektui.

private void OnArduinoInfoFail ()

{Debug. Log ("Nepavyko perskaityti"); } private void OnArduinoInfoReceived (eilutės sukimas, eilutės greitis) {Debug. Log ("Readin Successfull"); Debug. Log ("Pirmoji vertė:" + sukimas); Debug. Log ("Antroji vertė:" + greitis); }

Paskutinis žingsnis yra pradėti ir sustabdyti gijas, kurios paprašys „Arduino“reikšmių. Prieš pradėdami naują, turime užtikrinti, kad paskutinė gija būtų atlikta su paskutine užduotimi. Priešingu atveju „Arduino“vienu metu gali būti pateiktos kelios užklausos, o tai gali supainioti „Arduino“/„Unity“ir duoti nenuspėjamų rezultatų.

private Thread activeThread = null;

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

Jei palyginsite kodo našumą su kodu, kurį parašėme 5 skyriuje, našumas turėtų būti žymiai pagerintas.

private void OnArduinoInfoFail ()

{Debug. Log ("Nepavyko perskaityti"); }

5 žingsnis: kur toliau?

Kur toliau?
Kur toliau?

Paruošėme demonstracinę versiją, kurią galite atsisiųsti iš mūsų „Github“(https://github.com/AlexandreDoucet/InfinityBike), atsisiųsti kodą ir žaidimą bei važiuoti per mūsų takelį. Viskas paruošta greitai treniruotėms ir tikimės, kad tai suteiks jums galimybę paragauti, ką galėtumėte sukurti, jei pasinaudosite tuo, ką išmokėme, naudodamiesi šia instrukcija.

Kreditai

Projekto bendraautoriai

Alexandre Doucet (_Doucet_)

Maksimas Boudreau („MxBoud“)

Išoriniai ištekliai [„The Unity“žaidimo variklis] (https://unity3d.com)

Šis projektas prasidėjo perskaičius Allano Zucconi vadovėlį „Kaip integruoti„ Arduino “su„ Unity ““(https://www.alanzucconi.com/2015/10/07/how-to-int…)

„Arduino“užklausa tvarkoma naudojant „SerialCommand“biblioteką (https://github.com/kroimon/Arduino-SerialCommand)

Rekomenduojamas: