Sadržaj:

Infinity Bike - Video igra za trening bicikala u zatvorenom prostoru: 5 koraka
Infinity Bike - Video igra za trening bicikala u zatvorenom prostoru: 5 koraka

Video: Infinity Bike - Video igra za trening bicikala u zatvorenom prostoru: 5 koraka

Video: Infinity Bike - Video igra za trening bicikala u zatvorenom prostoru: 5 koraka
Video: Мега заброшенный курорт Майами-Бич - здесь выступали The Beatles! 2024, Jun
Anonim
Image
Image
Materijali
Materijali

Tokom zimskih sezona, hladnih dana i lošeg vremena, ljubitelji biciklista imaju samo nekoliko mogućnosti za vježbanje baveći se svojim omiljenim sportom. Tražili smo način da učinimo trening u zatvorenom sa postavkom bicikla/trenažera malo zabavnijim, ali većina dostupnih proizvoda je ili skupa ili jednostavno dosadna za upotrebu. Zbog toga smo počeli razvijati Infinity Bike kao video igricu za vježbanje otvorenog koda. Infinity bike čita brzinu i smjer s vašeg bicikla i nudi razinu interaktivnosti koju nije lako pronaći s trenerima za bicikle.

Iskoristili smo jednostavnost koja je dostupna od Arduino mikrokontrolera i nekoliko 3D ispisanih dijelova za pričvršćivanje jeftinih senzora na bicikl montiran na trenažeru. Informacije se prenose u video igru napravljenu sa popularnim mehanizmom za pravljenje igara, Unity. Do kraja ovog uputstva trebali biste moći postaviti vlastite senzore na svom biciklu i prenijeti podatke svojih senzora na Unity. Uključili smo čak i stazu na kojoj se možete provozati i isprobati svoju novu postavku. Ako ste zainteresirani za doprinos, možete posjetiti naš GitHub.

Korak 1: Materijali

Materijali
Materijali

Lista materijala koja će vam trebati može se malo razlikovati; for

na primjer, veličina vašeg bicikla će diktirati dužinu kablova koji vam trebaju, ali evo glavnih dijelova koji će vam trebati. Vjerojatno biste mogli pronaći jeftinije cijene za svaki komad na web stranici poput AliExpressa, ali čekanje od 6 mjeseci na isporuku nije uvijek opcija, pa ste koristili nešto skuplje dijelove, pa se procjena ne mijenja.

1 x Arduino nano (22,00 USD)

1 x mini ploča (1,33 USD/jedinici)

1 x 220 Ohm otpornik (1,00 USD/komplet)

1 x 10K potenciometar (1,80 USD/jedinici)

1 x Hall senzor (0,96 USD)

Zupčasti kaiš za 3D štampač 20 cm x 6 mm (3,33 USD)

1 komplet x M3 vijci i vijci različite dužine (6,82 USD)

1 x magnet za brzinomjer bicikla (0,98 USD)

Gornji materijal smo montirali pomoću 3D štampanih dijelova. Datoteke koje smo koristili navedene su ispod i označene su istim brojem kao slika na početku ovog odjeljka. Sve datoteke možete pronaći na Thingiverse -u. Možete ih koristiti kakve jesu, ali pazite da dimenzije koje smo koristili odgovaraju vašem biciklu.

1. FrameConnection_PotenciometerHolder_U_Holder.stl

2. FrameConnection_Spacer.stl

3. BreadboardFrameHolder.stl

4. Remenica_potenciometraSide.stl

5. Pot_PulleyConnection.stl

6. FrameConnection.stl

7. Pulley_HandleBarSide_Print2.stl

8. FrameToHallSensorConnector.stl

9. PotHolder.stl

10. HallSensorAttach.stl

Korak 2: Čitanje i prijenos podataka u Unity

Čitanje i prijenos podataka u Unity
Čitanje i prijenos podataka u Unity

Arduino i Unity kôd će zajedno raditi na prikupljanju, prijenos i obrada podataka sa senzora na biciklu. Unity će zatražiti vrijednost od Arduina slanjem niza kroz serijski broj i čekati da Arduino odgovori sa traženim vrijednostima.

Prvo, pripremamo Arduino s bibliotečkom serijskom naredbom koja se koristi za upravljanje zahtjevima iz Unityja uparivanjem niza zahtjeva s funkcijom. Osnovno postavljanje za ovu biblioteku može se izvršiti na sljedeći način;

#include "SerialCommand.h"

SerialCommand sCmd; void setup () {sCmd.addCommand ("TRIGG", TriggHanlder); Serial.begin (9600); } void loop () {while (Serial.available ()> 0) {sCmd.readSerial (); }} void TriggHandler () { /*Ovdje pročitajte i prenesite senzore* /}

Funkcija TriggHandler je pridružena objektu SCmd. Ako serijski broj primi niz koji odgovara priloženoj naredbi (u ovom slučaju TRIGG), izvršava se funkcija TriggHandler.

Koristimo potenciometar za mjerenje smjera upravljanja i senzor Halla za mjerenje rotacije bicikla u minuti. Očitavanja s potenciometra mogu se lako izvršiti pomoću ugrađenih funkcija iz Arduina. Funkcija TriggHandler tada može ispisati vrijednost u serijsku poruku sa sljedećom promjenom.

void TriggHandler () {

/*Očitavanje vrijednosti potenciometra*/ Serial.println (analogno čitanje (ANALOGPIN)); }

Hall senzor ima malo više podešavanja prije nego što možemo imati korisna mjerenja. Za razliku od potenciometra, trenutna vrijednost senzora u predvorju nije jako korisna. Budući da su pokušavali izmjeriti brzinu kotača, vrijeme između okidača je ono što je zanimalo.

Za svaku funkciju koja se koristi u Arduino kodu potrebno je vrijeme, a ako se magnet poravna s Hall -ovim senzorom u pogrešno vrijeme, mjerenje bi se u najboljem slučaju moglo odgoditi ili u najgorem slučaju preskočiti. To je očito loše jer bi Arduino mogao prijaviti brzinu koja se MNOGO razlikuje od stvarne brzine kotača.

Da bismo to izbjegli, koristimo značajku Arduinosa koja se naziva attach interrupt koja nam omogućuje da pokrenemo funkciju kad god se naznačeni digitalni pin aktivira s rastućim signalom. Funkcija rpm_fun je pridružena prekidu s jednom linijom koda dodanoj u kod za postavljanje.

void setup () {

sCmd.addCommand ("TRIGG", TriggHanlder); attachInterrupt (0, rpm_fun, RISING); Serial.begin (9600); } // Funkcija rpm_fun koristi se za izračunavanje brzine i definirana je kao; unsigned long lastRevolTime = 0; unsigned long revolSpeed = 0; void rpm_fun () {unsigned long revolTime = millis (); unsigned long deltaTime = revolTime - lastRevolTime; /*revolSpeed je vrijednost prenesena u Arduino kod* / revolSpeed = 20000 / deltaTime; lastRevolTime = revolTime; } TriggHandler tada može prenijeti ostatak informacija na zahtjev. void TriggHanlder () { /*Očitavanje vrijednosti potenciometra* / Serial.println (analogRead (ANALOGPIN)); Serial.println (revolSpeed); }

Sada imamo sve građevne blokove koji se mogu koristiti za izradu Arduino koda koji će prenositi podatke kroz serijsku jedinicu do trenutka kada Unity uputi zahtjev. Ako želite imati kopiju cijelog koda, možete ga preuzeti na našem GitHubu. Da biste provjerili je li kôd pravilno postavljen, možete koristiti serijski monitor za slanje TRIGG-a; obavezno postavite red koji završava na Carriage return. Sljedeći odjeljak fokusirat će se na to kako naše Unity skripte mogu zatražiti i primiti informacije od Arduina.

Korak 3: Prijem i obrada podataka

Prijem i obrada podataka
Prijem i obrada podataka

Unity je sjajan softver dostupan besplatno za ljubitelje

zainteresiran za izradu igara; dolazi s velikim brojem funkcionalnosti koje zaista mogu skratiti vrijeme postavljanja određenih stvari, kao što su niti ili programiranje GPU -a (AKA sjenčanje) bez ograničenja onoga što se može učiniti sa C# skriptama. Unity i Arduino mikrokontroleri mogu se koristiti zajedno za stvaranje jedinstvenih interaktivnih iskustava s relativno malim budžetom.

Fokus ovog uputstva je pomoći u postavljanju komunikacije između Unityja i Arduina tako da nećemo zaroniti previše duboko u većinu funkcija dostupnih s Unityjem. Postoji mnogo VELIKIH vodiča za jedinstvo i nevjerojatnu zajednicu koja bi mogla učiniti mnogo bolji posao objašnjavajući kako Unity funkcionira. Međutim, postoji posebna nagrada za one koji uspiju proći kroz ovo uputstvo koja služi kao mala izložba onoga što bi se moglo učiniti. Na našem Githubu možete preuzeti naš prvi pokušaj pravljenja staze s realnom fizikom bicikla.

Prvo, prođimo minimalni minimum koji je potrebno učiniti da biste komunicirali s Arduinom putem serije. Brzo će biti jasno da ovaj kod nije prikladan za igranje, ali dobro je proći svaki korak i naučiti koja su ograničenja.

U Unity -u kreirajte novu scenu s jednim praznim GameObject -om pod imenom ArduinoReceive i priložite C# skriptu koja se također naziva ArduinoReceive. Ova skripta će dodati sav kod koji upravlja komunikacijom s Arduinom.

Postoji biblioteka kojoj morate pristupiti da bismo mogli komunicirati sa serijskim portovima vašeg računara; Unity mora biti postavljen kako bi se omogućilo korištenje određenih biblioteka. Idite na Edit-> ProjectSerring-> Player i pored nivoa kompatibilnosti API-ja u okviru Konfiguracijski prekidač. Podskup. NET 2.0 na. NET 2.0. Sada dodajte sljedeći kôd na vrh skripte;

pomoću System. IO. Ports;

Ovo će vam omogućiti pristup klasi SerialPort koju možete definirati kao objekt klase ArduinoReceive. Neka bude privatno kako biste izbjegli smetnje iz druge skripte.

privatni SerialPort arduinoPort;

Objekt arduinoPort može se otvoriti odabirom ispravnog priključka (npr. Na koji je USB priključen Arduino) i brzine prijenosa (tj. Brzine kojom se šalju informacije). Ako niste sigurni na koji je priključak priključen Arduino, to možete saznati u upravitelju uređaja ili otvaranjem Arduino IDE -a. Za brzinu prijenosa, zadana vrijednost na većini uređaja je 9600, samo provjerite imate li tu vrijednost u svom Arduino kodu i trebala bi raditi.

Kôd bi sada trebao izgledati ovako;

pomoću System. Collections;

pomoću System. Collections. Generic; koristeći UnityEngine; pomoću System. IO. Ports; javna klasa ArduinoReceive: MonoBehaviour {privatni SerialPort arduinoPort; // Koristi ovo za inicijalizaciju void Start () {arduinoPort = new SerialPort ("COM5", 9600); arduinoPort. Open (); WriteToArduino ("TRIGG"); }}

Vaš COM broj će se najvjerojatnije razlikovati. Ako ste na MAC -u, vaše COM ime može imati naziv koji izgleda ovako /dev/cu.wchusbserial1420. Uvjerite se da je kôd iz odjeljka 4 postavljen na Arduino i da je serijski monitor zatvoren za ostatak ovog odjeljka i da se ovaj kôd kompilira bez problema.

Pošaljimo sada zahtjev za svaki okvir Arduina i zapisujmo rezultate u prozor konzole. Dodajte funkciju WriteToArduino u klasu ArduinoReceive. Povratak nosača i nova linija neophodni su za Arduino kôd za pravilno raščlanjivanje dolazne instrukcije.

private void WriteToArduino (niz poruka)

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

Ova funkcija se tada može pozvati u petlji ažuriranja.

void Update ()

{WriteToArduino ("TRIGG"); Debug. Log ("Prva vrijednost:" + arduinoPort. ReadLine ()); Debug. Log ("Druga vrijednost:" + arduinoPort. ReadLine ()); }

Gornji kôd je minimum koji vam je potreban za čitanje podataka s Arduina. Ako pažljivo obratite pažnju na FPS -ove date jedinstvom, trebali biste vidjeti značajan pad performansi. U mom slučaju, ide sa oko 90 FPS bez čitanja/pisanja do 20 FPS. Ako vaš projekt ne zahtijeva česta ažuriranja, to bi moglo biti dovoljno, ali za video igru 20 FPS je premalo. Sljedeći odjeljak će pokriti kako možete poboljšati performanse korištenjem više niti.

Korak 4: Optimiziranje prijenosa podataka

Prethodni odjeljak je govorio o tome kako postaviti osnovne postavke

komunikacija između programa Arduino i Unity. Glavni problem ovog koda su performanse. U trenutnoj implementaciji, Unity mora čekati da Arduino primi, obradi i odgovori na zahtjev. Za to vrijeme Unity kôd mora čekati da se zahtjev obavi i ne radi ništa drugo. Riješili smo ovaj problem stvaranjem niti koja će obrađivati zahtjeve i spremati varijablu u glavnu nit.

Za početak, moramo uključiti biblioteku threadinga dodavanjem;

pomoću System. Threading;

Zatim postavljamo funkciju koju pokrećemo u nitima. AsynchronousReadFromArduino počinje pisanjem zahtjeva u Arduino s funkcijom WrtieToArduino. Očitavanje je zatvoreno u blok try-catch, ako je vremensko ograničenje čitanja, varijable ostaju null i umjesto OnArduinoInfoReceive se poziva funkcija OnArduinoInfoFail.

Zatim definiramo funkcije OnArduinoInfoFail i OnArduinoInfoReceive. Za ovu instrukciju, ispisujemo rezultate na konzolu, ali možete pohraniti rezultate u varijable koje su vam potrebne za vaš projekt.

private void OnArduinoInfoFail ()

{Debug. Log ("Čitanje nije uspjelo"); } private void OnArduinoInfoReceived (rotacija niza, brzina niza) {Debug. Log ("Uspješno čitanje"); Debug. Log ("Prva vrijednost:" + rotacija); Debug. Log ("Druga vrijednost:" + brzina); }

Posljednji korak je pokretanje i zaustavljanje niti koje će zahtijevati vrijednosti od Arduina. Moramo osigurati da je posljednja nit završena sa svojim zadnjim zadatkom prije nego započnete novu. U suprotnom bi se moglo poslati više zahtjeva Arduinu u isto vrijeme što bi moglo zbuniti Arduino/Unity i donijeti nepredvidive rezultate.

privatna nit aktivnaThread = null;

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

Ako usporedite performanse koda s onima koje smo napisali u odjeljku 5, performanse bi se trebale značajno poboljšati.

private void OnArduinoInfoFail ()

{Debug. Log ("Čitanje nije uspjelo"); }

Korak 5: Gdje dalje?

Gdje dalje?
Gdje dalje?

Pripremili smo demo koji možete preuzeti na našem Githubu (https://github.com/AlexandreDoucet/InfinityBike), preuzeti kod i igru te se provozati našom stazom. Sve je namješteno za brzu vježbu i nadamo se da će vam dati uvid u ono što biste mogli izgraditi ako koristite ono što smo vas naučili ovim uputstvom.

Krediti

Saradnici na projektu

Alexandre Doucet (_Doucet_)

Maxime Boudreau (MxBoud)

Vanjski izvori [Unity engine za igre] (https://unity3d.com)

Ovaj je projekt započeo nakon što smo pročitali vodič Allana Zucconija "kako integrirati Arduino s jedinstvom" (https://www.alanzucconi.com/2015/10/07/how-to-int…)

Zahtjevi iz Arduina se obrađuju pomoću biblioteke SerialCommand (https://github.com/kroimon/Arduino-SerialCommand)

Preporučuje se: