Სარჩევი:

Infinity Bike - Indoors Bike სასწავლო ვიდეო თამაში: 5 ნაბიჯი
Infinity Bike - Indoors Bike სასწავლო ვიდეო თამაში: 5 ნაბიჯი

ვიდეო: Infinity Bike - Indoors Bike სასწავლო ვიდეო თამაში: 5 ნაბიჯი

ვიდეო: Infinity Bike - Indoors Bike სასწავლო ვიდეო თამაში: 5 ნაბიჯი
ვიდეო: Unreal Engine 5 Sequencer for Beginners 2024, ნოემბერი
Anonim
Image
Image
მასალები
მასალები

ზამთრის სეზონზე, ცივ დღეებსა და უამინდობაზე, ველოსიპედისტების მოყვარულებს აქვთ მხოლოდ რამდენიმე ვარიანტი განახორციელონ თავიანთი საყვარელი სპორტით. ჩვენ ვეძებთ გზას, რომ შიდა ტრენინგი ველოსიპედის/ტრენერის დაყენებით ცოტა უფრო გასართობი გავხადოთ, მაგრამ არსებული პროდუქციის უმეტესობა ან ძვირი ღირს, ან უბრალოდ მოსაწყენი. სწორედ ამიტომ დავიწყეთ Infinity Bike– ის განვითარება, როგორც ღია კოდის სასწავლო ვიდეო თამაში. უსასრულობის ველოსიპედი კითხულობს თქვენი ველოსიპედის სიჩქარეს და მიმართულებას და გთავაზობთ ინტერაქტიულობის დონეს, რომელიც ველოსიპედის ტრენერებთან ადვილად არ მოიძებნება.

ჩვენ ვიყენებთ სიმარტივეს Arduino მიკროკონტროლისგან და რამდენიმე 3D დაბეჭდილი ნაწილისგან, რათა უზრუნველვყოთ ტრენერზე დამონტაჟებული ველოსიპედის იაფი სენსორების უზრუნველყოფა. ინფორმაცია გადაეცემა ვიდეო თამაშს, რომელიც დამზადებულია პოპულარული თამაშების შემქმნელი ძრავით, Unity. ამ ინსტრუქციის ბოლოსთვის თქვენ უნდა შეძლოთ თქვენი სენსორების დაყენება თქვენს ველოსიპედზე და თქვენი სენსორების ინფორმაციის გადაცემა Unity– ში. ჩვენ ასევე ჩავრთეთ ბილიკი, რომელზედაც შეგიძლიათ იაროთ და გამოსცადოთ თქვენი ახალი შემადგენლობა. თუ თქვენ დაინტერესებული ხართ წვლილის შეტანით, შეგიძლიათ შეამოწმოთ ჩვენი GitHub.

ნაბიჯი 1: მასალები

მასალები
მასალები

მასალის ჩამონათვალი, რომელიც დაგჭირდებათ, შეიძლება ოდნავ განსხვავდებოდეს; ამისთვის

მაგალითად, თქვენი ველოსიპედის ზომა განსაზღვრავს თქვენთვის საჭირო ჯამპერის კაბელების სიგრძეს, მაგრამ აქ არის ძირითადი ნაწილები, რაც დაგჭირდებათ. თქვენ ალბათ იპოვით უფრო იაფ ფასებს თითოეული ნაწილისთვის ვებგვერდზე, როგორიცაა AliExpress, მაგრამ გადაზიდვისთვის 6 თვის ლოდინი ყოველთვის არ არის ვარიანტი, ასე რომ იყენებდით ოდნავ უფრო ძვირადღირებულ ნაწილებს, ასე რომ შეფასებები არ არის გადახრილი.

1 x Arduino nano ($ 22.00)

1 x მინი პურის დაფა ($ 1.33/ერთეული)

1 x 220 Ohm რეზისტორი ($ 1.00/ნაკრები)

1 x 10K პოტენომეტრი ($ 1.80/ერთეული)

1 x Hall სენსორი ($ 0.96)

20 სმ x 6 მმ 3D პრინტერის დროის ქამარი ($ 3.33)

1 ნაკრები x სხვადასხვა სიგრძის M3 ხრახნები და ჭანჭიკები ($ 6.82)

1 x ველოსიპედის სპიდომეტრის მაგნიტი ($ 0.98)

ჩვენ დავაყენეთ მასალა ზემოთ 3D ბეჭდვით ნაწილებით. ჩვენ მიერ გამოყენებული ფაილები ჩამოთვლილია ქვემოთ და ისინი დანომრილია იმავე კონვენციით, როგორც გამოსახულება ამ განყოფილების დასაწყისში. ყველა ფაილი შეგიძლიათ იხილოთ Thingiverse– ზე. თქვენ შეგიძლიათ გამოიყენოთ ისინი როგორც არის, მაგრამ დარწმუნდით, რომ ჩვენ მიერ გამოყენებული ზომები ემთხვევა თქვენს ველოსიპედს.

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

ნაბიჯი 2: მონაცემთა წაკითხვა და გადაცემა ერთიანობაზე

მონაცემების წაკითხვა და გადაცემა ერთიანობაზე
მონაცემების წაკითხვა და გადაცემა ერთიანობაზე

Arduino და Unity კოდი ერთად იმუშავებს შეგროვებაზე, ველოსიპედზე არსებული სენსორების მონაცემების გადაცემა და დამუშავება. Unity მოითხოვს ღირებულებას Arduino– სგან სერიის საშუალებით სტრიქონის გაგზავნით და დაელოდება Arduino– ს პასუხს მოთხოვნილი მნიშვნელობებით.

პირველ რიგში, ჩვენ ვამზადებთ Arduino– ს ბიბლიოთეკის სერიული ბრძანებით, რომელიც გამოიყენება Unity– ის მოთხოვნების მართვისთვის, მოთხოვნის სტრიქონის ფუნქციასთან შეთავსებით. ამ ბიბლიოთეკის ძირითადი შემადგენლობა შეიძლება გაკეთდეს შემდეგნაირად;

#მოიცავს "სერიული ბრძანება. თ"

SerialCommand sCmd; void setup () {sCmd.addCommand ("TRIGG", TriggHanlder); სერიული.დაწყება (9600); } void loop () {while (Serial.available ()> 0) {sCmd.readSerial (); }} void TriggHandler () { /*სენსორების წაკითხვა და გადაცემა აქ* /}

ფუნქცია TriggHandler მიმაგრებულია SCmd ობიექტზე. თუ სერიალი იღებს სტრიქონს, რომელიც შეესაბამება თანდართულ ბრძანებას (ამ შემთხვევაში TRIGG), ფუნქცია TriggHandler შესრულებულია.

ჩვენ ვიყენებთ პოტენომეტრს საჭის მიმართულების გასაზომად და დარბაზის სენსორს ველოსიპედის წუთში ბრუნვის გასაზომად. პოტენომეტრიდან კითხვები ადვილად შეიძლება გაკეთდეს Arduino– ს ჩამონტაჟებული ფუნქციების გამოყენებით. ფუნქციას TriggHandler შეუძლია დაბეჭდოს მნიშვნელობა სერიაზე შემდეგი ცვლილებით.

ბათილი TriggHandler () {

/*პოტენომეტრის მნიშვნელობის წაკითხვა*/ Serial.println (analogRead (ANALOGPIN)); }

ჰოლის სენსორს აქვს უფრო მეტი დაყენება, სანამ ჩვენ გვექნება სასარგებლო გაზომვები. პოტენომეტრის საპირისპიროდ, დარბაზების სენსორის მყისიერი მნიშვნელობა არ არის ძალიან სასარგებლო. მას შემდეგ, რაც ბორბლის სიჩქარის გაზომვას ცდილობდნენ, ტრიგერებს შორის დრო არის ის, რაც აინტერესებდათ.

არდუინოს კოდში გამოყენებულ ყველა ფუნქციას დრო სჭირდება და თუ მაგნიტი არასწორ დროს შეესაბამება ჰოლის სენსორს, გაზომვა საუკეთესოდ შეიძლება გადაიდოს ან უარეს შემთხვევაში მთლიანად გამოტოვდეს. ეს აშკარად ცუდია, რადგან Arduino– ს შეუძლია შეატყობინოს სიჩქარე, რომელიც ძალიან განსხვავდება ბორბლის რეალური სიჩქარისგან.

ამის თავიდან ასაცილებლად, ჩვენ ვიყენებთ Arduinos– ის მახასიათებელს, სახელწოდებით attach interrupt, რომელიც საშუალებას გვაძლევს გავააქტიუროთ ფუნქცია ყოველთვის, როდესაც დანიშნული ციფრული პინი ამოქმედდება მზარდი სიგნალით. ფუნქცია rpm_fun თან ერთვის წყვეტს და კოდის ერთი ხაზი ემატება კონფიგურაციის კოდს.

void setup () {

sCmd.addCommand ("TRIGG", TriggHanlder); attachInterrupt (0, rpm_fun, RISING); სერიული.დაწყება (9600); } // ფუნქცია rpm_fun გამოიყენება სიჩქარის გამოსათვლელად და განისაზღვრება როგორც; ხელმოუწერელი long lastRevolTime = 0; ხელმოუწერელი გრძელი revolSpeed = 0; void rpm_fun () {unsigned long revolTime = millis (); ხელმოუწერელი გრძელი deltaTime = revolTime - lastRevolTime; /*revolSpeed არის მნიშვნელობა Arduino კოდზე გადაცემული* / revolSpeed = 20000 / deltaTime; lastRevolTime = revolTime; } TriggHandler– ს შეუძლია მაშინ გადასცეს დანარჩენი ინფორმაცია მოთხოვნის შემთხვევაში. void TriggHanlder () { /*პოტენომეტრის მნიშვნელობის წაკითხვა* / Serial.println (analogRead (ANALOGPIN)); Serial.println (revolSpeed); }

ჩვენ ახლა გვაქვს ყველა სამშენებლო ბლოკი, რომელიც შეიძლება გამოყენებულ იქნას Arduino კოდის შესაქმნელად, რომელიც გადასცემს მონაცემებს სერიალის საშუალებით, როდესაც Unity ითხოვს მოთხოვნას. თუ გსურთ გქონდეთ სრული კოდის ასლი, შეგიძლიათ გადმოწეროთ ჩვენს GitHub– ზე. კოდის სწორად დაყენების შესამოწმებლად შეგიძლიათ გამოიყენოთ სერიული მონიტორი TRIGG– ის გასაგზავნად; დარწმუნდით, რომ თქვენ დააყენეთ ხაზი, რომელიც მთავრდება ვაგონის დაბრუნებით. მომდევნო ნაწილი ყურადღებას გაამახვილებს იმაზე, თუ როგორ შეიძლება ჩვენი ერთობის სკრიპტებს მოითხოვონ და მიიღონ ინფორმაცია არდუინოსგან.

ნაბიჯი 3: მონაცემების მიღება და დამუშავება

მონაცემების მიღება და დამუშავება
მონაცემების მიღება და დამუშავება

Unity არის შესანიშნავი პროგრამული უზრუნველყოფა, რომელიც ხელმისაწვდომია უფასოდ მოყვარულთათვის

დაინტერესებულია თამაშის დამზადებით; მას გააჩნია მრავალი ფუნქცია, რომელსაც ნამდვილად შეუძლია დროულად შეამციროს გარკვეული საკითხების დაყენება, როგორიცაა ძაფი ან GPU პროგრამირება (AKA დაჩრდილვა) შეზღუდვის გარეშე, თუ რა შეიძლება გაკეთდეს C# სკრიპტებით. Unity და Arduino მიკროკონტროლერები შეიძლება გამოყენებულ იქნას ერთად, რათა შეიქმნას უნიკალური ინტერაქტიული გამოცდილება შედარებით მცირე ბიუჯეტით.

ამ ინსტრუქციის მთავარი მიზანია დაეხმაროს Unity– სა და Arduino– ს შორის კომუნიკაციის დამყარებაში, ასე რომ ჩვენ არ ჩავუღრმავდებით Unity– ის უმეტეს მახასიათებლებს. არსებობს უამრავი დიდი გაკვეთილი ერთიანობისთვის და წარმოუდგენელი საზოგადოებისათვის, რომელსაც გაცილებით უკეთესი სამუშაოს შესრულება შეუძლია იმის ახსნა, თუ როგორ მუშაობს ერთიანობა. თუმცა, არსებობს სპეციალური პრიზი მათთვის, ვინც შეძლებს ამ გზას გაუდგას გზას, რომელიც წარმოადგენს მცირედი წარმოდგენას იმისა, რისი გაკეთებაც შეიძლებოდა. თქვენ შეგიძლიათ გადმოწეროთ ჩვენს Github– ზე ჩვენი პირველი მცდელობა ტრეკის შესაქმნელად რეალისტური ველოსიპედის ფიზიკით.

პირველი, მოდით გავარკვიოთ მინიმალური, რაც უნდა გაკეთდეს იმისათვის, რომ არდუინოს დაუკავშირდეთ სერიალის საშუალებით. სწრაფად გამოჩნდება, რომ ეს კოდი არ არის შესაფერისი თამაშისთვის, მაგრამ კარგია გაიაროთ ყველა ნაბიჯი და გაიგოთ რა შეზღუდვებია.

Unity– ში შექმენით ახალი სცენა ერთი ცარიელი GameObject– ით, სახელად ArduinoReceive, მიამაგრეთ C# სკრიპტი, რომელსაც ასევე ჰქვია ArduinoReceive. ეს სკრიპტი არის ის, სადაც ჩვენ დავამატებთ მთელ კოდს, რომელიც ამუშავებს Arduino– სთან კომუნიკაციას.

არსებობს ბიბლიოთეკა, რომელზეც უნდა იყოს წვდომა, სანამ ჩვენ შევძლებთ თქვენი კომპიუტერის სერიულ პორტებთან დაკავშირებას; ერთიანობა უნდა შეიქმნას, რომ შესაძლებელი იყოს გარკვეული ბიბლიოთეკების გამოყენება. გადადით რედაქტირება-> ProjectSerring-> პლეერი და კონფიგურაციის შეცვლის ქვეშ Api თავსებადობის დონის გვერდით. NET 2.0 ქვეჯგუფში. NET 2.0. ახლა დაამატეთ შემდეგი კოდი სკრიპტის ზედა ნაწილში;

System. IO. Ports- ის გამოყენებით;

ეს მოგცემთ წვდომას SerialPort კლასზე, რომელიც შეგიძლიათ განსაზღვროთ როგორც ArduinoReceive კლასის ობიექტი. გახადეთ ის პირადი, რათა თავიდან აიცილოთ სხვა სკრიპტის ჩარევა.

პირადი SerialPort arduinoPort;

ობიექტის arduinoPort შეიძლება გაიხსნას სწორი პორტის არჩევით (მაგალითად, რომელ USB– შია Arduino დაკავშირებული) და baud განაკვეთი (ანუ ინფორმაციის გაგზავნის სიჩქარე). თუ არ ხართ დარწმუნებული, რომელ პორტშია ჩართული Arduino, შეგიძლიათ გაიგოთ მოწყობილობის მენეჯერში ან Arduino IDE- ს გახსნით. ბოდის სიჩქარისთვის, მოწყობილობის უმეტესობაზე ნაგულისხმევი მნიშვნელობაა 9600, უბრალოდ დარწმუნდით, რომ გაქვთ ეს მნიშვნელობა თქვენს Arduino კოდში და ის უნდა იმუშაოს.

კოდი ახლა ასე უნდა გამოიყურებოდეს;

System. Collection- ების გამოყენებით;

System. Collections. Generic- ის გამოყენებით; UnityEngine- ის გამოყენებით; System. IO. Ports- ის გამოყენებით; საჯარო კლასი ArduinoReceive: MonoBehaviour {პირადი SerialPort arduinoPort; // გამოიყენეთ ეს ინიციალიზაციისთვის void Start () {arduinoPort = new SerialPort ("COM5", 9600); arduinoPort. Open (); WriteToArduino ("TRIGG"); }}

თქვენი COM ნომერი, სავარაუდოდ, განსხვავებული იქნება. თუ თქვენ MAC– ზე ხართ, თქვენი COM სახელი შეიძლება ჰქონდეს სახელს, რომელიც ასე გამოიყურება /dev/cu.wchusbserial1420. დარწმუნდით, რომ კოდი მე –4 ნაწილიდან აიტვირთება Arduino– ში და სერიული მონიტორი დახურულია ამ მონაკვეთის დანარჩენ ნაწილში და რომ ეს კოდი შედგენილია უპრობლემოდ.

მოდით გავგზავნოთ მოთხოვნა Arduino– ს ყველა ჩარჩოზე და შედეგები დავწეროთ კონსოლის ფანჯარაში. დაამატეთ WriteToArduino ფუნქცია კლასში ArduinoReceive. ვაგონის დაბრუნება და ახალი ხაზი აუცილებელია არდუინოს კოდისთვის, რათა სწორად გაანალიზდეს შემომავალი ინსტრუქცია.

პირადი სიცარიელე WriteToArduino (სიმებიანი შეტყობინება)

{შეტყობინება = შეტყობინება + "\ r / n"; arduinoPort. Write (შეტყობინება); arduinoPort. BaseStream. Fush (); }

ამ ფუნქციის დარეკვა შესაძლებელია განახლების მარყუჟში.

ბათილი განახლება ()

{WriteToArduino ("TRIGG"); Debug. Log ("პირველი მნიშვნელობა:" + arduinoPort. ReadLine ()); Debug. Log ("მეორე მნიშვნელობა:" + arduinoPort. ReadLine ()); }

ზემოთ მოყვანილი კოდი არის მინიმალური, რაც გჭირდებათ არდუინოს მონაცემების წასაკითხად. თუ დიდ ყურადღებას უთმობთ FPS– ს ერთიანობით, თქვენ უნდა დაინახოთ შესრულების მნიშვნელოვანი ვარდნა. ჩემს შემთხვევაში, ის გადადის 90 FPS– დან წაკითხვის/წერის გარეშე 20 FPS– მდე. თუ თქვენი პროექტი არ საჭიროებს ხშირ განახლებებს, ეს შეიძლება იყოს საკმარისი, მაგრამ ვიდეო თამაშისთვის, 20 FPS არის ძალიან დაბალი. მომდევნო ნაწილი მოიცავს იმას, თუ როგორ შეგიძლიათ გააუმჯობესოთ შესრულება მულტი -ძაფის გამოყენებით.

ნაბიჯი 4: მონაცემთა გადაცემის ოპტიმიზაცია

წინა ნაწილი მოიცავდა ძირითად პარამეტრებს

კომუნიკაცია არდუინოს და ერთობის პროგრამას შორის. ამ კოდის მთავარი პრობლემა არის შესრულება. მისი ახლანდელი განხორციელებით, Unity უნდა დაელოდოს Arduino– ს მოთხოვნის მიღებას, დამუშავებას და პასუხს. იმ დროის განმავლობაში, Unity კოდი უნდა დაელოდოს მოთხოვნის შესრულებას და სხვას არაფერს აკეთებს. ჩვენ გადავწყვიტეთ ეს საკითხი ძაფის შექმნით, რომელიც გაუმკლავდება მოთხოვნებს და შეინახავს ცვლადს მთავარ ძაფზე.

დასაწყისისთვის, ჩვენ უნდა შევიტანოთ ძაფის ბიბლიოთეკა დამატებით;

System. Threading– ის გამოყენებით;

შემდეგი, ჩვენ დავაყენებთ იმ ფუნქციას, რომელსაც ვიწყებთ ძაფებში. AsynchronousReadFromArduino იწყებს მოთხოვნის ჩაწერას Arduino– სთან WrtieToArduino ფუნქციით. კითხვა იწერება try-catch ბლოკში, თუ წაკითხვის ვადა ამოიწურება, ცვლადები რჩება ნულოვანი და OnArduinoInfoFail ფუნქციას იძახება OnArduinoInfoReceive ნაცვლად.

შემდეგი ჩვენ განვსაზღვრავთ OnArduinoInfoFail და OnArduinoInfoReceive ფუნქციებს. ამ ინსტრუქციისთვის, ჩვენ შედეგებს ვბეჭდავთ კონსოლზე, მაგრამ თქვენ შეგიძლიათ შეინახოთ შედეგები იმ ცვლადებში, რომლებიც გჭირდებათ თქვენი პროექტისათვის.

პირადი სიცარიელე OnArduinoInfoFail ()

{Debug. Log ("კითხვა ვერ მოხერხდა"); } private void OnArduinoInfoReceived (სიმების ბრუნვა, სიმების სიჩქარე) {Debug. Log ("Readin Successfull"); Debug. Log ("პირველი მნიშვნელობა:" + როტაცია); Debug. Log ("მეორე მნიშვნელობა:" + სიჩქარე); }

ბოლო ნაბიჯი არის თემების დაწყება და შეჩერება, რომლებიც მოითხოვენ მნიშვნელობებს არდუინოსგან. ჩვენ უნდა დავრწმუნდეთ, რომ ბოლო ძაფი შესრულებულია მისი ბოლო დავალებით ახლის დაწყებამდე. წინააღმდეგ შემთხვევაში, Arduino– სთვის ერთდროულად შეიძლება გაკეთდეს მრავალი მოთხოვნა, რამაც შეიძლება დაარღვიოს Arduino/Unity და გამოიღოს არაპროგნოზირებადი შედეგები.

პირადი თემა activeThread = null;

void Update () {if (activeThread == null ||! activeThread. IsAlive) {activeThread = ახალი თემა (AsynchronousReadFromArduino); activeThread. Start (); }}

თუ შეადარებთ კოდის შესრულებას იმასთან, რაც ჩვენ დავწერეთ მე –5 ნაწილში, შესრულება მნიშვნელოვნად უნდა გაუმჯობესდეს.

პირადი სიცარიელე OnArduinoInfoFail ()

{Debug. Log ("კითხვა ვერ მოხერხდა"); }

ნაბიჯი 5: სად არის შემდეგი?

სად შემდეგ?
სად შემდეგ?

ჩვენ მოვამზადეთ დემო, რომლის გადმოწერაც შეგიძლიათ ჩვენს Github– ზე (https://github.com/AlexandreDoucet/InfinityBike), ჩამოტვირთეთ კოდი და თამაში და იარეთ ჩვენს ტრასაზე. ეს ყველაფერი შექმნილია სწრაფი ვარჯიშისთვის და ჩვენ ვიმედოვნებთ, რომ ის მოგცემთ იმის გაგებას, თუ რისი აშენება შეგიძლიათ, თუ გამოიყენებთ იმას, რაც ჩვენ გვასწავლეთ ამ სასწავლო ინსტრუქციით.

კრედიტები

პროექტის მონაწილეები

ალექსანდრე დოუსე (_ დუკეტი)

მაქსიმე ბუდრო (MxBoud)

გარე რესურსები [The Unity თამაშის ძრავა] (https://unity3d.com)

ეს პროექტი დაიწყო მას შემდეგ რაც წავიკითხეთ ალან ზუკონის სახელმძღვანელო "როგორ გავაერთიანოთ არდუინო ერთობასთან" (https://www.alanzucconi.com/2015/10/07/how-to-int…)

Arduino– ს მოთხოვნა განიხილება SerialCommand ბიბლიოთეკის გამოყენებით (https://github.com/kroimon/Arduino-SerialCommand)

გირჩევთ: