Innholdsfortegnelse:

Infinity Bike - Innendørs sykkelopplæring Videospill: 5 trinn
Infinity Bike - Innendørs sykkelopplæring Videospill: 5 trinn

Video: Infinity Bike - Innendørs sykkelopplæring Videospill: 5 trinn

Video: Infinity Bike - Innendørs sykkelopplæring Videospill: 5 trinn
Video: 10 лучших курортов «все включено» в Пунта-Кане, Доминиканская Республика, на 2023 год 2024, Juni
Anonim
Image
Image
Materialer
Materialer

I vintersesongen, kalde dager og dårlig vær har syklistentusiaster bare noen få muligheter til å trene med sin favorittsport. Vi var på utkikk etter en måte å gjøre innendørs trening med sykkel/treneroppsett litt mer underholdende, men de fleste produktene som er tilgjengelige er enten kostbare eller bare kjedelige å bruke. Dette er grunnen til at vi begynte å utvikle Infinity Bike som et treningsvideospill med åpen kildekode. Infinity bike leser hastigheten og retningen fra sykkelen din og tilbyr et nivå av interaktivitet som ikke er lett å finne med sykkeltrenere.

Vi drar fordel av enkelheten som er tilgjengelig fra Arduino mikrokontroller og noen få 3D -trykte deler for å sikre billige sensorer til en sykkel montert på en trener. Informasjonen videresendes til et videospill laget med den populære spillfremstillingsmotoren, Unity. Ved slutten av denne instruksen, bør du kunne sette opp dine egne sensorer på sykkelen din og overføre informasjonen om sensorene dine til Unity. Vi inkluderte til og med et spor som du kan sykle på og teste det nye oppsettet ditt på. Hvis du er interessert i å bidra, kan du sjekke ut vår GitHub.

Trinn 1: Materialer

Materialer
Materialer

Materialelisten du trenger kan variere litt; til

for eksempel vil størrelsen på sykkelen din diktere lengden på hoppekablene du trenger, men her er hoveddelene du trenger. Du kan sannsynligvis finne billigere priser for hvert stykke på nettstedet som AliExpress, men å vente 6 måneder på frakt er ikke alltid et alternativ, så det var å bruke de litt dyrere delene, slik at estimatet ikke er skjevt.

1 x Arduino nano ($ 22,00)

1 x Mini -brødbrett ($ 1,33/enhet)

1 x 220 Ohm motstand ($ 1,00/sett)

1 x 10K potensiometer ($ 1,80/enhet)

1 x Hall -sensor ($ 0,96)

20 cm x 6 mm 3D -skriver timing belte ($ 3,33)

1 sett x forskjellige lengder M3 skruer og bolter ($ 6,82)

1 x Sykkelhastighetsmåler ($ 0,98)

Vi monterte materialet ovenfor med 3D -trykte deler. Filene vi brukte er listet nedenfor, og de er nummerert med samme konvensjon som bildet i begynnelsen av denne delen. Alle filene finnes på Thingiverse. Du kan bruke dem som de er, men sørg for at dimensjonene vi brukte stemmer overens med sykkelen din.

1. FrameConnection_PotentiometerHolder_U_Holder.stl

2. FrameConnection_Spacer.stl

3. BreadboardFrameHolder.stl

4. Remskive_PotensiometerSide.stl

5. Pot_PulleyConnection.stl

6. FrameConnection.stl

7. Pulley_HandleBarSide_Print2.stl

8. FrameToHallSensorConnector.stl

9. PotHolder.stl

10. HallSensorAttach.stl

Trinn 2: Lese og overføre data til enhet

Lese og overføre data til enhet
Lese og overføre data til enhet

Arduino og Unity -koden vil fungere sammen for å samle, overføre og behandle dataene fra sensorene på sykkelen. Unity vil be om verdien fra Arduino ved å sende en streng gjennom serien og vente på at Arduino skal svare med de forespurte verdiene.

Først forbereder vi Arduino med bibliotekets seriekommando som brukes til å administrere forespørslene fra Unity ved å koble en forespørselsstreng med en funksjon. Et grunnleggende oppsett for dette biblioteket kan gjøres som følger;

#include "SerialCommand.h"

SerialCommand sCmd; void setup () {sCmd.addCommand ("TRIGG", TriggHanlder); Serial.begin (9600); } void loop () {while (Serial.available ()> 0) {sCmd.readSerial (); }} ugyldig TriggHandler () { /*Les og overfør sensorene her* /}

Funksjonen TriggHandler er knyttet til objektet SCmd. Hvis føljetonen mottar en streng som samsvarer med den vedlagte kommandoen (i dette tilfellet TRIGG), utføres funksjonen TriggHandler.

Vi bruker potensiometer for å måle styreretningen og en hallsensor for å måle rotasjonen per minutt på sykkelen. Avlesningene fra potensiometeret kan enkelt gjøres ved hjelp av de innebygde funksjonene fra Arduino. Funksjonen TriggHandler kan deretter skrive ut verdien til serien med følgende endring.

ugyldig TriggHandler () {

/*Leser verdien av potensiometeret*/ Serial.println (analogRead (ANALOGPIN)); }

Hall -sensoren har litt mer oppsett før vi kan ha nyttige målinger. I motsetning til potensiometeret er øyeblikkelig verdi av hallsensoren ikke veldig nyttig. Siden jeg prøvde å måle hastigheten på hjulet, var tiden mellom utløsere det som var interessert i.

Hver funksjon som brukes i Arduino -koden tar tid, og hvis magneten stemmer overens med Hall -sensoren på feil tidspunkt, kan målingen i beste fall bli forsinket eller hoppe helt i verste fall. Dette er åpenbart dårlig fordi Arduino kan rapportere en hastighet som er MYE annerledes enn hjulets faktiske hastighet.

For å unngå dette bruker vi en funksjon hos Arduinos kalt attach interrupt som lar oss utløse en funksjon når en angitt digital pin utløses med et stigende signal. Funksjonen rpm_fun er knyttet til et interrupt med en enkelt linje med kode lagt til oppsettskoden.

ugyldig oppsett () {

sCmd.addCommand ("TRIGG", TriggHanlder); attachInterrupt (0, rpm_fun, RISING); Serial.begin (9600); } // Funksjonen rpm_fun brukes til å beregne hastigheten og er definert som; usignert lang lastRevolTime = 0; usignert lang revolSpeed = 0; void rpm_fun () {unsigned long revolTime = millis (); usignert lang deltaTime = revolTime - lastRevolTime; /*revolSpeed er verdien som overføres til Arduino -koden* / revolSpeed = 20000 / deltaTime; lastRevolTime = revolTime; } TriggHandler kan deretter overføre resten av informasjonen når det blir forespurt. void TriggHanlder () { /*Leser verdien av potensiometeret* / Serial.println (analogRead (ANALOGPIN)); Serial.println (revolSpeed); }

Vi har nå alle byggeklossene som kan brukes til å bygge Arduino -koden som vil overføre data gjennom serien til når en forespørsel blir fremsatt av Unity. Hvis du vil ha en kopi av hele koden, kan du laste den ned på vår GitHub. For å teste om koden var riktig konfigurert, kan du bruke den serielle skjermen til å sende TRIGG; sørg for at du setter linjen som slutter på vognretur. Den neste delen vil fokusere på hvordan våre Unity -skript kan be om og motta informasjonen fra Arduino.

Trinn 3: Motta og behandle data

Motta og behandle data
Motta og behandle data

Unity er en flott programvare som er gratis tilgjengelig for hobbyfolk

interessert i å lage spill; den kommer med et stort antall funksjoner som virkelig kan kutte ned på tiden for å sette opp visse ting som tråden eller GPU -programmering (AKA -skygge) uten å begrense det som kan gjøres med C# -skriptene. Unity og Arduino mikrokontrollere kan brukes sammen for å skape unike interaktive opplevelser med et relativt lite budsjett.

Fokuset for denne instruksen er å hjelpe til med å sette opp kommunikasjonen mellom Unity og Arduino, slik at vi ikke dykker for dypt ned i de fleste funksjonene som er tilgjengelige med Unity. Det er mange flotte opplæringsprogrammer for enhet og et utrolig fellesskap som kan gjøre en mye bedre jobb med å forklare hvordan Unity fungerer. Imidlertid er det en spesiell premie for de som klarer å arbeide seg gjennom denne instruerbare som fungerer som et lite utstillingsvindu for hva som kan gjøres. Du kan laste ned vårt første forsøk på å lage et spor med realistisk sykkelfysikk på Github.

La oss først gå gjennom det minste som må gjøres for å kommunisere med en Arduino gjennom serien. Det vil raskt være tydelig at denne koden ikke er egnet for spill, men det er godt å gå gjennom hvert trinn og lære hva begrensningene er.

I Unity kan du lage en ny scene med et enkelt tomt GameObject ved navn ArduinoReceive ved vedlegg av et C# -skript som også heter ArduinoReceive. Dette skriptet er hvor vi vil legge til all koden som håndterer kommunikasjonen med Arduino.

Det er et bibliotek som må være tilgjengelig før vi kan kommunisere med serielle porter på datamaskinen din. Det må settes opp enhet for å tillate bruk av visse biblioteker. Gå til Edit-> ProjectSerring-> Player og ved siden av Api-kompatibilitetsnivået under konfigurasjonsbryteren. NET 2.0 delsett til. NET 2.0. Legg nå til følgende kode øverst i skriptet;

bruker System. IO. Ports;

Dette gir deg tilgang til SerialPort -klassen som du kan definere som et objekt for ArduinoReceive -klassen. Gjør det privat for å unngå forstyrrelser fra et annet skript.

private SerialPort arduinoPort;

Objektet arduinoPort kan åpnes ved å velge riktig port (f.eks. Der USB Arduino er tilkoblet) og en baudhastighet (dvs. hastigheten som informasjonen sendes med). Hvis du ikke er sikker på hvilken port Arduino er plugget inn, kan du finne ut det enten i enhetsbehandling eller ved å åpne Arduino IDE. For overføringshastigheten er standardverdien på de fleste enheter 9600, bare sørg for at du har denne verdien i Arduino -koden, og den skal fungere.

Koden skal nå se slik ut;

bruk av System. Collections;

bruker System. Collections. Generic; bruker UnityEngine; bruker System. IO. Ports; offentlig klasse ArduinoReceive: MonoBehaviour {private SerialPort arduinoPort; // Bruk dette for initialisering void Start () {arduinoPort = ny SerialPort ("COM5", 9600); arduinoPort. Open (); WriteToArduino ("TRIGG"); }}

COM -nummeret ditt vil mest sannsynlig være annerledes. Hvis du bruker en MAC, kan COM -navnet ditt ha et navn som ser slik ut /dev/cu.wchusbserial1420. Sørg for at koden fra seksjon 4 er lastet opp til Arduino og at den serielle skjermen er lukket for resten av denne delen, og at denne koden kompileres uten problemer.

La oss nå sende en forespørsel til Arduino hver ramme og skrive resultatene til konsollvinduet. Legg til WriteToArduino -funksjonen i klassen ArduinoReceive. Vognretur og ny linje er nødvendig for at Arduino -koden skal analysere den innkommende instruksjonen riktig.

private void WriteToArduino (strengmelding)

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

Denne funksjonen kan deretter kalles i oppdateringssløyfen.

ugyldig oppdatering ()

{WriteToArduino ("TRIGG"); Debug. Log ("First Value:" + arduinoPort. ReadLine ()); Debug. Log ("Second Value:" + arduinoPort. ReadLine ()); }

Koden ovenfor er det minste minimum du trenger for å lese dataene fra en Arduino. Hvis du følger nøye med på FPS gitt av enhet, bør du se en betydelig nedgang i ytelsen. I mitt tilfelle går det fra rundt 90 FPS uten å lese/skrive til 20 FPS. Hvis prosjektet ditt ikke krever hyppige oppdateringer, kan det være tilstrekkelig, men for et videospill er 20 FPS altfor lavt. Den neste delen vil dekke hvordan du kan forbedre ytelsen ved å bruke multi -threading.

Trinn 4: Optimalisering av dataoverføring

Den forrige delen dekket hvordan du konfigurerer basic

kommunikasjon mellom Arduino og Unity -programmet. Det største problemet med denne koden er ytelsen. I den nåværende implementeringen må Unity vente på at Arduino mottar, behandler og svarer på forespørselen. I løpet av den tiden må Unity -koden vente på at forespørselen blir utført og gjør ingenting annet. Vi løste dette problemet ved å opprette en tråd som vil håndtere forespørslene og lagre variabelen på hovedtråden.

For å begynne må vi inkludere trådbiblioteket ved å legge til;

bruker System. Threading;

Deretter konfigurerer vi funksjonen vi starter i trådene. AsynchronousReadFromArduino starter med å skrive forespørselen til Arduino med WrtieToArduino -funksjonen. Avlesningen er vedlagt i en prøve-fang-blokk, hvis lesetidsavbruddet forblir variablene null og OnArduinoInfoFail-funksjonen kalles i stedet for OnArduinoInfoReceive.

Deretter definerer vi funksjonene OnArduinoInfoFail og OnArduinoInfoReceive. For denne instruksen skriver vi ut resultatene til konsollen, men du kan lagre resultatene i variablene du trenger for prosjektet ditt.

private void OnArduinoInfoFail ()

{Debug. Log ("Lese mislyktes"); } private void OnArduinoInfoReceived (strengrotasjon, strenghastighet) {Debug. Log ("Readin Sucessfull"); Debug. Log ("Første verdi:" + rotasjon); Debug. Log ("Andre verdi:" + hastighet); }

Det siste trinnet er å starte og stoppe trådene som vil be om verdiene fra Arduino. Vi må sørge for at den siste tråden er ferdig med den siste oppgaven før vi starter en ny. Ellers kan flere forespørsler gjøres til Arduino på en gang som kan forvirre Arduino/Unity og gi uforutsigbare resultater.

private Thread activeThread = null;

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

Hvis du sammenligner ytelsen til koden med den vi skrev i avsnitt 5, bør ytelsen forbedres betydelig.

private void OnArduinoInfoFail ()

{Debug. Log ("Lese mislyktes"); }

Trinn 5: Hvor neste?

Hvor neste?
Hvor neste?

Vi forberedte en demo som du kan laste ned på vår Github (https://github.com/AlexandreDoucet/InfinityBike), laste ned koden og spillet og ri gjennom sporet vårt. Det hele er lagt opp til en rask trening, og vi håper det kan gi deg en smakebit på hva du kan bygge hvis du bruker det vi lærte deg med dette instruerbare.

Studiepoeng

Prosjektbidragsytere

Alexandre Doucet (_Doucet_)

Maxime Boudreau (MxBoud)

Eksterne ressurser [The Unity game engine] (https://unity3d.com)

Dette prosjektet startet etter at vi leste opplæringen av Allan Zucconi "hvordan integrere Arduino med enhet" (https://www.alanzucconi.com/2015/10/07/how-to-int…)

Forespørselen fra Arduino håndteres ved hjelp av SerialCommand-biblioteket (https://github.com/kroimon/Arduino-SerialCommand)

Anbefalt: