Tartalomjegyzék:

Önkiegyenlítő robot a Magicbit -től: 6 lépés
Önkiegyenlítő robot a Magicbit -től: 6 lépés

Videó: Önkiegyenlítő robot a Magicbit -től: 6 lépés

Videó: Önkiegyenlítő robot a Magicbit -től: 6 lépés
Videó: Arduino DIY MeArm 4DOF Wooden Robotics Robot Arm Kit + SG90 / MG90s Servo Motor 2024, Június
Anonim

Ez az oktatóanyag bemutatja, hogyan lehet egyensúlyozó robotot készíteni a Magicbit fejlesztőtáblával. Ebben a projektben, amely az ESP32 -en alapul, fejlesztési táblaként a magicbit -et használjuk. Ezért bármilyen ESP32 fejlesztői kártya használható ebben a projektben.

Kellékek:

  • magicbit
  • Kettős H-híd L298 motor meghajtó
  • Lineáris szabályozó (7805)
  • Lipo 7.4V 700mah akkumulátor
  • Inerciamérő egység (IMU) (6 fok szabadság)
  • hajtómotorok 3V-6V DC

1. lépés: Történet

Sztori
Sztori
Sztori
Sztori

Hé srácok, ma ebben az oktatóanyagban egy kicsit bonyolult dologról fogunk tanulni. Ez arról szól, hogy az önkiegyenlítő robot Magicbit -et használ az Arduino IDE -vel. Tehát kezdjük.

Először is nézzük meg, mi az önkiegyenlítő robot. Az önkiegyenlítő robot kétkerekű robot. A különlegesség az, hogy a robot külső támogatás igénybevétele nélkül képes kiegyensúlyozni önmagát. Amikor a tápfeszültség be van kapcsolva, a robot feláll, majd oszcilláló mozgások segítségével folyamatosan kiegyensúlyozódik. Tehát most csak egy durva elképzelése van az önkiegyensúlyozó robotról.

2. lépés: Elmélet és módszertan

Elmélet és módszertan
Elmélet és módszertan

A robot kiegyensúlyozásához először bizonyos érzékelőktől kapunk adatokat a robot függőleges síkhoz viszonyított szögének mérésére. Ebből a célból az MPU6050 -et használtuk. Miután megkaptuk az adatokat az érzékelőtől, kiszámítjuk a függőleges síkba dőlést. Ha a robot egyenes és kiegyensúlyozott helyzetben van, akkor a dőlésszög nulla. Ha nem, akkor a dőlésszög pozitív vagy negatív érték. Ha a robot elülső oldalra van döntve, akkor a robotnak elöl kell haladnia. Továbbá, ha a robot hátrafelé van döntve, akkor a robotnak fordított irányba kell mozognia. Ha ez a dőlésszög nagy, akkor a válaszsebességnek magasnak kell lennie. Fordítva, a dőlésszög alacsony, a reakciósebességnek alacsonynak kell lennie. Ennek a folyamatnak a szabályozására a PID nevű speciális tételt használtuk. A PID olyan vezérlőrendszer, amely számos folyamatot irányít. A PID három folyamatot jelent.

  • P- arányos
  • I- integrál
  • D- származék

Minden rendszer rendelkezik bemenettel és kimenettel. Ugyanígy ennek a vezérlőrendszernek is van némi bemenete. Ebben a vezérlőrendszerben ez az eltérés a stabil állapottól. Ezt hibának neveztük. Robotunknál a hiba a függőleges síkhoz viszonyított dőlésszög. Ha a robot kiegyensúlyozott, akkor a dőlésszög nulla. Tehát a hiba értéke nulla lesz. Ezért a PID rendszer kimenete nulla. Ez a rendszer három külön matematikai folyamatot tartalmaz.

Az első a szorzás hibája a numerikus erősítésből. Ezt a nyereséget általában Kp -nek nevezik

P = hiba*Kp

A második a hiba integráljának generálása az időtartományban, és megszorozása a nyereség egy részéből. Ezt a nyereséget Ki -nek hívták

I = Integrál (hiba)*Ki

A harmadik az időtartomány hibájának deriváltja, és megszorozzuk valamilyen nyereséggel. Ezt a nyereséget Kd -nek nevezik

D = (d (hiba)/dt)*kd

A fenti műveletek hozzáadása után megkapjuk a végső kimenetet

KIMENET = P+I+D

A P rész miatt a robot stabil pozíciót kaphat, amely arányos az eltéréssel. Az első rész kiszámítja a hiba és az idő grafikon területét. Így megpróbálja mindig pontosan a robotot stabil helyzetbe hozni. A D rész az idő meredekségét és a hibagráfot méri. Ha a hiba növekszik, ez az érték pozitív. Ha a hiba csökken, ez az érték negatív. Emiatt, amikor a robot stabil helyzetbe kerül, a reakciósebesség csökken, és ez segít eltávolítani a felesleges túllépéseket. Az alább látható linkről többet megtudhat a PID elméletről.

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

A PID funkció kimenete 0-255 tartományra van korlátozva (8 bites PWM felbontás), és PWM jelként táplálja a motorokat.

3. lépés: Hardver beállítása

Hardver beállítása
Hardver beállítása

Ez most a hardver beállítási része. A robot tervezése tőled függ. A robot testének tervezésekor figyelembe kell venni a szimmetrikus függőleges tengelyt, amely a motor tengelye. Az akkumulátor az alábbiakban található. Ezért a robot könnyen kiegyensúlyozható. Tervezésünk során a Magicbit táblát függőlegesen rögzítjük a testhez. Két 12 V -os hajtóművet használtunk. De bármilyen hajtóművet használhat. ez a robot méreteitől függ.

Amikor az áramkörről beszélünk, azt 7,4 V -os Lipo akkumulátor táplálja. A Magicbit 5V -ot használt a tápellátáshoz. Ezért 7805 szabályozót használtunk az akkumulátor feszültségének 5 V -ra történő szabályozására. A Magicbit későbbi verzióiban erre a szabályozóra nincs szükség. Mert akár 12V -os tápellátást biztosít. Közvetlenül 7,4 V -ot szállítunk a motor meghajtójához.

Csatlakoztassa az összes alkatrészt az alábbi ábra szerint.

4. lépés: Szoftver beállítása

A kódban a PID könyvtárat használtuk a PID kimenet kiszámításához.

A letöltéshez kattintson a következő linkre.

www.arduinolibraries.info/libraries/pid

Töltse le annak legújabb verzióját.

A jobb érzékelői leolvasáshoz DMP könyvtárat használtunk. A DMP a digitális mozgási folyamatot jelenti. Ez az MPU6050 beépített jellemzője. Ez a chip integrált mozgási folyamategységgel rendelkezik. Tehát olvasni és elemezni kell. Miután zajtalan, pontos kimeneteket generál a mikrokontrollernek (ebben az esetben Magicbit (ESP32)). De sok munka van a mikrokontroller oldalán, hogy vegye le ezeket az értékeket és számítsa ki a szöget. Tehát egyszerűen az MPU6050 DMP könyvtárat használtuk. Töltse le az alábbi linkre kattintva.

github.com/ElectronicCats/mpu6050

A könyvtárak telepítéséhez lépjen az Arduino menüben az eszközök-> tartalmazza a könyvtárat-> add.zip könyvtárba, és válassza ki a letöltött könyvtárfájlt.

A kódban helyesen kell megváltoztatni az alapjel szöget. A PID állandó értékek robotonként eltérőek. Tehát a hangolás során először állítsa a Ki és Kd értékeket nullára, majd növelje a Kp értéket, amíg jobb reakciósebességet nem kap. Több Kp több túllépést okoz. Ezután növelje a Kd értéket. Növelje mindig nagyon kis mennyiségben. Ez az érték általában alacsony, mint a többi érték. Most növelje a Ki értéket, amíg nagyon jó stabilitást nem kap.

Válassza ki a megfelelő COM portot és a kártya típusát. töltse fel a kódot. Most már játszhat a DIY robotjával.

5. lépés: Sémák

Vázlatok
Vázlatok

6. lépés: Kód

#befoglalni

#include "I2Cdev.h" #include "MPU6050_6Axis_MotionApps20.h" #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE #include "Wire.h" #endif MPU6050 mpu; bool dmpReady = hamis; // igazítsa be, ha a DMP init sikeres volt uint8_t mpuIntStatus; // tényleges megszakítási állapot bájtot tartalmaz az MPU -ból uint8_t devStatus; // visszatérési állapot minden eszközművelet után (0 = siker,! 0 = hiba) uint16_t packetSize; // várható DMP csomagméret (alapértelmezett 42 bájt) uint16_t fifoCount; // az összes bájt száma a FIFO -ban uint8_t fifoBuffer [64]; // FIFO tárolópuffer Quaternion q; // [w, x, y, z] kvaternion konténer VectorFloat gravity; // [x, y, z] gravitációs vektor float ypr [3]; // [dőlés, dőlésszög, tekerés] rázkódás/dőlés/tekercstartály és gravitációs vektor dupla eredetiSetpoint = 172,5; dupla alapjel = originalSetpoint; dupla mozgóAngleOffset = 0,1; kettős bemenet, kimenet; int moveState = 0; double Kp = 23; // set P first double Kd = 0,8; // this value általában small double Ki = 300; // ennek az értéknek magasnak kell lennie a jobb stabilitás érdekében PID pid (& input, & output, & setpoint, Kp, Ki, Kd, DIRECT); // pid inicializálása int motL1 = 26; // 4 csap a motorhajtáshoz int motL2 = 2; int motR1 = 27; int motR2 = 4; illékony bool mpuInterrupt = hamis; // azt jelzi, hogy az MPU megszakítási gombja elérte -e void 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); // motorok pinmode ledcAttachPin (motL2, 1); ledcAttachPin (motR1, 2); ledcAttachPin (motR2, 3); // csatlakozzon az I2C buszhoz (az I2Cdev könyvtár ezt nem teszi meg automatikusan) #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE Wire.begin (); Wire.setClock (400000); // 400 kHz -es I2C órajel. Kommentelje ezt a sort, ha fordítási nehézségei vannak #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE Fastwire:: setup (400, igaz); #endif Serial.println (F ("I2C eszközök inicializálása …")); pinMode (14, BEMENET); // soros kommunikáció inicializálása // (115200 azért választva, mert ez szükséges a Teapot Demo kimenethez, de // ez valóban a projekttől függ) Serial.begin (9600); while (! Sorozat); // várja meg a Leonardo felsorolását, mások azonnal folytatják // inicializálja az eszközt Serial.println (F ("I2C eszközök inicializálása …")); mpu.initialize (); // kapcsolat ellenőrzése Serial.println (F ("Eszközkapcsolatok tesztelése …")); Serial.println (mpu.testConnection ()? F ("Az MPU6050 kapcsolat sikeres"): F ("Az MPU6050 kapcsolat sikertelen")); // a DMP betöltése és konfigurálása Serial.println (F ("DMP inicializálása …")); devStatus = mpu.dmpInitialize (); // itt adja meg saját giroszkóp korrekcióit, minimális érzékenységre méretezve mpu.setXGyroOffset (220); mpu.setYGyroOffset (76); mpu.setZGyroOffset (-85); mpu.setZAccelOffset (1788); // 1688 gyári alapértelmezés a tesztcsipemhez // győződjön meg róla, hogy működött (ha 0, akkor visszaadja), ha (devStatus == 0) {// kapcsolja be a DMP -t, most, hogy kész Serial.println (F ("DMP engedélyezése…) ")); mpu.setDMPEnabled (igaz); // engedélyezze az Arduino megszakítás észlelését Serial.println (F ("A megszakítás észlelésének engedélyezése (Arduino külső megszakítás 0)…")); attachInterrupt (14, dmpDataReady, RISING); mpuIntStatus = mpu.getIntStatus (); // állítsuk be a DMP Ready jelzőt, hogy a fő hurok () függvény tudja, hogy rendben van a használata Serial.println (F ("DMP kész! Várakozás az első megszakításra …")); dmpReady = igaz; // a várható DMP csomagméret beszerzése a későbbi összehasonlításhoz packetSize = mpu.dmpGetFIFOPacketSize (); // PID beállítása pid. SetMode (AUTOMATIC); pid. SetSampleTime (10); pid. SetOutputLimits (-255, 255); } else {// HIBA! // 1 = a kezdeti memória betöltése sikertelen // 2 = a DMP konfiguráció frissítése sikertelen // (ha megszakad, a kód általában 1 lesz) Serial.print (F ("A DMP inicializálása sikertelen (kód"))); Soros. print (devStatus); Serial.println (F (")")); }} void loop () {// ha a programozás nem sikerült, ne próbáljon semmit tenni, ha (! dmpReady) visszatér; // várjon az MPU megszakításra vagy további csomagokra, amíg (! mpuInterrupt && fifoCount <packetSize) {pid. Compute (); // ezt az időszakot használják az adatok betöltésére, így ezt más számításokhoz is használhatja motorSpeed (Kimenet); } // állítsa vissza a megszakítás jelzőt, és szerezze be az INT_STATUS bájtot mpuInterrupt = false; mpuIntStatus = mpu.getIntStatus (); // aktuális FIFO szám lekérése fifoCount = mpu.getFIFOCount (); // ellenőrizze a túlcsordulást (ennek soha nem szabad megtörténnie, ha a kódunk nem túl hatékony) if (((mpuIntStatus & 0x10) || fifoCount == 1024) {// reset, hogy tisztán tudjuk folytatni mpu.resetFIFO (); Serial.println (F ("FIFO túlcsordulás!")); // ellenkező esetben ellenőrizze, hogy nincs -e DMP -adatmegszakítás (ennek gyakran kell megtörténnie)} else if (mpuIntStatus & 0x02) {// várjon a megfelelő rendelkezésre álló adathosszra, NAGYON rövid várakozási idő kell, amíg (fifoCount 1 csomag elérhető // (ez azonnal olvassunk tovább anélkül, hogy megszakításra várnánk) 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 szögek 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; ha (PWM> = 0) {// előre L2 = 0; L1 = abs (PWM); R2 = 0; R1 = abs (PWM); ha (L1> = 255) { L1 = R1 = 255;}} else {// visszafelé irány L1 = 0; L2 = abs (PWM); R1 = 0; R2 = abs (PWM); if (L2> = 255) {L2 = R2 = 255; }} // motorhajtás ledcWrite (0, L1); ledcWrite (1, L2); ledcWrite (2, R1*0,97); // 0,97 a sebesség ténye vagy, mivel a jobb motor nagy fordulatszámú, mint a bal motor, ezért csökkentjük, amíg a motor fordulatszáma egyenlő ledcWrite (3, R2*0,97);

}

Ajánlott: