Inhoudsopgave:
- Stap 1: Materialen
- Stap 2: Gegevens lezen en overbrengen naar Unity
- Stap 3: Gegevens ontvangen en verwerken
- Stap 4: Gegevensoverdracht optimaliseren
- Stap 5: Waar nu?
Video: Infinity Bike - Indoor Bike Training Videogame - Ajarnpa
2024 Auteur: John Day | [email protected]. Laatst gewijzigd: 2024-01-30 11:18
Tijdens de winterseizoenen, koude dagen en slecht weer hebben wielrenners maar een paar mogelijkheden om hun favoriete sport te beoefenen. We waren op zoek naar een manier om indoortraining met een fiets/trainer-opstelling wat leuker te maken, maar de meeste beschikbare producten zijn ofwel duur ofwel gewoon saai om te gebruiken. Daarom zijn we begonnen met het ontwikkelen van Infinity Bike als een Open Source-trainingsvideogame. Infinity Bike leest de snelheid en richting van uw fiets en biedt een niveau van interactiviteit dat niet gemakkelijk te vinden is met fietstrainers.
We profiteren van de eenvoud van de Arduino-microcontroller en een paar 3D-geprinte onderdelen om goedkope sensoren te bevestigen aan een fiets die op een trainer is gemonteerd. De informatie wordt doorgegeven aan een videogame die is gemaakt met de populaire engine voor het maken van games, Unity. Aan het einde van deze instructie zou je in staat moeten zijn om je eigen sensoren op je fiets in te stellen en de informatie van je sensoren naar Unity over te dragen. We hebben zelfs een circuit toegevoegd waarop je kunt rijden en je nieuwe set-up kunt testen. Als je geïnteresseerd bent om bij te dragen, kun je onze GitHub bekijken.
Stap 1: Materialen
De materiaallijst die je nodig hebt, kan een beetje variëren; voor
de maat van je fiets bepaalt bijvoorbeeld de lengte van de startkabels die je nodig hebt, maar hier zijn de belangrijkste onderdelen die je nodig hebt. Je zou waarschijnlijk goedkopere prijzen kunnen vinden voor elk stuk op websites zoals AliExpress, maar 6 maanden wachten op verzending is niet altijd een optie, dus gebruikten we de iets duurdere onderdelen, zodat de schatting niet scheef is.
1 x Arduino nano ($ 22,00)
1 x mini-broodplank ($ 1,33 / eenheid)
1 x 220 Ohm weerstand ($ 1,00/kit)
1 x 10K Potentiometer ($1,80/eenheid)
1 x Hall-sensor ($ 0,96)
20 cm x 6 mm 3D-printer distributieriem ($ 3,33)
1 kit x M3-schroeven en bouten met verschillende lengtes ($ 6,82)
1 x Fietssnelheidsmetermagneet ($ 0,98)
Bovenstaand materiaal hebben we gemonteerd met 3D geprinte onderdelen. De bestanden die we hebben gebruikt, worden hieronder weergegeven en zijn genummerd met dezelfde conventie als de afbeelding aan het begin van dit gedeelte. Alle bestanden zijn te vinden op Thingiverse. Je kunt ze gewoon gebruiken, maar zorg ervoor dat de afmetingen die we hebben gebruikt overeenkomen met je fiets.
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. Pannenlap.stl
10. HallSensorAttach.stl
Stap 2: Gegevens lezen en overbrengen naar Unity
De Arduino- en Unity-code werken samen om te verzamelen, de gegevens van de sensoren op de fiets overdragen en verwerken. Unity zal de waarde van de Arduino opvragen door een string door de serie te sturen en te wachten tot de Arduino reageert met de gevraagde waarden.
Eerst bereiden we de Arduino voor met de bibliotheek Serial Command die wordt gebruikt om de verzoeken van Unity te beheren door een verzoekreeks aan een functie te koppelen. Een basisconfiguratie voor deze bibliotheek kan als volgt worden gemaakt;
#include "SerialCommand.h"
SerialCommand sCmd; void setup() { sCmd.addCommand("TRIGG", TriggHanlder); Serieel.begin(9600); } void loop() { while (Serial.available() > 0) { sCmd.readSerial(); } } void TriggHandler () { /*Lees en verzend de sensoren hier*/}
De functie TriggHandler is gekoppeld aan het object SCmd. Als het serienummer een string ontvangt die overeenkomt met het bijgevoegde commando (in dit geval TRIGG), wordt de functie TriggHandler uitgevoerd.
We gebruiken een potentiometer om de stuurrichting te meten en een hallensensor om de rotatie per minuut van de fiets te meten. De uitlezingen van de potentiometer kunnen eenvoudig worden gedaan met behulp van de ingebouwde functies van de Arduino. De functie TriggHandler kan vervolgens de waarde naar het serienummer afdrukken met de volgende wijziging.
ongeldige TriggHandler (){
/*De waarde van de potentiometer lezen*/ Serial.println(analogRead(ANALOGPIN)); }
De Hall-sensor heeft wat meer instellingen voordat we bruikbare metingen kunnen doen. In tegenstelling tot de potmeter is de instant waarde van de halls-sensor niet erg handig. Omdat we probeerden de snelheid van het wiel te meten, was de tijd tussen triggers waar we in geïnteresseerd waren.
Elke functie die in de Arduino-code wordt gebruikt, kost tijd en als de magneet op het verkeerde moment op één lijn ligt met de Hall-sensor, kan de meting op zijn best worden vertraagd of in het slechtste geval helemaal worden overgeslagen. Dit is duidelijk slecht omdat de Arduino een snelheid kan melden die VEEL anders is dan de werkelijke snelheid van het wiel.
Om dit te voorkomen, gebruiken we een functie van Arduinos genaamd attach interrupt waarmee we een functie kunnen activeren wanneer een aangewezen digitale pin wordt geactiveerd met een stijgend signaal. De functie rpm_fun is gekoppeld aan een interrupt met een enkele regel code toegevoegd aan de setup-code.
ongeldige setup(){
sCmd.addCommand ("TRIGG", TriggHanlder); attachInterrupt(0, rpm_fun, RISING); Serieel.begin(9600); } //De functie rpm_fun wordt gebruikt om de snelheid te berekenen en is gedefinieerd als; niet-ondertekend lang lastRevolTime = 0; niet-ondertekende lange omwentelingssnelheid = 0; void rpm_fun() { unsigned long revolTime = millis(); unsigned long deltaTime = revolTime - lastRevolTime; /*revolSpeed is de waarde die naar de Arduino-code wordt verzonden*/ revolSpeed = 20000 / deltaTime; lastRevolTime = revolTime; } TriggHandler kan vervolgens de rest van de informatie verzenden wanneer daarom wordt gevraagd. void TriggHanlder () { /* Lezen van de waarde van de potentiometer*/ Serial.println (analogRead (ANALOGPIN)); Serial.println(revolSpeed); }
We hebben nu alle bouwstenen die kunnen worden gebruikt om de Arduino-code te bouwen die gegevens via het serienummer zal overbrengen naar wanneer een verzoek wordt gedaan door Unity. Als u een kopie van de volledige code wilt hebben, kunt u deze downloaden op onze GitHub. Om te testen of de code goed is ingesteld, kunt u de seriële monitor gebruiken om TRIGG te verzenden; zorg ervoor dat u de regel die eindigt op Carriage return instelt. De volgende sectie zal zich richten op hoe onze Unity-scripts de informatie van de Arduino kunnen opvragen en ontvangen.
Stap 3: Gegevens ontvangen en verwerken
Unity is een geweldige software die gratis beschikbaar is voor hobbyisten
geïnteresseerd in het maken van games; het wordt geleverd met een groot aantal functionaliteiten die de tijd aanzienlijk kunnen verkorten bij het instellen van bepaalde dingen, zoals threading of GPU-programmering (AKA-shading) zonder te beperken wat er met de C#-scripts kan worden gedaan. Unity- en Arduino-microcontrollers kunnen samen worden gebruikt om met een relatief klein budget unieke interactieve ervaringen te creëren.
De focus van deze instructable is om te helpen bij het opzetten van de communicatie tussen Unity en de Arduino, zodat we niet te diep ingaan op de meeste functies die beschikbaar zijn met Unity. Er zijn tal van GEWELDIGE tutorials voor unity en een ongelooflijke community die veel beter zou kunnen uitleggen hoe Unity werkt. Er is echter een speciale prijs voor degenen die erin slagen zich een weg te banen door deze instructable die dient als een kleine demonstratie van wat er zou kunnen worden gedaan. Je kunt op onze Github onze eerste poging downloaden om een circuit te maken met realistische fietsfysica.
Laten we eerst het absolute minimum doornemen dat moet worden gedaan om via de seriële met een Arduino te communiceren. Het zal snel duidelijk zijn dat deze code niet geschikt is voor gameplay, maar het is goed om elke stap te doorlopen en te leren wat de beperkingen zijn.
Maak in Unity een nieuwe scène met een enkel leeg GameObject genaamd ArduinoReceive bij een C#-script dat ook ArduinoReceive heet. Dit script is waar we alle code zullen toevoegen die de communicatie met de Arduino afhandelt.
Er is een bibliotheek die toegang moet hebben voordat we kunnen communiceren met de seriële poorten van uw computer; Unity moet worden ingesteld om het gebruik van bepaalde bibliotheken mogelijk te maken. Ga naar Bewerken->ProjectSerring->Player en naast het Api-compatibiliteitsniveau onder Configuratie switch. NET 2.0 Subset naar. NET 2.0. Voeg nu de volgende code toe bovenaan het script;
met behulp van System. IO. Ports;
Dit geeft je toegang tot de SerialPort-klasse die je zou kunnen definiëren als een object voor de ArduinoReceive-klasse. Maak het privé om interferentie van een ander script te voorkomen.
privé SerialPort arduinoPort;
Het object arduinoPort kan worden geopend door de juiste poort te selecteren (bijvoorbeeld in welke USB de Arduino is aangesloten) en een baudrate (d.w.z. de snelheid waarmee de informatie wordt verzonden). Als u niet zeker weet op welke poort de Arduino is aangesloten, kunt u dit achterhalen in Apparaatbeheer of door de Arduino IDE te openen. Voor de baudrate is de standaardwaarde op de meeste apparaten 9600, zorg er gewoon voor dat je deze waarde in je Arduino-code hebt en het zou moeten werken.
De code zou er nu zo uit moeten zien;
met behulp van System. Collections;
met behulp van System. Collections. Generic; met behulp van UnityEngine; met behulp van System. IO. Ports; openbare klasse ArduinoReceive: MonoBehaviour {private SerialPort arduinoPort; // Gebruik dit voor initialisatie void Start() { arduinoPort = new SerialPort("COM5", 9600); arduinoPort. Open(); WriteToArduino("TRIGG"); } }
Uw COM-nummer zal hoogstwaarschijnlijk anders zijn. Als je een MAC gebruikt, kan je COM-naam een naam hebben die er zo uitziet /dev/cu.wchusbserial1420. Zorg ervoor dat de code uit sectie 4 is geüpload naar de Arduino en dat de seriële monitor is gesloten voor de rest van deze sectie en dat deze code probleemloos wordt gecompileerd.
Laten we nu elk frame een verzoek naar de Arduino sturen en de resultaten naar het consolevenster schrijven. Voeg de functie WriteToArduino toe aan de klasse ArduinoReceive. De regelterugloop en nieuwe regel zijn nodig om de Arduino-code de inkomende instructie correct te laten ontleden.
privé leegte WriteToArduino (stringbericht)
{ bericht = bericht + "\r\n"; arduinoPort. Write (bericht); arduinoPort. BaseStream. Flush (); }
Deze functie kan dan in de Update-lus worden aangeroepen.
ongeldige update ()
{ WriteToArduino ("TRIGG"); Debug. Log("Eerste waarde: " + arduinoPort. ReadLine()); Debug. Log("Tweede waarde: " + arduinoPort. ReadLine()); }
De bovenstaande code is het absolute minimum dat je nodig hebt om de gegevens van een Arduino te lezen. Als je goed let op de FPS die door unity wordt gegeven, zou je een aanzienlijke prestatievermindering moeten zien. In mijn geval gaat het van ongeveer 90 FPS zonder lezen/schrijven naar 20 FPS. Als uw project geen frequente updates vereist, is het misschien voldoende, maar voor een videogame is 20 FPS veel te laag. In het volgende gedeelte wordt beschreven hoe u de prestaties kunt verbeteren door multithreading te gebruiken.
Stap 4: Gegevensoverdracht optimaliseren
In het vorige gedeelte werd besproken hoe u de basis
communicatie tussen het Arduino- en Unity-programma. Het grootste probleem met deze code zijn de prestaties. In de huidige implementatie moet Unity wachten tot de Arduino het verzoek ontvangt, verwerkt en beantwoordt. Gedurende die tijd moet de Unity-code wachten tot het verzoek is gedaan en doet niets anders. We hebben dit probleem opgelost door een thread te maken die de verzoeken afhandelt en de variabele op de hoofdthread opslaat.
Om te beginnen moeten we de threading-bibliotheek opnemen door toe te voegen;
met behulp van System. Threading;
Vervolgens stellen we de functie in die we starten in de threads. AsynchronousReadFromArduino begint met het schrijven van het verzoek naar de Arduino met de functie WrtieToArduino. De uitlezing is ingesloten in een try-catch-blok, als de leestime-out, blijven de variabelen nul en wordt de functie OnArduinoInfoFail aangeroepen in plaats van de OnArduinoInfoReceive.
Vervolgens definiëren we de functies OnArduinoInfoFail en OnArduinoInfoReceive. Voor deze instructable drukken we de resultaten af naar de console, maar u kunt de resultaten opslaan in de variabelen die u nodig hebt voor uw project.
privé leegte OnArduinoInfoFail()
{ Debug. Log ("Lezen mislukt"); } private void OnArduinoInfoReceived (stringrotatie, stringsnelheid) { Debug. Log ("Readin Sucessfull"); Debug. Log("Eerste waarde: " + rotatie); Debug. Log ("Tweede waarde: " + snelheid); }
De laatste stap is het starten en stoppen van de threads die de waarden van de Arduino zullen opvragen. We moeten ervoor zorgen dat de laatste thread klaar is met zijn laatste taak voordat we een nieuwe starten. Anders zouden er meerdere verzoeken tegelijk aan de Arduino kunnen worden gedaan, wat de Arduino/Unity zou kunnen verwarren en onvoorspelbare resultaten zou opleveren.
privé-thread activeThread = null;
void Update () {if (activeThread == null || !activeThread. IsAlive) { activeThread = nieuwe thread (AsynchronousReadFromArduino); activeThread. Start(); } }
Als je de prestaties van de code vergelijkt met degene die we in sectie 5 hebben geschreven, zou de prestatie aanzienlijk moeten worden verbeterd.
privé leegte OnArduinoInfoFail()
{ Debug. Log ("Lezen mislukt"); }
Stap 5: Waar nu?
We hebben een demo voorbereid die je kunt downloaden op onze Github (https://github.com/AlexandreDoucet/InfinityBike), download de code en het spel en rijd door onze baan. Het is allemaal ingesteld voor een snelle training en we hopen dat het je een voorproefje kan geven van wat je zou kunnen bouwen als je gebruikt wat we je hebben geleerd met deze instructable.
Credits
Projectmedewerkers
Alexandre Doucet (_Doucet_)
Maxime Boudreau (MxBoud)
Externe bronnen [De Unity-game-engine](https://unity3d.com)
Dit project begon nadat we de tutorial van Allan Zucconi "hoe Arduino met Unity te integreren" hadden gelezen (https://www.alanzuccini.com/2015/10/07/how-to-int…)
Het verzoek van de Arduino wordt afgehandeld met behulp van de SerialCommand-bibliotheek (https://github.com/kroimon/Arduino-SerialCommand)
Aanbevolen:
Opencv Gezichtsdetectie, training en herkenning: 3 stappen
Opencv-gezichtsdetectie, training en herkenning: OpenCV is een open source computer vision-bibliotheek die erg populair is voor het uitvoeren van elementaire beeldverwerkingstaken zoals vervaging, beeldmenging, verbetering van zowel de beeld- als videokwaliteit, drempelwaardering enz. Naast beeldverwerking, het bewijst
Hoe een Arduino-videogame te maken: 5 stappen
Hoe maak je een Arduino-videogame: In deze instructie leer je hoe je een eenvoudig videogame maakt met Arduino. Het zijn de beste hobbyprojecten voor kinderen. Laten we beginnen
DIY-videogame bestuurd door hoofdbeweging (Augmented Reality): 4 stappen
DIY-videogame bestuurd door hoofdbeweging (Augmented Reality): ik wil je laten zien hoe gemakkelijk het tegenwoordig is om een eigen spel te maken dat kan worden bestuurd door je lichaam te bewegen. Je hebt alleen een laptop met webcam en enige programmeervaardigheid nodig. Als je geen laptop en webcam hebt of niet weet hoe je moet programmeren, kun je
Geweldige videogame-audio ontwerpen: 10 stappen (met afbeeldingen)
Ontzagwekkende videogame-audio ontwerpen: ik ben de afgelopen jaren een videogame-ontwerper geweest - ik heb aan verschillende games gewerkt, van zelfgemaakte dingen voor de Game Boy Advance tot echt vreemde dingen zoals Seaman, voor de Sega Dreamcast, tot blockbusters met een groot budget zoals de Sims
Een videogame maken met RPG Maker XP: 4 stappen
Maak een videogame met RPG Maker XP: RMXP leren gebruiken! Hallo! Deze instructable gaat over het maken van een eenvoudig spel met RMXP, een programma dat kan worden gedownload voor een gratis proefperiode of kan worden gekocht voor $ 60,00 op http://tkool.jp/products/rpgxp/eng/. Deze tut