Obsah:

Infinity Bike - Videohra pro trénink vnitřních kol: 5 kroků
Infinity Bike - Videohra pro trénink vnitřních kol: 5 kroků

Video: Infinity Bike - Videohra pro trénink vnitřních kol: 5 kroků

Video: Infinity Bike - Videohra pro trénink vnitřních kol: 5 kroků
Video: Adel ukazala prso 2024, Listopad
Anonim
Image
Image
Materiály
Materiály

Během zimních sezón, chladných dnů a špatného počasí mají cyklističtí nadšenci jen několik možností, jak cvičit a dělat svůj oblíbený sport. Hledali jsme způsob, jak udělat halové tréninky s nastavením kola/trenažéru trochu zábavnější, ale většina dostupných produktů je buď nákladná, nebo je prostě nudné používat. Proto jsme začali vyvíjet Infinity Bike jako tréninkovou videohru s otevřeným zdrojovým kódem. Kolo Infinity čte rychlost a směr z vašeho kola a nabízí úroveň interaktivity, kterou u cyklotrenažérů jen tak snadno nenajdete.

Využíváme jednoduchost, kterou nabízí mikrokontrolér Arduino a několik 3D tištěných dílů, abychom zajistili levné senzory na kole namontovaném na trenažéru. Informace jsou předávány do videohry vytvořené pomocí populárního enginu pro tvorbu her, Unity. Na konci tohoto pokynu byste měli být schopni na kole nastavit vlastní senzory a přenést informace o svých senzorech do Unity. Zahrnuli jsme dokonce trať, na které se můžete svézt a vyzkoušet si své nové nastavení. Pokud máte zájem přispět, můžete se podívat na náš GitHub.

Krok 1: Materiály

Materiály
Materiály

Seznam materiálu, který budete potřebovat, se může trochu lišit; pro

například velikost vašeho kola bude diktovat délky propojovacích kabelů, které potřebujete, ale zde jsou hlavní části, které budete potřebovat. Pravděpodobně byste mohli najít levnější ceny za každý kus na webových stránkách, jako je AliExpress, ale čekat 6 měsíců na dodání není vždy možné, takže jsme použili mírně dražší díly, takže odhad není zkreslený.

1 x Arduino nano (22,00 USD)

1 x Mini Breadboard (1,33 $/jednotka)

1 x odpor 220 ohmů (1,00 $/sada)

1 x 10K potenciometr (1,80 $/jednotka)

1 x Hallův senzor (0,96 $)

Rozvodový řemen 3D tiskárny 20 cm x 6 mm (3,33 USD)

1 sada x Šrouby a šrouby různé délky M3 (6,82 USD)

1 x magnet rychloměru jízdního kola (0,98 USD)

Materiál jsme namontovali výše pomocí 3D tištěných dílů. Soubory, které jsme použili, jsou uvedeny níže a jsou očíslovány stejnou konvencí jako obrázek na začátku této části. Všechny soubory najdete na Thingiverse. Můžete je používat tak, jak jsou, ale ujistěte se, že rozměry, které jsme použili, odpovídají vašemu kolu.

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

Krok 2: Čtení a přenos dat do Unity

Čtení a přenos dat do Unity
Čtení a přenos dat do Unity

Kód Arduino a Unity budou spolupracovat při shromažďování, přenášet a zpracovávat data ze senzorů na kole. Unity bude požadovat hodnotu od Arduina odesláním řetězce přes seriál a čekat, až Arduino odpoví požadovanými hodnotami.

Nejprve připravíme Arduino s knihovním sériovým příkazem, který slouží ke správě požadavků z Unity spárováním řetězce požadavků s funkcí. Základní nastavení pro tuto knihovnu lze provést následujícím způsobem;

#include "SerialCommand.h"

SerialCommand sCmd; neplatné nastavení () {sCmd.addCommand ("TRIGG", TriggHanlder); Serial.begin (9600); } void loop () {while (Serial.available ()> 0) {sCmd.readSerial (); }} neplatné TriggHandler () { /*Zde si přečtěte a odešlete senzory* /}

Funkce TriggHandler je připojena k objektu SCmd. Pokud seriál obdrží řetězec, který odpovídá připojenému příkazu (v tomto případě TRIGG), provede se funkce TriggHandler.

Potenciometrem měříme směr řízení a Hallovým senzorem otáčky kola za minutu. Odečty z potenciometru lze snadno provést pomocí vestavěných funkcí z Arduina. Funkce TriggHandler pak může vytisknout hodnotu do seriálu s následující změnou.

neplatné TriggHandler () {

/*Čtení hodnoty potenciometru*/ Serial.println (analogRead (ANALOGPIN)); }

Hallův senzor má trochu více nastavení, než budeme mít k dispozici užitečná měření. Na rozdíl od potenciometru není okamžitá hodnota Hallova senzoru příliš užitečná. Protože se pokoušeli měřit rychlost kola, zajímal se čas mezi spouštěmi.

Každá funkce použitá v kódu Arduino vyžaduje čas, a pokud se magnet seřadí s Hallovým senzorem ve špatný čas, měření by mohlo být v nejlepším případě zpožděno nebo v nejhorším případě přeskočeno. To je samozřejmě špatné, protože Arduino by mohlo hlásit rychlost, která je MNOHEM odlišná od skutečné rychlosti kola.

Abychom se tomu vyhnuli, používáme funkci Arduinos nazývanou připojit přerušení, která nám umožňuje spustit funkci vždy, když je spuštěn určený digitální pin se stoupajícím signálem. Funkce rpm_fun je připojena k přerušení jediným řádkem kódu přidaným do instalačního kódu.

neplatné nastavení () {

sCmd.addCommand ("TRIGG", TriggHanlder); attachInterrupt (0, rpm_fun, RISING); Serial.begin (9600); } // Funkce rpm_fun se používá k výpočtu rychlosti a je definována jako; unsigned long lastRevolTime = 0; nepodepsaná dlouhá revolSpeed = 0; void rpm_fun () {unsigned long revolTime = millis (); unsigned long deltaTime = revolTime - lastRevolTime; /*revolSpeed je hodnota přenesená do kódu Arduino* / revolSpeed = 20 000 / deltaTime; lastRevolTime = revolTime; } TriggHandler pak může na požádání odeslat zbývající informace. void TriggHanlder () { /*Čtení hodnoty potenciometru* / Serial.println (analogRead (ANALOGPIN)); Serial.println (revolSpeed); }

Nyní máme všechny stavební bloky, které lze použít k sestavení kódu Arduino, který bude přenášet data přes sériové číslo, když Unity podá žádost. Pokud chcete mít kopii celého kódu, můžete si jej stáhnout na našem GitHubu. Chcete-li otestovat, zda byl kód správně nastaven, můžete použít sériový monitor k odeslání TRIGG; ujistěte se, že jste nastavili konec řádku na Carriage return. Další část se zaměří na to, jak naše skripty Unity mohou požadovat a přijímat informace z Arduina.

Krok 3: Příjem a zpracování dat

Příjem a zpracování dat
Příjem a zpracování dat

Unity je skvělý software, který je k dispozici fandům zdarma

zajímá se o tvorbu her; přichází s velkým množstvím funkcí, které mohou skutečně omezit čas při nastavování určitých věcí, jako je například vytváření vláken nebo programování GPU (stínování AKA), aniž by se omezovalo, co lze dělat se skripty C#. Mikrokontroléry Unity a Arduino lze použít společně k vytvoření jedinečných interaktivních zážitků s relativně malým rozpočtem.

Cílem tohoto instruktážního programu je pomoci nastavit komunikaci mezi Unity a Arduino, takže se nebudeme ponořit příliš hluboko do většiny funkcí dostupných s Unity. Existuje spousta SKVĚLÝCH návodů pro jednotu a neuvěřitelnou komunitu, které by mohly udělat mnohem lepší práci vysvětlující, jak funguje Unity. Existuje však zvláštní cena pro ty, kterým se podaří projít tímto instruktážním programem, který slouží jako malá ukázka toho, co by se dalo dělat. Na našem Githubu si můžete stáhnout náš první pokus o vytvoření trati s realistickou fyzikou kola.

Nejprve si projdeme naprosté minimum, které je třeba udělat, abychom mohli komunikovat s Arduinem prostřednictvím seriálu. Rychle se ukáže, že tento kód není vhodný pro hraní, ale je dobré projít každý krok a zjistit, jaká jsou omezení.

V Unity vytvořte novou scénu s jediným prázdným GameObject pojmenovaným ArduinoReceive a připojte skript C# také pojmenovaný ArduinoReceive. V tomto skriptu přidáme veškerý kód, který zpracovává komunikaci s Arduinem.

Než budeme moci komunikovat se sériovými porty vašeho počítače, musí existovat knihovna; Aby bylo možné používat určité knihovny, je třeba nastavit jednotu. Přejděte na Upravit-> ProjectSerring-> Přehrávač a vedle Úroveň kompatibility Api v části Konfigurační přepínač. NET 2.0 Podmnožina na. NET 2.0. Nyní přidejte následující kód do horní části skriptu;

pomocí System. IO. Ports;

To vám umožní přístup ke třídě SerialPort, kterou byste mohli definovat jako objekt třídy ArduinoReceive. Nastavit jako soukromé, abyste se vyhnuli rušení jiným skriptem.

soukromý SerialPort arduinoPort;

Objekt arduinoPort lze otevřít výběrem správného portu (např. Ve kterém USB je Arduino připojeno) a přenosové rychlosti (tj. Rychlosti, jakou jsou informace odesílány). Pokud si nejste jisti, ve kterém portu je Arduino zapojeno, můžete to zjistit buď ve správci zařízení, nebo otevřením Arduino IDE. Pro přenosovou rychlost je výchozí hodnota na většině zařízení 9600, ujistěte se, že máte tuto hodnotu v kódu Arduino a že by měla fungovat.

Kód by nyní měl vypadat takto;

pomocí System. Collections;

pomocí System. Collections. Generic; pomocí UnityEngine; pomocí System. IO. Ports; veřejná třída ArduinoReceive: MonoBehaviour {private SerialPort arduinoPort; // Použijte pro inicializaci neplatné Start () {arduinoPort = new SerialPort ("COM5", 9600); arduinoPort. Open (); WriteToArduino ("TRIGG"); }}

Vaše číslo COM bude s největší pravděpodobností jiné. Pokud používáte MAC, vaše jméno COM může mít název, který vypadá takto /dev/cu.wchusbserial1420. Zajistěte, aby byl kód z oddílu 4 nahrán do Arduina a aby byl sériový monitor po zbytek této části uzavřen a aby byl tento kód kompilován bez problémů.

Nyní pošleme Arduinu požadavek na každý snímek a zapíšeme výsledky do okna konzoly. Přidejte funkci WriteToArduino do třídy ArduinoReceive. Návrat na vozík a nový řádek jsou nezbytné pro to, aby kód Arduino správně analyzoval příchozí instrukci.

private void WriteToArduino (řetězcová zpráva)

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

Tuto funkci pak lze vyvolat ve smyčce Update.

zrušit aktualizaci ()

{WriteToArduino ("TRIGG"); Debug. Log ("První hodnota:" + arduinoPort. ReadLine ()); Debug. Log ("Druhá hodnota:" + arduinoPort. ReadLine ()); }

Výše uvedený kód je naprosté minimum, které potřebujete ke čtení dat z Arduina. Pokud věnujete velkou pozornost FPS daným jednotou, měli byste zaznamenat výrazný pokles výkonu. V mém případě jde z přibližně 90 FPS bez čtení/zápisu na 20 FPS. Pokud váš projekt nevyžaduje časté aktualizace, může to stačit, ale pro videohry je 20 FPS příliš málo. Následující část se bude zabývat tím, jak můžete zlepšit výkon pomocí více vláken.

Krok 4: Optimalizace přenosu dat

V předchozí části bylo popsáno, jak nastavit základní

komunikace mezi programem Arduino a Unity. Hlavním problémem tohoto kódu je výkon. Ve své současné implementaci musí Unity počkat, až Arduino požadavek přijme, zpracuje a odpoví. Během této doby musí kód Unity čekat na vyřízení požadavku a nedělá nic jiného. Tento problém jsme vyřešili vytvořením vlákna, které bude zpracovávat požadavky a ukládat proměnnou do hlavního vlákna.

Na začátek musíme zahrnout knihovnu vláken přidáním;

pomocí System. Threading;

Dále nastavíme funkci, kterou začínáme ve vláknech. AsynchronousReadFromArduino začíná zapsáním požadavku do Arduina pomocí funkce WrtieToArduino. Čtení je uzavřeno v bloku try-catch, pokud časový limit čtení, proměnné zůstávají nulové a místo OnArduinoInfoReceive je volána funkce OnArduinoInfoFail.

Dále definujeme funkce OnArduinoInfoFail a OnArduinoInfoReceive. Pro tento instruktáž vytiskneme výsledky do konzoly, ale můžete uložit výsledky do proměnných, které potřebujete pro svůj projekt.

soukromá prázdnota OnArduinoInfoFail ()

{Debug. Log ("Čtení se nezdařilo"); } private void OnArduinoInfoReceived (rotace řetězce, rychlost řetězce) {Debug. Log ("Readin Sucessfull"); Debug. Log ("První hodnota:" + otočení); Debug. Log ("Druhá hodnota:" + rychlost); }

Posledním krokem je spuštění a zastavení vláken, která budou požadovat hodnoty od Arduina. Před spuštěním nového musíme zajistit, aby poslední vlákno bylo provedeno s jeho posledním úkolem. V opačném případě by bylo možné na Arduino provést více požadavků najednou, což by mohlo zaměnit Arduino/Unity a přinést nepředvídatelné výsledky.

private Thread activeThread = null;

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

Pokud porovnáte výkon kódu s tím, který jsme napsali v části 5, výkon by se měl výrazně zlepšit.

soukromá prázdnota OnArduinoInfoFail ()

{Debug. Log ("Čtení se nezdařilo"); }

Krok 5: Kam dál?

Kam dál?
Kam dál?

Připravili jsme demo, které si můžete stáhnout na našem Githubu (https://github.com/AlexandreDoucet/InfinityBike), stáhnout kód a hru a projet se po naší trati. Vše je připraveno na rychlé cvičení a doufáme, že vám pomůže ochutnat, co byste mohli vybudovat, pokud použijete to, co jsme vás naučili tímto návodem.

Kredity

Přispěvatelé projektu

Alexandre Doucet (_Doucet_)

Maxime Boudreau (MxBoud)

Externí zdroje [herní engine Unity] (https://unity3d.com)

Tento projekt začal poté, co jsme si přečetli návod od Allana Zucconiho „jak integrovat Arduino s Unity“(https://www.alanzucconi.com/2015/10/07/how-to-int…)

Žádost z Arduina se vyřizuje pomocí knihovny SerialCommand (https://github.com/kroimon/Arduino-SerialCommand)

Doporučuje: