Სარჩევი:
- ნაბიჯი 1: IMU სენსორი
- ნაბიჯი 2: ყველაფერი ყოველთვის არ არის სუფთა, მარტივი
- ნაბიჯი 3: საწყისი ტესტი
- ნაბიჯი 4: პრობლემების მოგვარება
- ნაბიჯი 5: სენსორის მონაცემების კითხვა
- ნაბიჯი 6: მოდით უფრო მეტად ჩავწვდეთ კითხვას / მონაცემებს
- ნაბიჯი 7: ჩვენ შეგვიძლია ვიმოქმედოთ ტემპერატურაზე და აჩქარებაზე
- ნაბიჯი 8: ამაჩქარებელი და გიროსკოპი
- ნაბიჯი 9: (მუშაობა პროგრესში) მაგნიტომეტრი
ვიდეო: უოლესი - წვრილმანი ავტონომიური რობოტი - ნაწილი 5 - დაამატეთ IMU: 9 ნაბიჯი
2024 ავტორი: John Day | [email protected]. ბოლოს შეცვლილი: 2024-01-30 10:19
ჩვენ ვალასთან ერთად მივდივართ. სახელი უოლესი წარმოიშვა "Wall-E"-ის ნაზავიდან და წინა პროექტიდან (ხმის ამოცნობა) და "espeak"-ის გამოყენებისას ის ცოტა ბრიტანულად ჟღერდა. როგორც მევახშე ან მეკარე. და ეს არის საბოლოო მიზანი: რომ ეს პროექტი იქცეს სასარგებლოდ. ამრიგად, "უოლესი".
უოლესს შეუძლია გადაადგილება, მას შეუძლია თავიდან აიცილოს დაბრკოლებები IR დისტანციის სენსორების გამოყენებით (ცოტა ხნის წინ, რატომღაც ისინი შემწვარი (?) (უნდა გავითვალისწინო, როდესაც მე მივიღებ შანსს), ასევე აქვს აკუსტიკური დისტანციის სენსორები (სამი მათგანი ერთდროულად ცუდად წავიდა) დრო, MCP23017 გაფართოებასთან ერთად) და ბოლოს, შეუძლია გამოავლინოს ძრავის დენის ცვლილებები, რათა იცოდეს, როდესაც ის რაღაცას ეჯახება.
სენსორების გარდა, უოლესს "ახსოვს" 100 ნაბიჯი და აქვს რამოდენიმე ელემენტარული ანალიზი მოძრაობის ისტორიის გამოყენებით.
ჯერჯერობით უოლესისთვის მიზანია უბრალოდ შეინარჩუნოს წინსვლა და იცოდეს როდის ჩერდება ის რაღაც განმეორებით ნიმუშში (მაგალითად კუთხეში) და ნამდვილად არ წინ მიიწევს.
მე გავიარე რამდენიმე გამეორება მოძრაობისა და ნავიგაციისთვის და თანმიმდევრული თავის ტკივილი იყო როტაციის დროს.
ვინაიდან უოლესი არის თვალთვალიანი რობოტი და მე მინდოდა პროგრამებში უფრო მარტივი გამეკეთებინა ყველაფერი (შემდგომში), რათა შემობრუნებულიყო მე უბრალოდ მებრუნება/ბრუნვა. ამრიგად, გამოიყენეთ თანაბარი, მაგრამ საპირისპირო სიმძლავრე / მოვალეობის ციკლი ძრავებზე.
პრობლემა, რომელიც გამოწვეულია აგენტის 390 რობოტული პლატფორმის დიზაინით. ტრასის ქამრები მიდრეკილია გვერდებზე. და რაც უარესია, ერთი მხარე ამას უფრო მეტს აკეთებს ვიდრე მეორე.
იატაკზე და პირდაპირ გასვლაზე, პრობლემა არ ყოფილა. გამოჩნდება ხალიჩაზე. მე შევარჩიე, რომ უოლესი დაეტოვებინა ხალიჩაზე მას შემდეგ, რაც მისი ბილიკები ბინძურდებოდა (ისინი ძალიან ადვილად იღებენ გრიმს).
რეალური პრობლემაა იატაკზე ბრუნვისას.
თუ მე მაქვს პროგრამული უზრუნველყოფა, რომელიც იყენებს მაღალი დონის მოვალეობის ციკლს, მაშინ ის მეტნაკლებად თანმიმდევრულად ბრუნავს. თუმცა, დაბალი მოვალეობის შემსრულებელი ციკლის დროს, ის შეიძლება რეალურად შემობრუნდეს ან არა. ან ის შეიძლება ოდნავ შემობრუნდეს და შემდეგ შენელდეს. როგორც ჩანს, მბრუნავი მოქმედება არაკონტროლირებადია პროგრამული უზრუნველყოფის საშუალებით, ან საუკეთესო შემთხვევაში ძალიან რთულია.
პრობლემა ვლინდება ნავიგაციის დროს და დაბრკოლებების ირგვლივ გადაადგილებისას. მას შეუძლია ან ძალიან ველურად გადატრიალდეს, ან შეიძლება ჩარჩენილიყო ძალიან მცირე ცვლის მცდელობისას, მოძრაობის გარეშეც კი.
ასე რომ, ზემოაღნიშნულმა ახსნა -განმარტებამ მოტივაცია მისცა ამ ინსტრუქციას.
თავდაპირველად, მე მინდოდა უარი მეთქვა ან გადამედო მოძრაობის აღქმის ერთეულის (IMU) დანერგვა, რადგან ისინი არიან ა) გართულებული, ბ) ხმაურიანი, გ) შეცდომები შეიძლება დროთა განმავლობაში და ა.შ. და ა.შ. ჩვენ შეგვიძლია ძალიან კარგად გავაკეთოთ ფრენის დროის IR ლაზერული სენსორების წინ გადახტომით. და ჩვენ შეგვეძლო - ლაზერების გამოყენებით გვეცოდინებოდა რობოტი ბრუნავდა თუ არა, მანძილზე ცვლილებების თვალყურის დევნებით.
სინამდვილეში, ჩვენ ასევე შეგვიძლია (ერთგვარი) ამის გაკეთება ახლა, აკუსტიკური სენსორებით.
თუმცა, ეს ყველაფერი ძალიან არაპირდაპირი, რთული გზაა ერთ მარტივ კითხვაზე პასუხის გასაცემად: "ჩვენ შევბრუნდით თუ არა?"
მომეჩვენა, რომ ToF ლაზერული სენსორების გამოყენებისას გადახტომა გადამიყვანდა პროგრამული უზრუნველყოფის შემდეგ საფეხურზე; კერძოდ, SLAM (ერთდროული ლოკალიზაცია და რუქა). ჯერ არ ვიყავი მზად იქ წასასვლელად.
კარგია რობოტის პროექტის გაკეთება ფენებად, პირველი (ქვედა) ფენები უფრო მარტივი და ეს უკანასკნელი (ზედა) უფრო აბსტრაქტული და უფრო რთულ საკითხებს ეხება.
ფენების მსგავსი რამ შეიძლება წარმოვიდგინოთ:
- რობოტის ფიზიკური ჩარჩო / მექანიკური სტრუქტურული საფუძველი
- ელემენტარული მართვის სისტემა (ჟოლო, რობოკლავი, ძრავები, კაბელები და სხვა, ძირითადი პროგრამული უზრუნველყოფა, კლავიატურაზე ორიენტირებული)
- ძირითადი სქემა სენსორების მხარდასაჭერად (ორმხრივი ძაბვის ამომრთველი, პორტის გაფართოება, ელექტრონული გაჩერება, ენერგიის განაწილება და სხვა)
- დაბრკოლების თავიდან აცილების სენსორები (აკუსტიკური, IR)
- არსებითი, ძირითადი პოზიციონირება და მოძრაობა - გამოვლენა (ამაჩქარებელი, გირო, მაგნიტომეტრი, საავტომობილო კოდირება, ბორბლის კოდირება)
თქვენ შეგიძლიათ შეადგინოთ თქვენი საკუთარი სია. ამ სიის პუნქტები იმაში მდგომარეობს, რომ თქვენ ალბათ უნდა გააკეთოთ ეს მეტ -ნაკლებად ამ თანმიმდევრობით და ასევე ის, რომ თუ თითოეულ ფენაზე დახარჯავთ დროს კარგ სამუშაო მდგომარეობამდე მისასვლელად, ეს მოგვიანებით დაგეხმარება, რადგან ყველაფერი უფრო გართულდება.
ზემოთ ჩამოთვლილი სია შეიძლება მეტ -ნაკლებად იყოს ასახული ამ კონცეპტუალურ ფენებში პროგრამულ უზრუნველყოფაში.
- SLAM (ერთდროული ლოკალიზაცია და რუქა)
- მოძრაობის კონტროლი და ცნობიერება, როტაცია
- ძირითადი დაბრკოლების თავიდან აცილება
- სენსორული მონაცემების კონტროლი და გამოვლენა
- არსებითი მოძრაობა წინ, უკან, მარცხნივ და მარჯვნივ, აჩქარება, შენელება, გაჩერება
როგორც ხედავთ, ამ სიისათვის პირველი პუნქტები იქნება ზედა, უფრო რთული ფენები, რომლებიც უფრო აბსტრაქტულ საკითხებსა და კითხვებს ეხება, როგორიცაა "სად ვარ" და "სად მივდივარ", ხოლო ეს უკანასკნელი იქნება პროგრამული უზრუნველყოფის ქვედა ფენები, რომლებიც ატარებენ "როგორ უნდა ვისაუბროთ/მოვუსმინოთ სენსორს A" ან "როგორ გადავიტანოთ ეს ბორბალი".
ახლა, მე არ ვამბობ, რომ როდესაც დაიწყებ ფენას, დაასრულებ მას და შემდეგ ის იქნება შემდეგ ფენაზე, არასოდეს დაბრუნდე წინაზე. რობოტის პროექტი შეიძლება ძალიან ჰგავდეს პროგრამის განვითარების თანამედროვე, განმეორებით მეთოდებს (სწრაფი, SCRUM და ა.
მე უბრალოდ ვამბობ, რომ დრო დაუთმოს თითოეულ მათგანს. თქვენ უნდა დააბალანსოთ რამდენი უნდა გააკეთოთ თითოეულში და გადაწყვიტეთ, რას ცდილობთ გარკვეულ ფენაში, დროსა და უბედურებად.
არსებობს გარკვეული "კონფლიქტი" ან "დაძაბულობა" ორ კონკურენტულ იდეასა თუ მიმართულებას შორის.
ერთი არის ის, რასაც მე ვუწოდებ "plug-n-play"-ს პრობლემის გადასაჭრელად.
მეორე არის წვრილმანი (გააკეთე ეს შენ თვითონ). და ეს შეიძლება არც იყოს საუკეთესო იარლიყი ამ სხვა იდეისთვის.
აქ მოცემულია თითოეული მათგანის მაგალითი, იმედია ნახავთ დაძაბულობას ან კონფლიქტს ორ არჩევანს შორის.
ამ მაგალითისთვის, მოდით შევაჯამოთ SLAM, დაბრკოლებების თავიდან აცილება და ძირითადი ძირითადი მოძრაობა, როგორც ერთი პრობლემა ერთდროულად მოსაგვარებლად.
- თუ ჩვენ გადავწყვეტთ plug-n-play მარშრუტის გავლას, მაშინვე (ბიუჯეტის მიხედვით) გადავდივართ ისეთებზე, როგორიცაა ზემოდან დამონტაჟებული მბრუნავი ლაზერები, ან ველის სიღრმის კამერა, ან ToF ლაზერები და IMU (ამ თემის თემა ინსტრუქცია).
- თუ ჩვენ, მეორეს მხრივ, გვინდა მეორე მარშრუტის გავლა, შეიძლება შევეცადოთ ამოვიღოთ ყველა შესაძლო ინფორმაცია ზოგიერთი აკუსტიკური სენსორიდან ან IR სენსორიდან, ან საერთოდ არ გვყავს - ჩვენ უბრალოდ ვიყენებთ ძრავის მიმდინარე მონიტორინგს (დარტყმა)
რა შეიძლება ითქვას #1 -ის წინააღმდეგ #2 -ის შესახებ? ერთი რამ იქნებოდა, რომ ჩვენ მეტს ვისწავლიდით #2 – ით. მხოლოდ აკუსტიკური სენსორების მუშაობის შეზღუდვები გვაიძულებს ვიფიქროთ ბევრად მეტ საკითხზე.
მეორეს მხრივ, თუ ჩვენ ძალიან კონცენტრირებულნი ვართ საქმეების #2 საშუალებით გაკეთებაზე, ჩვენ შეგვიძლია დროის დაკარგვა, რადგან ჩვენ იმაზე მეტს ვითხოვთ ვიდრე საჭიროა აკუსტიკური სენსორებისგან.
კიდევ ერთი კონცეფცია ან იდეა დასაფიქრებელი: აპარატურის და პროგრამული უზრუნველყოფის რომელი ნარევი საუკეთესოდ პასუხობს კითხვებს "როგორ", და პროგრამული უზრუნველყოფის რა ნარევი (და აპარატურა?) პასუხობს კითხვას "რა", "როდის", "სად" რა რადგან "როგორ" ჩვეულებრივ არის ქვედა დონის კითხვა, რომელზედაც დამოკიდებულია "რა", "როდის" და "სად" პასუხის მისაღებად.
ყოველ შემთხვევაში, ყოველივე ზემოთქმული იყო მხოლოდ დასაფიქრებელი.
ჩემს შემთხვევაში, დიდი ძალისხმევის შემდეგ და თანმიმდევრული შემაშფოთებელი პრობლემის მქონე გზაზე და ვერ მივიღე თანმიმდევრული კონტროლი და მოძრაობა, დროა სხვა რამის გაკეთება.
ამდენად ეს Instructable - IMU.
მიზანია, თუ IMU ამბობს, რომ რობოტი არ ბრუნავს, ჩვენ გავზარდოთ მოვალეობის ციკლი. თუ ჩვენ ძალიან სწრაფად ვტრიალებთ, ჩვენ ვამცირებთ სამუშაო ციკლს.
ნაბიჯი 1: IMU სენსორი
ასე რომ, ჩვენი შემდეგი სენსორი, რომელსაც უოლესს დავამატებთ არის IMU. გარკვეული კვლევის შემდეგ, მე ვიღებდი გადაწყვეტილებას MPU6050– ზე. მაგრამ შემდეგ ამ დროს, MPU9050 (და კიდევ უფრო ცოტა ხნის წინ, MPU9250) კიდევ უფრო უკეთესი იდეა ჩანდა.
ჩემი წყარო იყო ამაზონი (აშშ-ში). ამიტომ შევუკვეთე ორი მათგანი.
რაც მე რეალურად მივიღე (როგორც ჩანს, ამაზე კონტროლი არ არის; ეს არის ის, რაც მე არ მომწონს ამაზონში) იყო ორი MPU92/65. ცოტა მაინტერესებს აღნიშვნის შესახებ. გადახედეთ სურათებს; როგორც ჩანს, ეს არის "ოჯახის" აღნიშვნა. ყოველ შემთხვევაში, ეს არის ის, რაც მე დავრჩი.
მისი დამატება ძალიან მარტივია -მიიღეთ პროტო დაფა დამაკავშირებელი ბილიკებით, შეაერთეთ სენსორი ბორტზე, დაამატეთ 10 პინიანი ხრახნიანი ტერმინალის ბლოკი (მე მივიღე ჩემი პოლოლუდან).
ყოველგვარი ჩარევის შესამცირებლად, მე შევეცადე ეს სენსორები ყველაფრისგან მოშორებით.
ეს ასევე გულისხმობდა ნეილონის ჭანჭიკების/კაკლების გამოყენებას.
ვაპირებ გამოვიყენო I2C პროტოკოლი. ვიმედოვნებთ, რომ მავთულის მთლიანი სიგრძე არ იქნება ცუდი.
სხვაგან არის უამრავი ინფორმაცია ძირითადი კავშირებისა და ძაბვის დონის შესახებ და ა.შ., ასე რომ მე ამას აქ არ გავიმეორებ.
ნაბიჯი 2: ყველაფერი ყოველთვის არ არის სუფთა, მარტივი
ამ წერისას, როგორც ჩანს, ბევრი არ არის ინტერნეტში ამ კონკრეტული MPU-92/65– ისთვის. ის, რაც არის ხელმისაწვდომი, ისევე როგორც სენსორების უმეტესობა, როგორც ჩანს, არის მაგალითები Arduino– ს გამოყენებით.
ვცდილობ, ეს ინსტრუქციები ცოტა განსხვავებული გავხადო არც თუ ისე სუფთა პროცესის წარმოდგენით, რადგან ყველაფერი ყოველთვის არ მუშაობს მაშინვე.
ვფიქრობ, ეს ინსტრუქციები უფრო წააგავს ბლოგს, ვიდრე პირდაპირ A-B-C, 1-2-3 "ასე აკეთებ ამას".
ნაბიჯი 3: საწყისი ტესტი
წინა ნაბიჯის სურათებიდან, სენსორებისკენ მიმავალი წითელი და შავი მავთულები, რა თქმა უნდა, არის VCC (5V) და GND. მწვანე და ყვითელი მავთულები არის I2C კავშირები.
თუ თქვენ გაქვთ სხვა I2C პროექტები ან მიჰყვებით ამ სერიებს, მაშინ უკვე იცით "i2cdetect" - ის შესახებ და ეს არის პირველი ნაბიჯი იმის გასარკვევად, შეუძლია თუ არა ჟოლოს ახალი სენსორის ნახვა.
როგორც ამ ნაბიჯის სურათებიდან ხედავთ, ჩვენი პირველი მცდელობა წარუმატებელი აღმოჩნდა. IMU არ გამოჩნდება (უნდა იყოს მოწყობილობის id 0x68).
თუმცა, კარგი ამბავი ის არის, რომ I2C ავტობუსი მუშაობს. ჩვენ ვხედავთ ერთ მოწყობილობას 0x20 და ეს არის MCP23017 პორტის გაფართოება (ამჟამად პასუხისმგებელია HCSR04 აკუსტიკური სენსორებისთვის).
სურათის დანახვა ადვილი არ არის, მაგრამ მე დავუკავშირე იგივე ფერის მწვანე და ყვითელი მავთულები IMU– დან MCP23017– ს (იხ. ქვედა მარცხენა სურათი)
ჩვენ მოგვიწევს გარკვეული პრობლემების მოგვარება.
ნაბიჯი 4: პრობლემების მოგვარება
ვოლტმეტრზე უწყვეტობის პარამეტრის გამოყენებით (ის მაღალი ტონით), მე გამოვცადე VCC (5V), GND, SDA და SCL კავშირები. ეს კარგი იყო.
შემდეგი მცდელობა იყო MCP23017 გათიშვა I2C ავტობუსიდან, ავტობუსში დარჩა მხოლოდ MPU-92/65. ეს უნაყოფო აღმოჩნდა - "i2cdetect" - მა მაშინ არ აჩვენა მოწყობილობები.
ასე რომ, შემდეგ, მე ამოვიღე სენსორი ტოტემის ბოძიდან და ხელახლა შევიყვანე პირდაპირ 5V-3V ორმხრივი ავტობუსში; ანუ, პირდაპირ ჟოლოსთან. (მოკლე მავთულები?).
და ვოილა. ამჯერად არის წარმატება. ჩვენ ვხედავთ, რომ 0x68 გამოჩნდება "i2cdetect" - ის გამოყენებით.
მაგრამ ჩვენ ჯერ არ ვიცით, რატომ იმუშავა ამჯერად. შეიძლება ეს იყოს მავთულის სიგრძე? წინა ადგილმდებარეობა?
შენიშვნა: არანაირი მნიშვნელობა არ აქვს ADO დასაბუთებული იყო თუ არა. ეს შეიძლება იყოს ბორტზე გამყვანი და გასაშლელი რეზისტორები. იგივე შეიძლება ითქვას FSYNC– ზეც.
შემდეგი, მე ხელახლა დავუკავშირე MCP23017. ახლა ჩვენ გვაქვს ორი მოწყობილობა I2C ავტობუსზე. (იხ. სურათი). წარმატებები, ჩვენ ახლა ვხედავთ როგორც 0x20, ასევე 0x68 i2cdetect– ით.
ვიდეოები უფრო მეტს აღწერს რა მოხდა პრობლემების მოგვარების დროს.
ნაბიჯი 5: სენსორის მონაცემების კითხვა
სხვადასხვა მიდგომები
მე გადავწყვიტე სენსორისგან სასარგებლო ინფორმაციის მიღების მრავალი მიდგომა. აქ ისინი არიან, არავითარი თანმიმდევრობით:
- სცადეთ რამდენიმე ძირითადი პროგრამირება
- გადახედეთ ონლაინ დოკუმენტაციას რეგისტრებზე
- გადახედეთ სხვების მაგალითებს და / ან კოდს
რატომ ეს მიდგომები? რატომ არ უნდა მოძებნოთ არსებული ბიბლიოთეკა ან კოდი?
ზოგიერთი იდეის ექსპერიმენტითა და გამოცდილებით, ჩვენ შეგვიძლია უკეთესად მივიღოთ გარკვეული ცოდნა არა მხოლოდ ამ კონკრეტული სენსორის შესახებ, არამედ მივიღოთ გარკვეული ტექნიკა, უნარი და აზროვნების გზები რაიმე ახლის გადასაჭრელად და ისეთზე, რასაც შეიძლება ბევრი დოკუმენტაცია არ ჰქონდეს; რაღაც, რაც შეიძლება ბევრი უცნობი იყოს.
ასევე, მას შემდეგ რაც ჩვენ ვითამაშეთ და გამოვიცადეთ ჩვენი საკუთარი იდეები და მივიღეთ გარკვეული გამჭრიახობა, ჩვენ უკეთეს მდგომარეობაში ვართ შევაფასოთ სხვისი კოდი ან ბიბლიოთეკა.
მაგალითად, github– ში MPU9250– ის ზოგიერთი C ++ კოდის დათვალიერების შემდეგ მივხვდი, რომ ეს მაიძულებდა მე შემეშალა, რაც ჯერ არ მსურს.
ასევე, მას გააჩნია დამატებითი საგნები, როგორიცაა დაკალიბრება; ისევ ის, რაც მე ჯერ არ მაინტერესებს.
შეიძლება ის, რაც მე უნდა გავაკეთო იმისათვის, რომ ვუპასუხო მარტივ კითხვას "რობოტი ბრუნავს დიახ თუ არა" შეიძლება ძალიან მარტივად უპასუხოს მხოლოდ რამდენიმე რეგისტრის წაკითხვით.
რეგისტრები
ამ წერის დროს, როგორც ჩანს, ამ სენსორზე ბევრი არაფერია ხელმისაწვდომი. სინამდვილეში, თუ გადახედავთ სურათებს, რომლებიც მოყვება ამ ინსტრუქციას და ახლოდან დაათვალიერებთ წარწერებს რეალურ ჩიპებზე, ეს მაინტერესებს, არის თუ არა ეს ნოკაუტი. რასაც ვხედავ, არაფერს ვაკავშირებ ინვენსისგან. მიუხედავად ამისა, მე ავირჩიე რეესტრის ინფორმაციის ნახვა იმ მოდელებისთვის, რომლებიც ვიპოვე: MPU-6050 და MPU-9250.
ორივე შემთხვევაში, შემდეგი ერთი და იგივეა ორივესთვის. დამწყებთათვის, ჩვენ ვივარაუდოთ, რომ ეს იგივე იქნება ამ MPU-92/65-ისთვის.
59 -დან 64 -მდე - აქსელერომეტრის გაზომვები
65, 66 - ტემპერატურის გაზომვები 67 -დან 72 -მდე - გიროსკოპის გაზომვები 73 -დან 96 -მდე - გარე სენსორის მონაცემები
შენიშვნა: MPU-6050– ს, როგორც ჩანს, არ აქვს მაგნიტომეტრი, ხოლო MPU-9250– ს (და ჩვენ ვვარაუდობთ, რომ ესეც) აქვს ერთი.
კიდევ რამდენიმე საინტერესო, იმედია სასარგებლო ინფორმაცია მოპოვებული სარეგისტრაციო დოკუმენტიდან:
მაგნიტომეტრის ინფორმაცია:
მაგნიტომეტრი id: 0x48 აღრიცხავს 00 -დან 09: 00 საათამდე WIA 0 1 0 0 1 0 0 0 01 01 INFO INFO7 INFO6 INFO5 INFO4 INFO3 INFO2 INFO1 INFO0 02H ST1 0 0 0 0 0 0 0 DOR DRDY 03H HXL HX7 HX6 HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXX HXH HX15 HX14 HX13 HX12 HX11 HX10 HX9 HX8 05H HYL HY7 HY6 HY5 HY4 HY3 HY2 HY1 HY0 06H HYH HY15 HY14 HY13 HY12 HY11 HY10 HY9 HY8 07H HZL HZ7 HZ6 HZ5 HZ4 HZ3 HZ2 HZ1 HZ0 08H HZH HZ15 HZ14 HZ13 HZ12 HZ11 HZ10 HZ9 HZ8 09H ST2 0 0 0 BITM HOFL 0 0 0 რას ნიშნავს თითოეული რეგისტრი: HXL [7: 0]: X ღერძის გაზომვის მონაცემები ქვედა 8 ბიტიანი HXH [15: 8]: X ღერძი გაზომვის მონაცემები უფრო მაღალი 8 ბიტიანი HYL [7: 0]: Y ღერძი გაზომვის მონაცემები ქვედა 8 ბიტიანი HYH [15: 8]: Y ღერძი გაზომვის მონაცემები უფრო მაღალი 8 ბიტიანი HZL [7: 0]: Z ღერძი გაზომვის მონაცემები ქვედა 8 ბიტიანი HZH [15: 8]: Z ღერძის საზომი მონაცემები უფრო მაღალი 8 ბიტიანი
პროგრამირება
კიდევ ერთი მცირე ინფორმაცია რეესტრის დოკუმენტებიდან არის ის, რომ, როგორც ჩანს, მხოლოდ 100 – მდე რეგისტრი იყო. ასე რომ, ერთი ტაქტიკა შეიძლება იყოს მარტივი პროგრამის დაწერა, რომელიც წვდება მოწყობილობას (0x68) და ცდილობს წაიკითხოს რიგი რეგისტრები თანმიმდევრულად, მათი მნიშვნელობის მიუხედავად, მხოლოდ იმის დანახვა, თუ რა მონაცემების ნახვა შეიძლება.
შემდეგ გააკეთეთ თანმიმდევრული პასი, ერთი და იგივე კოდის გამოყენებით და შეადარეთ მონაცემები ერთი უღელტეხილიდან მეორეზე.
იდეა იმაში მდგომარეობს, რომ ჩვენ შეგვიძლია აღმოვფხვრათ ნებისმიერი რეგისტრი, რომელსაც ეტყობა არ აქვს მონაცემები (ნულოვანი თუ FF?) ან რომელიც აბსოლუტურად არასოდეს იცვლება და ასევე შეგვიძლია გავამახვილოთ ყურადღება მათზე, ვინც იცვლება.
შემდეგ, ერთს ჩვენ ვუყურებთ მხოლოდ მათ, ვინც იცვლება, დაამატეთ საშუალო მაჩვენებელი, რომელიც საშუალოდ ამ რეგისტრის N ბოლო მაჩვენებლებს, რათა ნახოთ არის თუ არა რეალურად გარკვეული სტაბილური მნიშვნელობა ამ რეგისტრისათვის. ეს ვივარაუდოთ, რომ ჩვენ ვინახავთ სენსორს ძალიან უძრავად და იმავე ადგილას.
დაბოლოს, ჩვენ შეგვიძლია ნაზად ვცადოთ ისეთი რამ, რაც სენსორთან არის დაკავშირებული, მაგალითად, მისი დაჭერა (ამაჩქარებელი, გირო), ან აფეთქება მასზე (ტემპერატურა), ან მისი ბრუნვა (წინა ორი პლუს მაგნიტომეტრი) და ვნახოთ რა გავლენას ახდენს ეს მნიშვნელობებზე.
მაქსიმალურად მომწონს wiringPi ბიბლიოთეკის გამოყენება. მას აქვს I2C მხარდაჭერა.
პირველი სირბილი:
/********************************************************************************
* აშენება: gcc first.test.mpu9265.c -o first.test.mpu9265 -lwiringPi * * გასაშვებად: sudo./first.test.mpu9265 * * ეს პროგრამა მხოლოდ MCP23017– დან გამოაქვს (შესაძლებელია) რეგისტრების დიაპაზონი, * და შემდეგ MPU9265– დან (ან ნებისმიერი სხვა MPU– დან იმ 0x68 მისამართზე) * * მე გამოვიყენე იგი დასადასტურებლად, თუკი სენსორიდან კითხვაც კი შემეძლო, რადგან მე უკვე * მქონდა ნდობა MCP23017– ში. *********************************************** *************************** # #მოიცავს #მოიცავს #მოიცავს #მოიცავს #მოიცავს #მთავარს (int argc, char ** argv) {აყენებს ("ვნახოთ რას ამბობს MCP23017 @ 0x20:"); errno = 0; int მოწყობილობაId1 = 0x20; int fd1 = გაყვანილობაPiI2C დაყენება (მოწყობილობა ID1); if (-1 == fd1) {fprintf (stderr, "გაყვანილობის გახსნა ვერ ხერხდება Pi I2C მოწყობილობა: %s / n", strerror (errno)); დაბრუნება 1; } for (int reg = 0; reg <300; reg ++) {fprintf (stderr, "%d", wiringPiI2CReadReg8 (fd1, reg)); fflush (stderr); დაგვიანება (10); } აყენებს (""); აყენებს ("ვნახოთ რას ამბობს MPU9265 @ 0x20:"); errno = 0; int მოწყობილობაId2 = 0x68; int fd2 = გაყვანილობაPiI2C დაყენება (მოწყობილობა ID2); if (-1 == fd2) {fprintf (stderr, "გაყვანილობა ვერ გაიხსნება Pi I2C მოწყობილობა: %s / n", strerror (errno)); დაბრუნება 1; } for (int reg = 0; reg <300; reg ++) {fprintf (stderr, "%d", wiringPiI2CReadReg8 (fd2, reg)); fflush (stderr); დაგვიანება (10); } აყენებს (""); დაბრუნება 0; }
მეორე გარბენი:
/********************************************************************************
* აშენება: gcc second.test.mpu9265.c -o second.test.mpu9265 -lwiringPi * * გასაშვებად: sudo./second.test.mpu9265 * * ეს პროგრამა გასცემს რეგისტრის ნომერს წაკითხულ მნიშვნელობასთან ერთად. * * ამით გამოსადეგია გამომავალი ფაილის მიწოდება (გადამისამართება), შემდეგ კი * შესადარებლად შესაძლებელია რამდენიმე გაშვება. მას შეუძლია გაეცნოს * რომელი რეგისტრი მნიშვნელოვანია და როგორ შეიძლება მოიქცეს მონაცემები. *********************************************** *************************** # #მოიცავს #მოიცავს #მოიცავს #მოიცავს #მოიცავს #მოიცავს #ძირი argv) {int deviceId = -1; თუ (0) {} სხვაგან თუ (! strncmp (argv [1], "0x20", strlen ("0x20"))) {deviceId = 0x20; } else if (! strncmp (argv [1], "0x68", strlen ("0x68"))) {deviceId = 0x68; } else if (! strncmp (argv [1], "0x69", strlen ("0x69"))) {deviceId = 0x69; } აყენებს ("ვნახოთ რას იტყვის MPU9265 @ 0x20:"); ერნრო = 0; int fd = გაყვანილობაPiI2C დაყენება (მოწყობილობა ID); if (-1 == fd) {fprintf (stderr, "wiringPi I2C მოწყობილობის გახსნა შეუძლებელია: %s / n", strerror (errno)); დაბრუნება 1; } for (int reg = 0; reg <300; reg ++) {fprintf (stderr, "%d:%d / n", reg, wiringPiI2CReadReg8 (fd, reg)); fflush (stderr); დაგვიანება (10); } დაბრუნება 0; }
მესამე გარბენი:
/********************************************************************************
* აშენება: gcc third.test.mpu9265.c -o third.test.mpu9265 -lwiringPi * * გასაშვებად: sudo./third.test.mpu9265 * * ეს პროგრამა არის მეორის შედეგი. ის იკითხება მხოლოდ * რეესტრიდან, რომელიც მიუთითებს სხვაობას ერთ და მომდევნო გაშვებას შორის.*********************************************** *************************** # #მოიცავს #მოიცავს #მოიცავს #მოიცავს #მოიცავს #მოიცავს #ძირი argv) {int deviceId = -1; თუ (0) {} სხვაგან თუ (! strncmp (argv [1], "0x68", strlen ("0x68"))) {deviceId = 0x68; } else if (! strncmp (argv [1], "0x69", strlen ("0x69"))) {deviceId = 0x69; } აყენებს ("ვნახოთ რას იტყვის MPU9265 @ 0x20:"); ერნრო = 0; int fd = გაყვანილობაPiI2C დაყენება (მოწყობილობა ID); if (-1 == fd) {fprintf (stderr, "wiringPi I2C მოწყობილობის გახსნა შეუძლებელია: %s / n", strerror (errno)); დაბრუნება 1; } for (int reg = 61; reg <= 73; reg ++) {fprintf (stderr, "%d:%d / n", reg, wiringPiI2CReadReg8 (fd, reg)); fflush (stderr); დაგვიანება (10); } for (int reg = 111; reg <= 112; reg ++) {fprintf (stderr, "%d:%d / n", reg, wiringPiI2CReadReg8 (fd, reg)); fflush (stderr); დაგვიანება (10); } for (int reg = 189; reg <= 201; reg ++) {fprintf (stderr, "%d:%d / n", reg, wiringPiI2CReadReg8 (fd, reg)); fflush (stderr); დაგვიანება (10); } for (int reg = 239; reg <= 240; reg ++) {fprintf (stderr, "%d:%d / n", reg, wiringPiI2CReadReg8 (fd, reg)); fflush (stderr); დაგვიანება (10); } დაბრუნება 0; }
მაშ რა ვისწავლეთ აქამდე? ცხრილის გამოსახულება ფერადი ხაზგასმული უბნებით მიუთითებს, რომ გამომავალი, როგორც ჩანს, ემთხვევა რეგისტრების პირველ ნაკრებებს.
აქამდე მიღებულმა შედეგებმა შეიძლება გამოიწვიოს ახალი კითხვები.
კითხვა: რატომ არის მხოლოდ ერთი სარეგისტრაციო შედეგი "გარე" ჯგუფისათვის?
კითხვა: რა არის ყველა ის უცნობი რეგისტრი "??????"
კითხვა: ვინაიდან პროგრამა არ არის შეწყვეტილი, მოითხოვდა თუ არა მონაცემებს ძალიან ნელა? ძალიან სწრაფად?
კითხვა: შეგვიძლია თუ არა გავლენა მოახდინოს შედეგებზე, როდესაც ჩვენ ვცდილობთ რამეს თავად სენსორთან მუშაობისას?
ნაბიჯი 6: მოდით უფრო მეტად ჩავწვდეთ კითხვას / მონაცემებს
მე ვფიქრობ, რომ შემდეგი ნაბიჯი ყველაფრის წინ არის პროგრამის გაუმჯობესება:
- იყავით მოქნილი მარყუჟის დაგვიანებით (ms)
- იყავით მოქნილი იმაზე, თუ რამდენ კითხვას უნდა მისცეს საშუალო მაჩვენებელი თითო რეგისტრზე
(მე უნდა დავამატო პროგრამა, როგორც ფაილი. როგორც ჩანს, აქ მისი ჩასმის პრობლემა იყო. "4th.test.mpu9265.c")
აქ არის პერსპექტივა, რომელიც იყენებს ბოლო 10 კითხვას საშუალოდ, 10ms მარყუჟზე:
sudo./ მეოთხე. ტესტი.mpu9265 0x68 10 10
61:255 0 255 0 255 0 255 0 0 0: 102 62:204 112 140 164 148 156 188 248 88 228: 167 63:189 188 189 187 189 188 188 188 188 189: 188 64: 60 40 16 96 208 132 116 252 172 36: 112 65: 7 7 7 7 7 7 7 7 7 7: 7 66:224 224 224 240 160 208 224 208 144 96: 195 67: 0 0 0 0 0 0 0 0 0 0: 0 68:215 228 226 228 203 221 239 208 214 187: 216 69: 0 255 0 255 255 0 255 0 0 0: 102 70:242 43 253 239 239 45 206 28 247 207: 174 71: 0 255 255 0 255 255 255 255 255 255: 204 72: 51 199 19 214 11 223 21 236 193 8: 117 73: 0 0 0 0 0 0 0 0 0 0: 0 111: 46 149 91 199 215 46 142 2 233 199: 132 112: 0 0 0 0 0 0 0 0 0 0: 0 189:255 0 255 0 255 0 0 255 0 255: 127 190: 76 36 240 36 100 0 164 164 152 244: 121 191:188 188 188 188 187 188 187 189 187 189: 187 192: 8 48 48 196 96 220 144 0 76 40: 87 193: 7 7 7 7 7 8 7 7 7 7: 7 194:208 224 144 240 176 240 224 208 240 224: 212 195: 0 0 0 0 0 0 0 0 0 0: 0 196:243 184 233 200 225 192 189 242 188 203: 209 197:255 0 0 0 255 0 255 0 0 255: 102 198:223 39 247 43 245 22 255 221 0 6: 130 199: 0 255 255 255 0 255 255 255 255 0: 178 200:231 225 251 1 252 20 211 216 218 16: 164 201: 0 0 0 0 0 0 0 0 0 0: 0 239: 21 138 196 87 26 89 16 245 187 144: 114 240: 0 0 0 0 0 0 0 0 0 0: 0
პირველი, ყველაზე მარცხენა სვეტი არის რეგისტრაციის ნომერი. შემდეგ მოდის ბოლო 10 კითხვა იმ რეგისტრისთვის. დაბოლოს, ბოლო სვეტი არის საშუალო თითოეული სტრიქონისთვის.
როგორც ჩანს, 61, 69, 71, 189, 197 და 199 რეგისტრები ან მხოლოდ ორობითია, ან მზადაა / არ არის მზად, ან არის 16 ბიტიანი მნიშვნელობის მაღალი ბაიტი (უარყოფითი?).
სხვა საინტერესო დაკვირვებები:
- რეგისტრები 65, 193 - ძალიან სტაბილური და იგივე მნიშვნელობა
- რეგისტრი 63, 191 - ძალიან სტაბილური და იგივე მნიშვნელობა
- რეგისტრები 73, 112, 195, 201, 240 - ყველა ნულზე
მოდით დავუკავშიროთ ეს დაკვირვებები ადრინდელი მრავალფუნქციური ფერადი, ხაზგასმული ცხრილის სურათს.
რეგისტრაცია 65 - ტემპერატურა
რეგისტრაცია 193 - ??????
რეგისტრაცია 63 - ამაჩქარებელი
რეგისტრაცია 191 - ??????
რეგისტრაცია 73 - გარე
დარეგისტრირდით 112 და შემდეგ - ??????
ისე, ჩვენ ჯერ კიდევ გვაქვს უცნობი, თუმცა, ჩვენ ვისწავლეთ რაიმე სასარგებლო.
რეგისტრაცია 65 (ტემპერატურა) და რეგისტრი 63 (ამაჩქარებელი) ორივე ძალიან სტაბილური იყო. ეს არის ის, რასაც ველოდით. მე არ შეხებია სენსორს; ის არ მოძრაობს, გარდა სხვა შემთხვევითი ვიბრაციებისა, რადგან რობოტი ისვენებს იმავე მაგიდაზე, როგორც ჩემი კომპიუტერი.
ჩვენ გვაქვს ერთი საინტერესო ტესტი თითოეული ამ ტემპერატურის/აქსელერომეტრის რეგისტრაციისთვის. ამ ტესტისთვის ჩვენ გვჭირდება პროგრამის კიდევ ერთი ვერსია.
ნაბიჯი 7: ჩვენ შეგვიძლია ვიმოქმედოთ ტემპერატურაზე და აჩქარებაზე
წინა ნაბიჯებში ჩვენ შევამცირეთ მინიმუმ ერთი რეგისტრატორი ტემპერატურისთვის და ერთი აჩქარებისათვის.
პროგრამის ამ მომდევნო ვერსიით ("5th.test.mpu9265.c"), ჩვენ რეალურად ვხედავთ, რომ ცვლილებები ხდება ორივე რეგისტრისათვის. გთხოვთ უყუროთ ვიდეოებს.
მეტი თხრა
თუ ჩვენ დავბრუნდებით და გადავხედავთ რეგისტრის ინფორმაციას, ვნახავთ, რომ არსებობს:
- სამი 16 ბიტიანი გამოშვება გიროსკოპისთვის
- სამი 16 ბიტიანი გამოსავალი ამაჩქარებლისთვის
- სამი 16 ბიტიანი გამოსასვლელი მაგნიტომეტრისთვის
- ერთი 16 ბიტიანი გამომავალი ტემპერატურა
თუმცა, ჩვენი მარტივი სატესტო პროგრამებით მიღებული შედეგები იყო ყველა ერთჯერადი 8 ბიტიანი შედეგი. (ერთჯერადი რეგისტრები).
მოდით შევეცადოთ იგივე მიდგომა, მაგრამ ამჯერად 16 ბიტის ნაცვლად 8 -ის ნაცვლად.
ჩვენ ალბათ დაგვჭირდება მსგავსი რამის გაკეთება ქვემოთ. მოდით გამოვიყენოთ ტემპერატურა, როგორც მაგალითი, რადგან ის მხოლოდ ერთი 16 ბიტიანი გამომავალია.
// მიიღეთ ფაილის აღმწერი fd…
int tempRegHi = 65; int tempRegLo = 66; int hiByte = გაყვანილობაPiI2CReadReg8 (fd, tempRegHi); int loByte = გაყვანილობაPiI2CReadReg8 (fd, tempRegLo); int შედეგი = hiByte << 8; // ჩადეთ hi შეკვეთა 8 ბიტიანი 16 ბიტიანი ღირებულების შედეგის ზედა ნაწილში | = loByte; // ახლავე დაამატე lo რიგით 8 ბიტი, გამოიღო სრული 16 ბიტიანი ნომერი // დაბეჭდე ეს რიცხვი ან გამოიყენე ჩვენების ჰორიზონტალური გრაფიკული ფუნქცია წინადან
ჩვენი წინა ნაბიჯებიდან ჩვენ დავინახეთ, რომ 65 -ე რეგისტრი საკმაოდ მყარია, ხოლო 66 -ე ხმაური ძალიან ხმაურიანი. ვინაიდან 65 არის მაღალი რიგის ბაიტი და 66 დაბალი რიგის ბაიტი, ეს აზრი.
წასაკითხად, ჩვენ შეგვიძლია ავიღოთ 65 – ის მონაცემები, როგორც არის, მაგრამ ჩვენ შეგვიძლია საშუალოდ გამოვთვალოთ 66 – ის მნიშვნელობა.
ან ჩვენ შეგვიძლია მხოლოდ საშუალო შედეგი მთლიანი.
შეხედეთ ამ ნაწილის ბოლო ვიდეოს; ის აჩვენებს მთლიანი 16 ბიტიანი ტემპერატურის მნიშვნელობის კითხვას. კოდი არის "sixth.test.mpu9265.c"
ნაბიჯი 8: ამაჩქარებელი და გიროსკოპი
ამ განყოფილების ვიდეოები აჩვენებს ამაჩქარებლიდან და გიროსკოპიდან, საცდელი პროგრამის გამოყენებით "მეშვიდე.ტესტი.მპუ9265.c". ამ კოდს შეუძლია წაიკითხოს 1, 2 ან 3 ზედიზედ ბაი წყვილი (hi და lo ბაიტი) და გარდაქმნის მნიშვნელობებს ერთ 16 ბიტიან მნიშვნელობად. ამრიგად, ჩვენ შეგვიძლია წავიკითხოთ ნებისმიერი ერთი ღერძი, ან შეგვიძლია წავიკითხოთ ორი მათგანი ერთად (და ეს აჯამებს ცვლილებებს), ან ჩვენ შეგვიძლია წავიკითხოთ სამივე (და ის აჯამებს ცვლილებებს).
კიდევ ერთხელ გავიმეორებ, ამ ეტაპისთვის, ამ ინსტრუქციისთვის, მე უბრალოდ ვუპასუხე მარტივ კითხვას: "რობოტი ბრუნავდა/ბრუნავდა?". მე არ ვეძებ რაიმე ზუსტ მნიშვნელობას, მაგალითად, ის ბრუნავს 90 გრადუსით. ეს მოხდება მოგვიანებით, როდესაც ჩვენ დავიწყებთ SLAM– ის გაკეთებას, მაგრამ ეს არ არის საჭირო დაბრკოლებების თავიდან აცილებისა და შემთხვევითი მოძრაობისთვის.
ნაბიჯი 9: (მუშაობა პროგრესში) მაგნიტომეტრი
i2cdetect ინსტრუმენტის გამოყენებისას, MPU9265 ცხრილში გამოჩნდება 0x68:
0 1 2 3 4 5 6 7 8 9 a ბ c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- 68 -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- --
IMU– ს მაგნიტომეტრის ნაწილიდან წასაკითხად დამატებითი ნაბიჯებია საჭირო.
Invesense– დან რეგისტრირებულია PDF დოკუმენტი:
რეგისტრაცია 37 -დან 39 -მდე - I2C SLAVE 0 CONTROL
- რეგისტრაცია 37 - I2C_SLV0_ADDR
- რეგისტრაცია 38 - I2C_SLV0_REG
- რეგისტრაცია 39 - I2C_SLV0_CTRL
გირჩევთ:
ავტონომიური ხანძარსაწინააღმდეგო რობოტი ცეცხლმოკიდებული ცეცხლით: 3 ნაბიჯი
ავტონომიური ხანძარსაწინააღმდეგო რობოტი ცეცხლმოკიდებული ცეცხლით: ყველაზე მძლავრი ავტონომიური ხანძარსაწინააღმდეგო რობოტი GEN2.0HII..ეს არის ჩვენი პირველი პროექტი. მოდით დავიწყოთ. ამ რობოტის კონცეფცია ძალიან მარტივია. გადაარჩინეთ ადამიანის სიცოცხლე ავტომატური დაბალი ღირებულება სწრაფი ცეცხლგამძლე
მინიატურული Arduino ავტონომიური რობოტი (ლენდ როვერი / მანქანა) ეტაპი 1 მოდელი 3: 6 ნაბიჯი
მინიატურული Arduino ავტონომიური რობოტი (ლენდ როვერი / მანქანა) ეტაპი 1 მოდელი 3: მე გადავწყვიტე მინიატურული ლენდ როვერის / მანქანის / ბოტის პროექტის ზომისა და ენერგიის მოხმარების შემცირება
უოლესი ანიმატრონული უცხო არსება: 9 ნაბიჯი (სურათებით)
უოლესი ანიმატრონიკული უცხო არსება: კეთილი იყოს თქვენი მობრძანება! დღეს მე გაჩვენებთ თუ როგორ უნდა ავაშენოთ უოლესი, ანიმატიური უცხოპლანეტელი არსება. დასაწყებად დაგჭირდებათ: x 1 Fur Real Friends dog (ასე: https://www.ebay.com/p/1903566719)x5 MG996R Servos x 1 Pololu Maestro 6 არხიანი Servo Contro
დაბალანსებული რობოტი / 3 ბორბლიანი რობოტი / STEM რობოტი: 8 ნაბიჯი
დაბალანსებული რობოტი / 3 ბორბლიანი რობოტი / STEM რობოტი: ჩვენ შევქმენით კომბინირებული ბალანსირების და 3 ბორბლიანი რობოტი სკოლებში საგანმანათლებლო გამოყენებისთვის და სკოლის შემდგომ საგანმანათლებლო პროგრამებისთვის. რობოტი დაფუძნებულია Arduino Uno– ზე, საბაჟო ფარზე (კონსტრუქციის ყველა დეტალი მოცემულია), Li Ion ბატარეის პაკეტზე (ყველა კონსტრუქცია
[არდუინოს რობოტი] როგორ გავაკეთოთ მოძრავი გადაღების რობოტი - ცერა თითის რობოტი - სერვო ძრავა - წყაროს კოდი: 26 ნაბიჯი (სურათებით)
[არდუინოს რობოტი] როგორ გავაკეთოთ მოძრავი გადაღების რობოტი | ცერა თითის რობოტი | სერვო მოტორი | წყაროს კოდი: Thumbs Robot. გამოყენებული იქნა MG90S სერვო ძრავის პოტენომეტრი. ეს არის ძალიან სახალისო და მარტივი! კოდი ძალიან მარტივია. ეს მხოლოდ 30 სტრიქონია. როგორც ჩანს მოძრაობის გადაღება. გთხოვთ დატოვოთ ნებისმიერი შეკითხვა ან გამოხმაურება! [ინსტრუქცია] წყაროს კოდი https: //github.c