Turinys:
- 1 žingsnis: istorija
- 2 žingsnis: teorija ir metodika
- 3 žingsnis: Aparatūros sąranka
- 4 žingsnis: programinės įrangos sąranka
- 5 žingsnis: schemos
- 6 žingsnis: kodas
Video: Savaime balansuojantis robotas iš „Magicbit“: 6 žingsniai
2024 Autorius: John Day | [email protected]. Paskutinį kartą keistas: 2024-01-30 10:44
Ši pamoka parodo, kaip pasigaminti savaime balansuojantį robotą naudojant „Magicbit dev“plokštę. Šiame projekte, kuris grindžiamas ESP32, mes naudojame „Magicbit“kaip kūrimo lentą. Todėl šiame projekte gali būti naudojama bet kuri ESP32 kūrimo plokštė.
Priedai:
- magija
- Dvigubo H-tilto L298 variklio vairuotojas
- Linijinis reguliatorius (7805)
- „Lipo“7,4 V 700 mAh baterija
- Inercinis matavimo vienetas (IMU) (6 laipsniai laisvės)
- pavarų varikliai 3V-6V DC
1 žingsnis: istorija
Ei, vaikinai, šiandien šioje pamokoje mes sužinosime apie šiek tiek sudėtingą dalyką. Tai yra apie savaime balansuojantį robotą, naudojantį „Magicbit“su „Arduino IDE“. Taigi pradėkime.
Pirmiausia pažvelkime į tai, kas yra savaime balansuojantis robotas. Savaime balansuojantis robotas yra dviejų ratų robotas. Ypatingas bruožas yra tas, kad robotas gali subalansuoti save nenaudodamas jokios išorinės paramos. Įjungus maitinimą, robotas atsistos, o tada nuolat subalansuos, naudodamas svyravimo judesius. Taigi dabar visi turite šiurkščią idėją apie savaime balansuojantį robotą.
2 žingsnis: teorija ir metodika
Norėdami subalansuoti robotą, pirmiausia mes gauname duomenis iš kai kurių jutiklių, skirtų išmatuoti roboto kampą į vertikalią plokštumą. Tuo tikslu mes naudojome MPU6050. Gavę duomenis iš jutiklio, apskaičiuojame pasvirimą į vertikalią plokštumą. Jei robotas yra tiesioje ir subalansuotoje padėtyje, tada pasvirimo kampas yra lygus nuliui. Jei ne, pakreipimo kampas yra teigiama arba neigiama. Jei robotas yra pakreiptas į priekį, tada robotas turi judėti į priekį. Taip pat, jei robotas pasviręs į atbulinę pusę, robotas turėtų judėti atbuline eiga. Jei šis pasvirimo kampas yra didelis, atsako greitis turėtų būti didelis. Priešingai, pasvirimo kampas yra mažas, tada reakcijos greitis turėtų būti mažas. Šiam procesui valdyti naudojome specialią teoremą, vadinamą PID. PID yra valdymo sistema, naudojama daugeliui procesų valdyti. PID reiškia 3 procesus.
- P- proporcingas
- I- vientisas
- D- darinys
Kiekviena sistema turi įvestį ir išvestį. Panašiai ši valdymo sistema taip pat turi tam tikrą įvestį. Šioje valdymo sistemoje tai yra nukrypimas nuo stabilios būsenos. Mes tai pavadinome klaida. Mūsų robote klaida yra pasvirimo kampas nuo vertikalios plokštumos. Jei robotas yra subalansuotas, pasvirimo kampas lygus nuliui. Taigi klaidos vertė bus lygi nuliui. Todėl PID sistemos išėjimas yra lygus nuliui. Ši sistema apima tris atskirus matematinius procesus.
Pirmasis yra daugybos klaida iš skaitinio stiprinimo. Šis pelnas paprastai vadinamas Kp
P = klaida*Kp
Antrasis yra sugeneruoti klaidos integralas laiko srityje ir padauginti jį iš tam tikros naudos. Šis pelnas vadinamas Ki
I = integralas (klaida)*Ki
Trečiasis yra išvestis iš laiko srities klaidos ir padauginama iš tam tikros naudos. Šis pelnas vadinamas Kd
D = (d (klaida)/dt)*kd
Pridėję aukščiau nurodytas operacijas, gauname galutinį rezultatą
IŠVADA = P+I+D
Dėl P dalies robotas gali įgyti stabilią padėtį, kuri yra proporcinga nuokrypiui. I dalis apskaičiuoja klaidų ir laiko grafiko plotą. Taigi jis visada stengiasi, kad robotas būtų stabilioje padėtyje. D dalis matuoja nuolydį laike ir klaidų grafike. Jei klaida didėja, ši vertė yra teigiama. Jei klaida mažėja, ši vertė yra neigiama. Dėl to, kai robotas perkeliamas į stabilią padėtį, reakcijos greitis sumažės ir tai padės pašalinti nereikalingus viršijimus. Daugiau apie PID teoriją galite sužinoti iš šios nuorodos, parodyta žemiau.
www.arrow.com/en/research-and-events/articles/pid-controller-basics-and-tutorial-pid-implementation-in-arduino
PID funkcijos išvestis ribojama iki 0–255 diapazono (8 bitų PWM skiriamoji geba) ir varikliai bus perduodami kaip PWM signalas.
3 žingsnis: Aparatūros sąranka
Dabar tai aparatinės įrangos sąrankos dalis. Roboto dizainas priklauso nuo jūsų. Kurdami roboto kūną, turite atsižvelgti į jo simetriškumą vertikaliai ašiai, esančiai variklio ašyje. Akumuliatorius yra žemiau. Todėl robotą lengva subalansuoti. Pagal savo dizainą „Magicbit“plokštę pritvirtiname vertikaliai prie korpuso. Mes naudojome du 12 V pavarų variklius. Bet jūs galite naudoti bet kokius pavarų variklius. tai priklauso nuo jūsų roboto matmenų.
Kai diskutuojame apie grandinę, ji maitinama 7,4 V „Lipo“baterija. Maitinimui „Magicbit“naudojo 5 V įtampą. Todėl mes naudojome 7805 reguliatorių akumuliatoriaus įtampai reguliuoti iki 5 V. Vėlesnėse „Magicbit“versijose šio reguliatoriaus nereikia. Nes maitina iki 12V. Mes tiesiogiai tiekiame 7,4 V variklio vairuotojui.
Prijunkite visus komponentus pagal žemiau pateiktą schemą.
4 žingsnis: programinės įrangos sąranka
Kode mes naudojome PID biblioteką PID išėjimui apskaičiuoti.
Eikite į šią nuorodą, kad ją atsisiųstumėte.
www.arduinolibraries.info/libraries/pid
Atsisiųskite naujausią jo versiją.
Norėdami gauti geresnius jutiklių rodmenis, naudojome DMP biblioteką. DMP reiškia skaitmeninio judesio procesą. Tai yra integruota MPU6050 funkcija. Ši mikroschema turi integruotą judesio proceso bloką. Taigi reikia skaityti ir analizuoti. Po to jis sukuria tikslius triukšmo išėjimus į mikrovaldiklį (šiuo atveju „Magicbit“(ESP32)). Tačiau mikrovaldiklio pusėje yra daug darbų, kad būtų galima išmatuoti šiuos rodmenis ir apskaičiuoti kampą. Taigi paprasčiausiai naudojome MPU6050 DMP biblioteką. Atsisiųskite jį apsilankę šioje nuorodoje.
github.com/ElectronicCats/mpu6050
Norėdami įdiegti bibliotekas, „Arduino“meniu eikite į įrankiai-> įtraukti biblioteką-> add.zip biblioteką ir pasirinkite atsisiųstą bibliotekos failą.
Kode turite teisingai pakeisti nustatytos vertės kampą. PID pastovios vertės skirtinguose robotuose skiriasi. Taigi, derindami tai, pirmiausia nustatykite Ki ir Kd reikšmes nuliui, tada padidinkite Kp, kol pasieksite geresnį reakcijos greitį. Daugiau Kp sukelia daugiau viršijimų. Tada padidinkite Kd vertę. Visada padidinkite jį labai mažais kiekiais. Ši vertė paprastai yra mažesnė nei kitos vertės. Dabar padidinkite Ki, kol gausite labai gerą stabilumą.
Pasirinkite tinkamą COM prievadą ir plokštės tipą. įkelti kodą. Dabar galite žaisti su savo „pasidaryk pats“robotu.
5 žingsnis: schemos
6 žingsnis: kodas
#įtraukti
#include "I2Cdev.h" #include "MPU6050_6Axis_MotionApps20.h" #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE #include "Wire.h" #endif MPU6050 mpu; bool dmpReady = klaidinga; // nustatyti tiesa, jei DMP init buvo sėkmingas uint8_t mpuIntStatus; // turi faktinį pertraukimo būsenos baitą iš MPU uint8_t devStatus; // grąžinti būseną po kiekvienos įrenginio operacijos (0 = sėkmė,! 0 = klaida) uint16_t packetSize; // numatomas DMP paketo dydis (numatytasis yra 42 baitai) uint16_t fifoCount; // visų baitų skaičius šiuo metu FIFO uint8_t fifoBuffer [64]; // FIFO saugojimo buferis Quaternion q; // [w, x, y, z] kvaterniono konteineris VectorFloat gravity; // [x, y, z] gravitacijos vektoriaus plūdė ypr [3]; // [posūkis, žingsnis, ridenimasis] posūkis/žingsnis/ritininis indas ir gravitacijos vektorius dvigubas originalusSetpoint = 172,5; dvigubas nustatymas = originalSetpoint; dvigubas judėjimasAngleOffset = 0,1; dvigubas įėjimas, išėjimas; int moveState = 0; dvigubas Kp = 23; // nustatyti P pirmą dvigubą Kd = 0,8; // ši vertė paprastai maža dviguba Ki = 300; // ši vertė turėtų būti didelė, kad būtų užtikrintas geresnis stabilumas, DIRECT); // pid inicializuoti int motL1 = 26; // 4 kaiščiai variklio pavarai int motL2 = 2; int motR1 = 27; int motR2 = 4; nepastovus bool mpuInterrupt = false; // nurodo, ar MPU pertraukimo smeigtukas tapo labai tuščias 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); // variklių pinmode ledcAttachPin (motL2, 1); ledcAttachPin (motR1, 2); ledcAttachPin (motR2, 3); // prisijungti prie I2C magistralės („I2Cdev“biblioteka to nedaro automatiškai) #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE Wire.begin (); Wire.setClock (400000); // 400 kHz I2C laikrodis. Komentuokite šią eilutę, jei turite kompiliavimo sunkumų #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE Fastwire:: setup (400, tiesa); #endif Serial.println (F ("I2C įrenginių inicijavimas …")); pinMode (14, Įvestis); // inicijuoti nuoseklųjį ryšį // (115200 pasirinktas, nes jis reikalingas arbatinuko demonstracinei išvestims, bet tai // tikrai priklauso nuo jūsų, priklausomai nuo jūsų projekto) Serial.begin (9600); while (! Serial); // laukti Leonardo išvardijimo, kiti iškart tęsti // inicijuoti įrenginį Serial.println (F ("I2C įrenginių inicijavimas …")); mpu.initialize (); // patikrinti ryšį Serial.println (F ("Įrenginio jungčių tikrinimas …")); Serial.println (mpu.testConnection ()? F ("MPU6050 ryšys sėkmingas"): F ("MPU6050 ryšys nepavyko")); // įkelti ir sukonfigūruoti DMP Serial.println (F ("DMP inicijavimas …")); devStatus = mpu.dmpInitialize (); // čia pateikite savo giroskopo poslinkius, pritaikytus mažiausiam jautrumui mpu.setXGyroOffset (220); mpu.setYGyroOffset (76); mpu.setZGyroOffset (-85); mpu.setZAccelOffset (1788); // mano bandomojo lusto gamykla pagal numatytuosius nustatymus 1688 // įsitikinkite, kad ji veikė (grąžina 0, jei taip), jei (devStatus == 0) {// įjunkite DMP dabar, kai jis paruoštas Serial.println (F ("Įjungiamas DMP … ")); mpu.setDMPEnabled (tiesa); // įgalinti „Arduino“pertraukimo aptikimą Serial.println (F („Įgalinti pertraukimo aptikimą („ Arduino “išorinis pertraukimas 0)…“)); attachInterrupt (14, dmpDataReady, RISING); mpuIntStatus = mpu.getIntStatus (); // nustatykite mūsų DMP Ready vėliavą, kad pagrindinė ciklo () funkcija žinotų, jog ją naudoti yra gerai Serial.println (F ("DMP paruošta! Laukiama pirmo pertraukimo …")); dmpReady = tiesa; // gauti laukiamą DMP paketo dydį vėlesniam palyginimui packetSize = mpu.dmpGetFIFOPacketSize (); // sąranka PID pid. SetMode (AUTOMATIC); pid. SetSampleTime (10); pid. SetOutputLimits (-255, 255); } else {// KLAIDA! // 1 = nepavyko įkelti pradinės atminties // 2 = nepavyko atnaujinti DMP konfigūracijos // (jei ji nutrūks, dažniausiai kodas bus 1) Serial.print (F ("DMP inicijavimas nepavyko (kodas))); Serijinis. spausdinti (devStatus); Serial.println (F (")")); }} void loop () {// jei programavimas nepavyko, nebandykite nieko daryti, jei (! dmpReady) grįžta; // laukti MPU pertraukimo arba papildomo paketo (-ų), kol (! mpuInterrupt && fifoCount <packetSize) {pid. Compute (); // šis laikotarpis yra naudojamas duomenims įkelti, todėl galite tai naudoti kitiems skaičiavimams motorSpeed (išvestis); } // iš naujo nustatyti pertraukimo vėliavą ir gauti INT_STATUS baitą mpuInterrupt = false; mpuIntStatus = mpu.getIntStatus (); // gauti dabartinį FIFO skaičių fifoCount = mpu.getFIFOCount (); // patikrinkite, ar nėra perpildymo (to niekada neturėtų nutikti, nebent mūsų kodas yra per neefektyvus) if (((mpuIntStatus & 0x10) || fifoCount == 1024) {// atstatyti, kad galėtume tęsti švariai mpu.resetFIFO (); Serial.println (F ("FIFO perpildymas!")); // kitaip, patikrinkite, ar DMP duomenų paruošimo pertraukimas (tai turėtų nutikti dažnai)} else if (mpuIntStatus & 0x02) {// laukite teisingo turimo duomenų ilgio, turėtų būti LABAI trumpas laukimas, kol (fifoCount 1 paketas prieinamas // (tai iš karto skaitykime daugiau, nelaukdami pertraukos) fifoCount -= packetSize; mpu.dmpGetQuaternion (& q, fifoBuffer); mpu.dmpGetGravity (& gravity, & q); mpu.dmpGetYawPitchRoll (ypr, & q, & gravity); #if Lial. print ("ypr / t"); Serial.print (ypr [0] * 180/M_PI); // euler kampai 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;}} void motorSpeed (int PWM) {float L1, L2, R1, R2; jei (PWM> = 0) {// kryptis į priekį L2 = 0; L1 = abs (PWM); R2 = 0; R1 = abs (PWM); jei (L1> = 255) { L1 = R1 = 255;}} else {// atgal kryptis L1 = 0; L2 = abs (PWM); R1 = 0; R2 = abs (PWM); jei (L2> = 255) {L2 = R2 = 255; }} // variklio pavara ledcWrite (0, L1); ledcWrite (1, L2); ledcWrite (2, R1*0,97); // 0,97 yra greičio faktas arba dėl to, kad dešiniojo variklio greitis yra didesnis nei kairiojo variklio, todėl jį sumažiname, kol variklio greitis lygus ledcWrite (3, R2*0,97);
}
Rekomenduojamas:
Savaime balansuojantis robotas - PID valdymo algoritmas: 3 žingsniai
Savaiminio balansavimo robotas - PID valdymo algoritmas: Šis projektas buvo sukurtas, nes man buvo įdomu sužinoti daugiau apie valdymo algoritmus ir kaip efektyviai įgyvendinti funkcines PID kilpas. Projektas dar tik kuriamas, nes dar reikia pridėti „Bluetooth“modulį, kuris
Balansavimo robotas / 3 ratų robotas / STEM robotas: 8 žingsniai
Balansavimo robotas / 3 ratų robotas / STEM robotas: Mes sukūrėme kombinuotą balansavimo ir 3 ratų robotą, skirtą naudoti mokyklose ir po pamokų. Robotas sukurtas naudojant „Arduino Uno“, pasirinktinį skydą (pateikiama visa konstrukcijos informacija), „Li Ion“akumuliatorių paketą (visa tai atitinka
Savaime balansuojantis robotas naudojant PID algoritmą (STM MC): 9 žingsniai
Savarankiškai subalansuojantis robotas, naudojant PID algoritmą (STM MC): Pastaruoju metu daug nuveikta atliekant savarankišką objektų balansavimą. Savarankiško balansavimo koncepcija prasidėjo nuo apverstos švytuoklės balansavimo. Ši koncepcija išplėtė ir orlaivių dizainą. Šiame projekte mes sukūrėme nedidelį mod
Savaime balansuojantis robotas: 6 žingsniai (su nuotraukomis)
Savaime subalansuojantis robotas: šioje instrukcijoje mes parodysime, kaip sukurti savaime balansuojantį robotą, kurį sukūrėme kaip mokyklos projektą. Jis pagrįstas kai kuriais kitais robotais, pvz., „NBot“ir kitu „Instructable“. Robotą galima valdyti iš „Android“išmaniojo telefono
Savaime balansuojantis Robo-riteris: 7 žingsniai (su paveikslėliais)
Savaime balansuojantis „Robo-riteris“: vaizdo žaidimai ir stalo žaidimai yra puikus būdas praleisti laiką su draugais ir šeima. Kartais norisi leisti laiką neprisijungus ir atiduoti visą elektroniką, o kitą kartą pasineri į virtualų sporto, arkados ar kovos žaidimų pasaulį