Përmbajtje:

Infinity Bike - Trajnimi për biçikleta në ambiente të mbyllura Video lojë: 5 hapa
Infinity Bike - Trajnimi për biçikleta në ambiente të mbyllura Video lojë: 5 hapa

Video: Infinity Bike - Trajnimi për biçikleta në ambiente të mbyllura Video lojë: 5 hapa

Video: Infinity Bike - Trajnimi për biçikleta në ambiente të mbyllura Video lojë: 5 hapa
Video: Alltag und Beruf - Deutsch lernen mit Dialogen - B2 2024, Nëntor
Anonim
Image
Image
Materiale
Materiale

Gjatë stinëve të dimrit, ditëve të ftohta dhe motit të keq, entuziastët e çiklistëve kanë vetëm disa mundësi për të ushtruar duke bërë sportin e tyre të preferuar. Ne po kërkonim një mënyrë për ta bërë trajnimin në ambiente të mbyllura me një konfigurim biçikletë/trainer pak më argëtues, por shumica e produkteve në dispozicion janë ose të kushtueshme ose thjesht të mërzitshme për t'u përdorur. Kjo është arsyeja pse ne filluam të zhvillojmë Infinity Bike si një lojë video trajnimi me burim të hapur. Biçikleta Infinity lexon shpejtësinë dhe drejtimin nga biçikleta juaj dhe ofron një nivel interaktiviteti që nuk mund të gjendet lehtë me trajnerët e biçikletave.

Ne përfitojmë nga thjeshtësia e disponueshme nga mikrokontrolluesi Arduino dhe disa pjesë të printuara 3D për të siguruar sensorë të lirë në një biçikletë të montuar në një trajner. Informacioni transmetohet në një lojë video të krijuar me motorin popullor të krijimit të lojërave, Unity. Deri në fund të këtij udhëzimi, duhet të jeni në gjendje të vendosni sensorët tuaj në biçikletën tuaj dhe të transferoni informacionin e sensorëve tuaj tek Unity. Ne madje kemi përfshirë një pistë në të cilën mund të hipni dhe të provoni strukturën tuaj të re. Nëse jeni të interesuar të kontribuoni, mund të kontrolloni GitHub -in tonë.

Hapi 1: Materialet

Materiale
Materiale

Lista e materialeve që ju nevojiten mund të ndryshojë pak; për

Për shembull, madhësia e biçikletës suaj do të diktojë gjatësinë e kabllove të kërcyesit që ju nevojiten, por këtu janë pjesët kryesore që do t'ju nevojiten. Ju ndoshta mund të gjeni çmime më të lira për secilën pjesë në faqen në internet si AliExpress, por pritja 6 muaj për transport nuk është gjithmonë një opsion, kështu që po përdorni pjesët pak më të shtrenjta, kështu që vlerësimi nuk është i shtrembëruar.

1 x Arduino nano (22,00 dollarë)

1 x Mini Breadboard (1.33 dollarë/njësi)

1 rezistencë 220 Ohm ($ 1.00/komplet)

1 potenciometër 10K (1.80 dollarë/njësi)

1 x sensor Hall (0.96 dollarë)

Rripi i kohës i printerit 3D 20 cm x 6 mm (3.33 dollarë)

1 komplet x Vida dhe bulona me gjatësi të ndryshme M3 (6.82 dollarë)

1 x magnet i shpejtësisë së biçikletës (0.98 dollarë)

Ne e montuam materialin e mësipërm me pjesë të printuara 3D. Skedarët që përdorëm janë të shënuar më poshtë dhe numërohen me të njëjtën konventë si imazhi në fillim të këtij seksioni. Të gjitha skedarët mund të gjenden në Thingiverse. Ju mund t'i përdorni ato ashtu siç janë, por sigurohuni që dimensionet që kemi përdorur të përputhen me biçikletën tuaj.

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

Hapi 2: Leximi dhe transferimi i të dhënave në Unitet

Leximi dhe transferimi i të dhënave në Unitet
Leximi dhe transferimi i të dhënave në Unitet

Kodi Arduino dhe Unity do të punojnë së bashku për të mbledhur, transferoni dhe përpunoni të dhënat nga sensorët në biçikletë. Uniteti do të kërkojë vlerën nga Arduino duke dërguar një varg përmes serialit dhe do të presë që Arduino të përgjigjet me vlerat e kërkuara.

Së pari, ne përgatisim Arduino me Komandën Seriale të bibliotekës e cila përdoret për të menaxhuar kërkesat nga Unity duke çiftuar një varg kërkesash me një funksion. Një bazë themelore për këtë bibliotekë mund të bëhet si më poshtë;

#përfshi "SerialCommand.h"

SerialCommand sCmd; void setup () {sCmd.addCommand ("TRIGG", TriggHanlder); Serial.filloj (9600); } void loop () {while (Serial.available ()> 0) {sCmd.readSerial (); }} void TriggHandler () { /*Lexoni dhe transmetoni sensorët këtu* /}

Funksioni TriggHandler i bashkëngjitet objektit SCmd. Nëse seriali merr një varg që përputhet me komandën e bashkangjitur (në këtë rast TRIGG), funksioni TriggHandler ekzekutohet.

Ne përdorim potenciometër për të matur drejtimin e drejtimit dhe një sensor sallash për të matur rrotullimin në minutë të biçikletës. Leximet nga potenciometri mund të bëhen lehtësisht duke përdorur funksionet e integruara nga Arduino. Funksioni TriggHandler mund të printojë vlerën në serial me ndryshimin e mëposhtëm.

void TriggHandler () {

/*Leximi i vlerës së potenciometrit*/ Serial.println (analogRead (ANALOGPIN)); }

Sensori Hall ka pak më shumë konfigurim para se të kemi matje të dobishme. Në kundërshtim me potenciometrin, vlera e menjëhershme e sensorit të sallave nuk është shumë e dobishme. Meqenëse po përpiqeshin të matnin shpejtësinë e rrotës, koha midis nxitësve është ajo që u interesonte.

Çdo funksion i përdorur në kodin Arduino kërkon kohë dhe nëse magneti përputhet me sensorin Hall në kohën e gabuar, matja mund të vonohet në rastin më të mirë ose të anashkalohet plotësisht në rastin më të keq. Kjo është padyshim e keqe sepse Arduino mund të raportojë një shpejtësi që është SHUME e ndryshme nga shpejtësia aktuale e timonit.

Për të shmangur këtë, ne përdorim një veçori të Arduinos të quajtur ndërprerja e bashkëngjitjes e cila na lejon të aktivizojmë një funksion sa herë që një kunj dixhital i caktuar nxitet me një sinjal në rritje. Funksioni rpm_fun i bashkëngjitet një ndërprerjeje me një linjë të vetme kodi të shtuar në kodin e konfigurimit.

void setup () {

sCmd.addCommand ("TRIGG", TriggHanlder); attachInterrupt (0, rpm_fun, RISING); Serial.filloj (9600); } // Funksioni rpm_fun përdoret për të llogaritur shpejtësinë dhe përcaktohet si; pa nënshkruar gjatë lastRevolTime = 0; revolucion i gjatë i panënshkruarShpejtësia = 0; void rpm_fun () {revoltë e gjatë e panënshkruar kohë = milis (); deltaTime e gjatë e panënshkruar = revoltime - lastRevolTime; /*revolSpeed është vlera e transmetuar në kodin Arduino* / revolspeed = 20000 / deltaTime; lastRevolTime = revolTime; } TriggHandler pastaj mund të transmetojë pjesën tjetër të informacionit kur kërkohet. void TriggHanlder () { /*Leximi i vlerës së potenciometrit* / Serial.println (analogRead (ANALOGPIN)); Serial.println (revolSpeed); }

Tani kemi të gjitha blloqet e ndërtimit që mund të përdoren për të ndërtuar kodin Arduino i cili do të transferojë të dhëna përmes serisë kur të bëhet një kërkesë nga Unity. Nëse dëshironi të keni një kopje të kodit të plotë, mund ta shkarkoni në GitHub tonë. Për të provuar nëse kodi është vendosur siç duhet, mund të përdorni monitorin serik për të dërguar TRIGG; sigurohuni që të vendosni vijën që përfundon në kthimin e Transportit. Seksioni tjetër do të përqëndrohet në mënyrën sesi skriptet tona të Unitetit mund të kërkojnë dhe marrin informacion nga Arduino.

Hapi 3: Marrja dhe përpunimi i të dhënave

Marrja dhe përpunimi i të dhënave
Marrja dhe përpunimi i të dhënave

Uniteti është një program i shkëlqyeshëm i disponueshëm falas për hobi

të interesuar për lojëra; vjen me një numër të madh të funksionaliteteve që me të vërtetë mund të zvogëlojnë në kohë vendosjen e gjërave të caktuara siç janë filetimi ose programimi i GPU (mbrojtja nga drita AKA) pa kufizuar atë që mund të bëhet me skriptet C#. Mikrokontrolluesit Unity dhe Arduino mund të përdoren së bashku për të krijuar përvoja unike ndërvepruese me një buxhet relativisht të vogël.

Fokusi i këtij udhëzimi është të ndihmojë në vendosjen e komunikimit midis Unitetit dhe Arduino kështu që ne nuk do të zhyten shumë thellë në shumicën e veçorive të disponueshme me Unity. Ka shumë mësime të shkëlqyera për unitetin dhe një komunitet të jashtëzakonshëm që mund të bëjë një punë shumë më të mirë duke shpjeguar se si funksionon Uniteti. Sidoqoftë, ka një çmim të veçantë për ata që arrijnë të punojnë në rrugën e tyre përmes këtij udhëzimi që shërben si një vitrinë e vogël e asaj që mund të bëhet. Ju mund të shkarkoni në Github tonë përpjekjen tonë të parë për të bërë një udhë me fizikë realiste të biçikletës.

Së pari, le të kalojmë nëpër minimumin që duhet bërë për të komunikuar me një Arduino përmes serialit. Do të jetë shpejt e qartë se ky kod nuk është i përshtatshëm për lojë, por është mirë të kalosh çdo hap dhe të mësosh se cilat janë kufizimet.

Në Unity, krijoni një skenë të re me një GameObject të vetëm të zbrazët të quajtur ArduinoReceive dhe bashkëngjitni një shkrim C# të quajtur gjithashtu ArduinoReceive. Ky skenar është vendi ku ne do të shtojmë të gjithë kodin që trajton komunikimin me Arduino.

Ekziston një bibliotekë që duhet të ketë qasje para se të mund të komunikojmë me portat serik të kompjuterit tuaj; Uniteti duhet të krijohet për të lejuar që disa biblioteka të përdoren. Shkoni te Edit-> ProjectSerring-> Player dhe pranë Nivelit të Përputhshmërisë Api nën çelësin e Konfigurimit. NET 2.0 Nënbashkësia në. NET 2.0. Tani shtoni kodin e mëposhtëm në krye të skenarit;

duke përdorur System. IO. Ports;

Kjo do t'ju lejojë të hyni në klasën SerialPort të cilën mund ta përcaktoni si objekt të Klasës ArduinoReceive. Bëjeni atë private për të shmangur çdo ndërhyrje nga një skenar tjetër.

SerialPort privat arduinoPort;

Objekti arduinoPort mund të hapet duke zgjedhur portën e duhur (p.sh. në të cilën USB është lidhur Arduino) dhe një normë baud (dmth shpejtësia me të cilën dërgohet informacioni). Nëse nuk jeni të sigurt se në cilën port është kyçur Arduino, mund ta zbuloni ose në menaxherin e pajisjes ose duke hapur Arduino IDE. Për normën e baud, vlera e paracaktuar në shumicën e pajisjeve është 9600, vetëm sigurohuni që ta keni këtë vlerë në kodin tuaj Arduino dhe duhet të funksionojë.

Kodi tani duhet të duket kështu;

duke përdorur System. Collection;

duke përdorur System. Collections. Generic; duke përdorur UnityEngine; duke përdorur System. IO. Ports; klasa publike ArduinoReceive: MonoBehaviour {private SerialPort arduinoPort; // Përdoreni këtë për inicimin e zbrazëtisë Start () {arduinoPort = new SerialPort ("COM5", 9600); arduinoPort. Open (); WriteToArduino ("TRIGG"); }}

Numri juaj COM ka shumë të ngjarë të jetë i ndryshëm. Nëse jeni në një MAC, emri juaj COM mund të ketë një emër që duket si ky /dev/cu.wchusbserial1420. Sigurohuni që kodi nga pjesa 4 të jetë ngarkuar në Arduino dhe monitori serik të jetë i mbyllur për pjesën tjetër të këtij seksioni dhe që ky kod të përpilohet pa problem.

Tani le t'i dërgojmë një kërkesë Arduino çdo kuadër dhe t'i shkruajmë rezultatet në dritaren e tastierës. Shtoni funksionin WriteToArduino në klasën ArduinoReceive. Kthimi i karrocës dhe linja e re janë të nevojshme që kodi Arduino të analizojë siç duhet udhëzimin në hyrje.

zbrazëti private WriteToArduino (mesazh vargu)

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

Ky funksion më pas mund të thirret në lakun Update.

void Update ()

{WriteToArduino ("TRIGG"); Debug. Log ("Vlera e parë:" + arduinoPort. ReadLine ()); Debug. Log ("Vlera e dytë:" + arduinoPort. ReadLine ()); }

Kodi i mësipërm është minimumi i nevojshëm për të lexuar të dhënat nga një Arduino. Nëse i kushtoni vëmendje FPS të dhënë nga uniteti, duhet të shihni një rënie të konsiderueshme të performancës. Në rastin tim, shkon nga rreth 90 FPS pa lexuar/shkruar në 20 FPS. Nëse projekti juaj nuk kërkon përditësime të shpeshta, mund të jetë i mjaftueshëm, por për një lojë video, 20 FPS janë shumë të ulëta. Seksioni tjetër do të mbulojë se si mund të përmirësoni performancën duke përdorur fije të shumta.

Hapi 4: Optimizimi i transferimit të të dhënave

Seksioni i mëparshëm mbuloi mënyrën e krijimit të bazës

komunikimi midis programit Arduino dhe Unity. Problemi kryesor me këtë kod është performanca. Në zbatimin e tij aktual, Uniteti duhet të presë që Arduino të marrë, përpunojë dhe përgjigjet në kërkesë. Gjatë asaj kohe, kodi i Unitetit duhet të presë që kërkesa të bëhet dhe nuk bën asgjë tjetër. Ne e zgjidhëm këtë çështje duke krijuar një fije që do të trajtojë kërkesat dhe do të ruajë ndryshoren në fillin kryesor.

Për të filluar, ne duhet të përfshijmë bibliotekën e filetimit duke shtuar;

duke përdorur System. Threading;

Tjetra, ne vendosim funksionin që po fillojmë në fijet. AsynchronousReadFromArduino fillon duke i shkruar kërkesën Arduino me funksionin WrtieToArduino. Leximi është i mbyllur në një bllok try-catch, nëse koha e leximit, ndryshoret mbeten nul dhe funksioni OnArduinoInfoFail thirret në vend të OnArduinoInfoReceive.

Tjetra ne përcaktojmë funksionet OnArduinoInfoFail dhe OnArduinoInfoReceive. Për këtë udhëzues, ne i printojmë rezultatet në tastierë, por ju mund t'i ruani rezultatet në variablat që ju nevojiten për projektin tuaj.

zbrazëti private OnArduinoInfoFail ()

{Debug. Log ("Leximi dështoi"); } private void OnArduinoInfoReceived (rrotullimi i vargut, shpejtësia e vargut) {Debug. Log ("Readin Successfull"); Debug. Log ("Vlera e parë:" + rrotullimi); Debug. Log ("Vlera e dytë:" + shpejtësia); }

Hapi i fundit është të filloni dhe ndaloni fijet që do të kërkojnë vlerat nga Arduino. Ne duhet të sigurohemi që fija e fundit të bëhet me detyrën e saj të fundit para se të filloni një të re. Përndryshe, kërkesat e shumta mund t'i bëhen Arduino në një kohë të vetme e cila mund të ngatërrojë Arduino/Unity dhe të japë rezultate të paparashikueshme.

fije private activeThread = null;

void Update () {if (activeThread == null ||! activeThread. IsAlive) {activeThread = fije e re (AsinkronousReadFromArduino); activeThread. Start (); }}

Nëse e krahasoni performancën e kodit me atë që kemi shkruar në pjesën 5, performanca duhet të përmirësohet ndjeshëm.

zbrazëti private OnArduinoInfoFail ()

{Debug. Log ("Leximi dështoi"); }

Hapi 5: Ku Tjetra?

Ku Tjetra?
Ku Tjetra?

Ne kemi përgatitur një demonstrim që mund ta shkarkoni në Github tonë (https://github.com/AlexandreDoucet/InfinityBike), shkarkoni kodin dhe lojën dhe kaloni nëpër rrugën tonë. E gjitha është krijuar për një stërvitje të shpejtë dhe shpresojmë se mund t'ju japë një shije të asaj që mund të ndërtoni nëse përdorni atë që ju mësuam me këtë udhëzues.

Kredite

Kontribuesit e projektit

Alexandre Doucet (_Doucet_)

Maxime Boudreau (MxBoud)

Burimet e jashtme [Motori i lojës së Unitetit] (https://unity3d.com)

Ky projekt filloi pasi lexuam mësimin nga Allan Zucconi "si të integrojmë Arduino me Unitetin" (https://www.alanzucconi.com/2015/10/07/how-to-int…)

Kërkesa nga Arduino trajtohet duke përdorur bibliotekën SerialCommand (https://github.com/kroimon/Arduino-SerialCommand)

Recommended: