Mündəricat:

Magicbit -dən Özünü Balanslaşdıran Robot: 6 addım
Magicbit -dən Özünü Balanslaşdıran Robot: 6 addım

Video: Magicbit -dən Özünü Balanslaşdıran Robot: 6 addım

Video: Magicbit -dən Özünü Balanslaşdıran Robot: 6 addım
Video: Learn Coding with MagicBit 2024, Noyabr
Anonim

Bu dərslik Magicbit dev board istifadə edərək özünü balanslaşdıran bir robotun necə hazırlanacağını göstərir. ESP32 -ə əsaslanan bu layihədə inkişaf etdirmə lövhəsi olaraq magicbit istifadə edirik. Bu səbəbdən hər hansı bir ESP32 inkişaf lövhəsi bu layihədə istifadə edilə bilər.

Təchizat:

  • sehrli bit
  • İkili H-körpü L298 motor sürücüsü
  • Xətti tənzimləyici (7805)
  • Lipo 7.4V 700mah batareya
  • İnertial Ölçmə Birimi (IMU) (6 dərəcə azadlıq)
  • dişli mühərriklər 3V-6V DC

Addım 1: Hekayə

Hekayə
Hekayə
Hekayə
Hekayə

Hey uşaqlar, bu dərsdə bir az mürəkkəb bir şey öyrənəcəyik. Bu, Arduino IDE ilə Magicbit istifadə edərək özünü balanslaşdıran robot haqqında. Beləliklə, başlayaq.

Əvvəlcə özünü balanslaşdıran robotun nə olduğunu nəzərdən keçirək. Özünü balanslaşdıran robot iki təkərli bir robotdur. Xüsusi xüsusiyyət, robotun heç bir xarici dəstək istifadə etmədən özünü tarazlaşdıra bilməsidir. Güc açıldıqda robot ayağa qalxacaq və sonra salınım hərəkətləri ilə davamlı olaraq balanslaşdırılacaq. Beləliklə, indi özünüzü balanslaşdıran robot haqqında bir az təsəvvürünüz var.

Addım 2: nəzəriyyə və metodologiya

Nəzəriyyə və Metodologiya
Nəzəriyyə və Metodologiya

Robotu tarazlaşdırmaq üçün əvvəlcə robotun şaquli müstəviyə bucağını ölçmək üçün bəzi sensorlardan məlumat alırıq. Bunun üçün MPU6050 istifadə etdik. Sensordan məlumat aldıqdan sonra şaquli müstəviyə meylini hesablayırıq. Robot düz və balanslı vəziyyətdədirsə, əyilmə bucağı sıfırdır. Əks təqdirdə, əyilmə bucağı müsbət və ya mənfi dəyərdir. Robot ön tərəfə əyilmişsə, robot ön istiqamətə keçməlidir. Həmçinin, robot arxa tərəfə əyilmişsə, robot tərs istiqamətə keçməlidir. Bu əyilmə bucağı yüksəkdirsə, cavab sürəti yüksək olmalıdır. Əksinə əyilmə bucağı aşağıdır, sonra reaksiya sürəti aşağı olmalıdır. Bu prosesi idarə etmək üçün PID adlı xüsusi teoremdən istifadə etdik. PID, bir çox prosesi idarə etmək üçün istifadə olunan bir nəzarət sistemidir. PID 3 prosesdən ibarətdir.

  • P- mütənasib
  • I- ayrılmaz
  • D- törəmə

Hər bir sistemin giriş və çıxışı var. Eyni şəkildə bu idarəetmə sisteminin də bəzi girişləri var. Bu idarəetmə sistemində sabit vəziyyətdən sapma. Biz bunu səhv adlandırdıq. Robotumuzda səhv, şaquli müstəvidən meyl açısıdır. Robot balanslıdırsa, əyilmə bucağı sıfırdır. Beləliklə, səhv dəyəri sıfır olacaq. Buna görə PID sisteminin çıxışı sıfırdır. Bu sistemə üç ayrı riyazi proses daxildir.

Birincisi, ədədi mənfəətdən vurulan səhvdir. Bu qazanc ümumiyyətlə Kp adlanır

P = səhv*Kp

İkincisi, zaman sahəsindəki xətanın inteqralını yaratmaq və onu bəzi qazanclardan çoxaltmaqdır. Bu qazanc Ki adlanır

I = İnteqral (səhv)*Ki

Üçüncüsü, vaxt sahəsindəki xətanın törəməsidir və onu bir qədər qazancla vurur. Bu qazanc Kd adlanır

D = (d (səhv)/dt)*kd

Yuxarıdakı əməliyyatları əlavə etdikdən sonra son nəticəmizi alırıq

Çıxış = P+I+D

P hissəsi sayəsində robot, sapma ilə mütənasib olaraq sabit bir mövqe əldə edə bilər. I hissə, vaxt qrafiki ilə səhv sahəsini hesablayır. Beləliklə, robotu sabit mövqeyə hər zaman dəqiq şəkildə çatdırmağa çalışır. D hissəsi, yamacın vaxt və səhv qrafikini ölçür. Səhv artarsa, bu dəyər müsbətdir. Səhv azalırsa, bu dəyər mənfi olur. Bu səbəbdən, robot sabit mövqeyə keçdikdə reaksiya sürəti azalacaq və bu, lazımsız aşınmaları aradan qaldırmağa kömək edəcək. Aşağıdakı linkdən PID nəzəriyyəsi haqqında daha çox məlumat əldə edə bilərsiniz.

www.arrow.com/en/research-and-events/articles/pid-controller-basics-and-tutorial-pid-implementation-in-arduino

PID funksiyasının çıxışı 0-255 aralığında (8 bit PWM qətnaməsi) məhduddur və PWM siqnalı olaraq mühərriklərə veriləcəkdir.

Addım 3: Hardware Setup

Avadanlıq Quraşdırması
Avadanlıq Quraşdırması

İndi bu hardware quraşdırma hissəsidir. Robotun dizaynı sizdən asılıdır. Robotun cəsədini tərtib edərkən, motor oxunda yerləşən şaquli oxun simmetrik olduğunu nəzərə almalısınız. Batareya dəsti aşağıda yerləşir. Beləliklə, robotu balanslaşdırmaq asandır. Dizaynımızda Magicbit lövhəsini bədənə şaquli şəkildə bağlayırıq. İki 12V dişli mühərrikdən istifadə etdik. Ancaq hər hansı bir dişli mühərrikdən istifadə edə bilərsiniz. Bu, robotun ölçülərindən asılıdır.

Dövrə haqqında danışarkən, 7.4V Lipo batareyası ilə işləyir. Magicbit 5V gücə malikdir. Batareya gərginliyini 5V -ə qədər tənzimləmək üçün 7805 tənzimləyicidən istifadə etdik. Magicbit -in sonrakı versiyalarında bu tənzimləyiciyə ehtiyac yoxdur. Çünki 12 V -a qədər gücə malikdir. Motor sürücüsü üçün birbaşa 7.4V veririk.

Aşağıdakı diaqrama uyğun olaraq bütün komponentləri birləşdirin.

Addım 4: Proqram Quraşdırması

Kodda PID çıxışını hesablamaq üçün PID kitabxanasından istifadə etdik.

Yükləmək üçün aşağıdakı linkə daxil olun.

www.arduinolibraries.info/libraries/pid

Bunun son versiyasını yükləyin.

Daha yaxşı sensor oxunuşları əldə etmək üçün DMP kitabxanasından istifadə etdik. DMP rəqəmsal hərəkət prosesi deməkdir. Bu MPU6050 -in daxili xüsusiyyətidir. Bu çipdə inteqrasiya olunmuş hərəkət prosesi vahidi var. Buna görə oxumaq və təhlil etmək lazımdır. Mikro nəzarətçiyə səs -küy olmadan dəqiq çıxışlar yaratdıqdan sonra (bu halda Magicbit (ESP32)). Ancaq bu oxunuşları götürmək və bucağı hesablamaq üçün mikrokontrolör tərəfində bir çox işlər var. Sadəcə olaraq MPU6050 DMP kitabxanasından istifadə etdik. Goint ilə aşağıdakı linkə yükləyin.

github.com/ElectronicCats/mpu6050

Kitabxanaları quraşdırmaq üçün Arduino menyusunda alətlər-> kitabxana daxil et-> add.zip kitabxanasına keçin və yüklədiyiniz kitabxana faylını seçin.

Kodda, təyin olunan nöqtəni düzgün bir şəkildə dəyişdirməlisiniz. PID sabit dəyərləri robotdan robotdan fərqlidir. Bunu tənzimləyərkən əvvəlcə Ki və Kd dəyərlərini sıfıra qoyun və sonra daha yaxşı reaksiya sürəti əldə edənə qədər Kp -ni artırın. Daha çox Kp daha çox atışa səbəb olur. Sonra Kd dəyərini artırın. Həmişə çox az miqdarda artırın. Bu dəyər ümumiyyətlə digər dəyərlərdən aşağıdır. İndi çox yaxşı bir sabitliyə sahib olana qədər Ki -ni artırın.

Doğru COM portunu seçin və lövhəni yazın. kodu yükləyin. İndi DIY robotunuzla oynaya bilərsiniz.

Addım 5: sxemlər

Sxemalar
Sxemalar

Addım 6: Kod

#daxil edin

#include "I2Cdev.h" #include "MPU6050_6Axis_MotionApps20.h" #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE #include "Wire.h" #endif MPU6050 mpu; bool dmpReady = yalan; // DMP init uğurlu uint8_t mpuIntStatus olsaydı doğru təyin edin; // MPU uint8_t devStatus -dan faktiki fasilə statusu baytını saxlayır; // hər cihaz əməliyyatından sonra vəziyyəti qaytarın (0 = uğur,! 0 = səhv) uint16_t packetSize; // gözlənilən DMP paket ölçüsü (standart 42 baytdır) uint16_t fifoCount; // hazırda FIFO -da olan bütün baytların sayı uint8_t fifoBuffer [64]; // FIFO saxlama buferi Quaternion q; // [w, x, y, z] quaternion konteyner VectorFloat çəkisi; // [x, y, z] cazibə vektoru float ypr [3]; // [yaw, pitch, roll] yaw/pitch/roll konteyner və çəkisi vektoru ikiqat originalSetpoint = 172.5; ikiqat setpoint = originalSetpoint; ikiqat hərəkət edənAngleOffset = 0.1; ikiqat giriş, çıxış; int moveState = 0; double Kp = 23; // set P first double Kd = 0.8; // bu dəyər ümumiyyətlə kiçik ikiqat Ki = 300; // daha yaxşı sabitlik üçün bu dəyər yüksək olmalıdır PID pid (& giriş, & çıxış, & setpoint, Kp, Ki, Kd, DIRECT); // pid int motL1 = 26; // motor sürücüsü üçün 4 pin int motL2 = 2; int motR1 = 27; int motR2 = 4; uçucu bool mpuInterrupt = false; // MPU kəsmə pininin yüksək boşluğa getdiyini göstərir dmpDataReady () {mpuInterrupt = true; } void setup () {ledcSetup (0, 20000, 8); // pwm setup ledcSetup (1, 20000, 8); ledcSetup (2, 20000, 8); ledcSetup (3, 20000, 8); ledcAttachPin (motL1, 0); // mühərriklərin pinmode ledcAttachPin (motL2, 1); ledcAttachPin (motR1, 2); ledcAttachPin (motR2, 3); // I2C avtobusuna qoşul (I2Cdev kitabxanası bunu avtomatik etməz) #I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE Wire.begin (); Wire.setClock (400000); // 400kHz I2C saatı. Kompilyasiya çətinlikləri varsa bu sətiri şərh edin #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE Fastwire:: setup (400, true); #endif Serial.println (F ("I2C cihazlarının işə salınması …")); pinMode (14, GİRİŞ); // serial ünsiyyətini başlatmaq // (115200, Çaydanlıq Demosu çıxışı üçün lazım olduğu üçün seçildi, ancaq layihənizdən asılı olaraq həqiqətən sizə bağlıdır) Serial.begin (9600); while (! Serial); // Leonardonun siyahıya alınmasını gözləyin, digərləri dərhal davam edir // cihazı Serial.println (F ("I2C cihazlarının işə salınması …")); mpu.initialize (); // əlaqəni yoxlayın Serial.println (F ("Cihaz əlaqələrini yoxlayır …")); Serial.println (mpu.testConnection ()? F ("MPU6050 bağlantısı uğurlu"): F ("MPU6050 bağlantısı uğursuz oldu")); // DMP Serial.println yükləyin və konfiqurasiya edin (F ("DMP başlatılır …")); devStatus = mpu.dmpInitialize (); // mpu.setXGyroOffset (220) üçün minimum həssaslıq üçün ölçülmüş öz girro ofsetlərinizi təmin edin; mpu.setYGyroOffset (76); mpu.setZGyroOffset (-85); mpu.setZAccelOffset (1788); // Test çipim üçün 1688 zavod varsayılanı // işlədiyinə əmin olun (əgər varsa 0 qaytarır) əgər (devStatus == 0) {// hazırdırsa, DMP -ni yandırın Serial.println (F ("DMP -ni aktivləşdirmək… ")); mpu.setDMPEnabled (doğru); // Arduino kəsilməsinin aşkarlanmasını aktivləşdir Serial.println (F ("Aralıq aşkarlanmasını aktivləşdirmək (Arduino xarici kəsmə 0) …")); attachInterrupt (14, dmpDataReady, RISING); mpuIntStatus = mpu.getIntStatus (); // DMP Hazır bayrağımızı elə qurun ki, əsas loop () funksiyası ondan istifadə etməyinizin yaxşı olduğunu bilsin Serial.println (F ("DMP hazır! İlk kəsilmə gözləyir …")); dmpReady = doğru; // sonrakı müqayisə üçün gözlənilən DMP paket ölçüsünü əldə edin packetSize = mpu.dmpGetFIFOPacketSize (); // PID pid. SetMode qurmaq (OTOMATİK); pid. SetSampleTime (10); pid. SetOutputLimits (-255, 255); } başqa {// HATA! // 1 = ilkin yaddaş yüklənməsi uğursuz oldu // 2 = DMP konfiqurasiya yeniləmələri uğursuz oldu // (pozulacaqsa, adətən kod 1 olacaq) Serial.print (F ("DMP Başlanğıcı uğursuz oldu (kod")); Serial. çap (devStatus); Serial.println (F (")")); }} void loop () {// proqramlaşdırma uğursuz olarsa, (! dmpReady) qayıtsa heç bir şey etməyə çalışmayın; // (! mpuInterrupt && fifoCount <packetSize) {pid. Compute (); // bu zaman aralığı məlumat yükləmək üçün istifadə olunur, buna görə digər hesablamalar üçün istifadə edə biləcəyiniz üçün MotorSpeed (çıxış); } // fasilə bayrağını sıfırlayın və INT_STATUS bayt alın mpuInterrupt = false; mpuIntStatus = mpu.getIntStatus (); // cari FIFO sayını alın fifoCount = mpu.getFIFOCount (); // daşqını yoxlayın (kodumuz çox təsirsiz olmadıqda bu heç vaxt baş verməməlidir) if ((mpuIntStatus & 0x10) || fifoCount == 1024) {// sıfırlayın ki, təmiz şəkildə davam edək mpu.resetFIFO (); Serial.println (F ("FIFO daşması!")); // əks halda, DMP məlumatlarının hazır kəsilməsini yoxlayın (bu tez -tez baş verməlidir)} başqa halda (mpuIntStatus & 0x02) {// düzgün mövcud məlumat uzunluğunu gözləyin, çox qısa bir müddət gözləyin (fifoCount 1 paket mövcuddur // (bu bir fasilə gözləmədən dərhal daha çox oxumağımıza imkan verir) fifoCount -= packetSize; mpu.dmpGetQuaternion (& q, fifoBuffer); mpu.dmpGetGravity (& gravity, & q); mpu.dmpGetYawPitchRoll (ypr, & q, & grif) çap ("ypr / t"); Serial.print (ypr [0] * 180/M_PI); // euler açıları Serial.print ("\ t"); Serial.print (ypr [1] * 180/M_PI); Serial.print ("\ t"); Serial.println (ypr [2] * 180/M_PI); #endif input = ypr [1] * 180/M_PI + 180;}} boş motorSpeed (int PWM) {float L1, L2, R1, R2; əgər (PWM> = 0) {// irəli istiqamət L2 = 0; L1 = abs (PWM); R2 = 0; R1 = abs (PWM); əgər (L1> = 255) { L1 = R1 = 255;}} başqa {// geriyə istiqamət L1 = 0; L2 = abs (PWM); R1 = 0; R2 = abs (PWM); if (L2> = 255) {L2 = R2 = 255; }} // motor sürücüsü ledcWrite (0, L1); ledcWrite (1, L2); ledcWrite (2, R1*0.97); // 0.97 sürətli faktdır və ya, sağ motor sol mühərrikdən daha yüksək sürətə malik olduğundan, motor sürətləri bərabər olana qədər azaldır ledcWrite (3, R2*0.97);

}

Tövsiyə: