Obsah:

Samovyvažovací robot od Magicbit: 6 krokov
Samovyvažovací robot od Magicbit: 6 krokov

Video: Samovyvažovací robot od Magicbit: 6 krokov

Video: Samovyvažovací robot od Magicbit: 6 krokov
Video: Arduino DIY MeArm 4DOF Wooden Robotics Robot Arm Kit + SG90 / MG90s Servo Motor 2024, Júl
Anonim

Tento tutoriál ukazuje, ako vytvoriť samovyvažovacieho robota pomocou dosky Magicbit dev. V tomto projekte používame magicbit ako vývojovú dosku, ktorá je založená na ESP32. V tomto projekte je preto možné použiť akúkoľvek vývojovú dosku ESP32.

Zásoby:

  • magický bit
  • Duálny ovládač motora H-bridge L298
  • Lineárny regulátor (7805)
  • Batéria Lipo 7,4 V 700 mAh
  • Inerciálna meracia jednotka (IMU) (6 stupňov voľnosti)
  • prevodové motory 3V-6V DC

Krok 1: Príbeh

Príbeh
Príbeh
Príbeh
Príbeh

Hej, chlapci, dnes sa v tomto návode naučíme trochu zložitú vec. Ide o samovyvažovacieho robota používajúceho Magicbit s Arduino IDE. Začnime teda.

Najprv sa pozrime na to, čo je samovyvažovací robot. Samovyvažovací robot je dvojkolesový robot. Zvláštnosťou je, že sa robot dokáže vyvažovať bez použitia akejkoľvek externej podpory. Keď je napájanie zapnuté, robot sa postaví a potom plynule vyrovnáva pomocou oscilačných pohybov. Takže teraz máte len hrubú predstavu o samovyvažovacom robotovi.

Krok 2: Teória a metodika

Teória a metodika
Teória a metodika

Aby sme vyvážili robota, najskôr získame údaje z nejakého senzora na meranie uhla robota voči zvislej rovine. Na tento účel sme použili MPU6050. Po získaní údajov zo senzora vypočítame náklon do zvislej roviny. Ak je robot v rovnej a vyváženej polohe, uhol sklonu je nulový. Ak nie, uhol sklonu je kladná alebo záporná hodnota. Ak je robot naklonený na prednú stranu, mal by sa robot posunúť dopredu. Aj keď je robot naklonený na opačnú stranu, mal by sa robot pohybovať v opačnom smere. Ak je tento uhol náklonu vysoký, rýchlosť odozvy by mala byť vysoká. Naopak uhol sklonu je nízky, potom by mala byť reakčná rýchlosť nízka. Na ovládanie tohto procesu sme použili špecifickú vetu nazývanú PID. PID je riadiaci systém, ktorý sa používa na riadenie mnohých procesov. PID znamená 3 procesy.

  • P- proporcionálne
  • I- integrál
  • D- derivát

Každý systém má vstup a výstup. Rovnakým spôsobom má tento riadiaci systém tiež určitý vstup. V tomto riadiacom systéme je to odchýlka od stabilného stavu. Nazvali sme to ako chybu. V našom robote je chybou uhol sklonu od zvislej roviny. Ak je robot vyvážený, uhol sklonu je nulový. Chybová hodnota bude teda nulová. Preto je výkon systému PID nulový. Tento systém zahŕňa tri samostatné matematické procesy.

Prvým je násobenie chyby z číselného zisku. Tento zisk sa zvyčajne nazýva Kp

P = chyba*Kp

Druhá generuje integrál chyby v časovej oblasti a vynásobí ju nejakým ziskom. Tento zisk sa nazýva Ki

I = integrál (chyba)*Ki

Tretí je derivát chyby v časovej oblasti a vynásobte ju určitým ziskom. Tento zisk sa nazýva Kd

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

Po pridaní vyššie uvedených operácií získame konečný výstup

VÝSTUP = P+I+D

Vďaka časti P môže robot získať stabilnú polohu, ktorá je úmerná odchýlke. Časť vypočítava graf chyby a času. Snaží sa teda dostať robota do stabilnej polohy vždy presne. D časť meria sklon v čase vs. graf chýb. Ak sa chyba zvyšuje, je táto hodnota kladná. Ak chyba klesá, je táto hodnota záporná. Z tohto dôvodu, keď sa robot pohybuje do stabilnej polohy, reakčná rýchlosť sa zníži, čo pomôže odstrániť zbytočné prekročenia. Viac informácií o teórii PID sa môžete dozvedieť z tohto odkazu uvedeného nižšie.

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

Výstup funkcie PID je obmedzený na rozsah 0-255 (8-bitové rozlíšenie PWM) a bude sa napájať do motorov ako signál PWM.

Krok 3: Nastavenie hardvéru

Nastavenie hardvéru
Nastavenie hardvéru

Teraz je to časť nastavenia hardvéru. Konštrukcia robota závisí od vás. Pri navrhovaní tela robota musíte zvážiť jeho symetriu voči zvislej osi, ktorá leží v osi motora. Batéria umiestnená nižšie. Preto je robot ľahko vyvážený. V našom návrhu pripevňujeme dosku Magicbit vertikálne k telu. Použili sme dva 12V prevodové motory. Môžete však použiť akýkoľvek prevodový motor. to závisí od rozmerov vášho robota.

Keď diskutujeme o obvode, je napájaný 7,4 V batériou Lipo. Na napájanie použil Magicbit 5V. Preto sme použili regulátor 7805 na reguláciu napätia batérie na 5V. V neskorších verziách programu Magicbit tento regulátor nie je potrebný. Pretože napája až 12V. Pre vodiča motora dodávame priamo 7,4 V.

Pripojte všetky komponenty podľa nižšie uvedeného diagramu.

Krok 4: Nastavenie softvéru

V kóde sme na výpočet výstupu PID použili knižnicu PID.

Prejdite na nasledujúci odkaz a stiahnite si ho.

www.arduinolibraries.info/libraries/pid

Stiahnite si jeho najnovšiu verziu.

Na lepšie čítanie senzorov sme použili knižnicu DMP. DMP je skratka pre digitálny pohybový proces. Toto je vstavaná funkcia MPU6050. Tento čip má integrovanú jednotku procesného pohybu. Vyžaduje si to čítanie a analýzu. Potom generuje bezhlučné presné výstupy do mikrokontroléra (v tomto prípade Magicbit (ESP32)). Na strane mikrokontroléra je však veľa práce, ktoré tieto hodnoty odčítajú a vypočítajú uhol. Jednoducho povedané, použili sme DMP knižnicu MPU6050. Stiahnite si ho pomocou nasledujúceho odkazu.

github.com/ElectronicCats/mpu6050

Ak chcete nainštalovať knižnice, v ponuke Arduino prejdite na nástroje-> zahrnúť knižnicu-> knižnicu add.zip a vyberte stiahnutý súbor knižnice.

V kóde musíte správne zmeniť požadovaný bod. Konštantné hodnoty PID sa líšia od robota k robotovi. Pri ladení teda najskôr nastavte hodnoty Ki a Kd na nulu a potom zvyšujte Kp, kým nezískate lepšiu rýchlosť reakcie. Viac Kp príčin pre ďalšie prestrely. Potom zvýšte hodnotu Kd. Zvýšte ho vždy vo veľmi malom množstve. Táto hodnota je spravidla nízka ako ostatné hodnoty. Teraz zvyšujte Ki, kým nebudete mať veľmi dobrú stabilitu.

Vyberte správny port COM a typ dosky. nahrajte kód. Teraz sa môžete hrať so svojim robotom.

Krok 5: Schémy

Schémy
Schémy

Krok 6: Kód

#zahrnúť

#include "I2Cdev.h" #include "MPU6050_6Axis_MotionApps20.h" #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE #include "Wire.h" #endif MPU6050 mpu; bool dmpReady = false; // set true, ak bol DMP init úspešný uint8_t mpuIntStatus; // uchováva bajt skutočného stavu prerušenia z MPU uint8_t devStatus; // návrat stavu po každej operácii zariadenia (0 = úspech,! 0 = chyba) uint16_t packetSize; // očakávaná veľkosť paketu DMP (predvolená hodnota je 42 bajtov) uint16_t fifoCount; // počet všetkých bajtov aktuálne vo FIFO uint8_t fifoBuffer [64]; // Vyrovnávacia pamäť FIFO Quaternion q; // [w, x, y, z] kvartérny kontajner VectorFloat gravitácia; // [x, y, z] gravitačný vektor float ypr [3]; // [vybočenie, rozstup, zvinutie] vybočenie/rozteč/zvinutie kontajnera a vektor gravitácie dvojitý originalSetpoint = 172,5; dvojnásobná požadovaná hodnota = pôvodnáSetpoint; double movingAngleOffset = 0,1; dvojitý vstup, výstup; int moveState = 0; double Kp = 23; // set P first double Kd = 0,8; // this value usually small double Ki = 300; // this value should be high for better stability PID pid (& input, & output, & setpoint, Kp, Ki, Kd, DIRECT); // pid initializate int motL1 = 26; // 4 piny pre pohon motora int motL2 = 2; int motR1 = 27; int motR2 = 4; volatile bool mpuInterrupt = false; // indikuje, či pin prerušenia MPU dosiahol vysokú neplatnosť dmpDataReady () {mpuInterrupt = true; } void setup () {ledcSetup (0, 20000, 8); // nastavenie pwm ledcSetup (1, 20 000, 8); ledcSetup (2, 20 000, 8); ledcSetup (3, 20 000, 8); ledcAttachPin (motL1, 0); // pinmode motorov ledcAttachPin (motL2, 1); ledcAttachPin (motR1, 2); ledcAttachPin (motR2, 3); // pripojenie k zbernici I2C (knižnica I2Cdev to nerobí automaticky) #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE Wire.begin (); Wire.setClock (400000); // 400kHz hodiny I2C. Komentujte tento riadok, ak máte problémy so kompiláciou #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE Fastwire:: setup (400, true); #endif Serial.println (F („Inicializácia zariadení I2C …“)); pinMode (14, VSTUP); // inicializácia sériovej komunikácie // (115200 zvolených, pretože je to potrebné pre demo ukážku Teapot, ale je to // skutočne na vás v závislosti od vášho projektu) Serial.begin (9600); while (! Serial); // počkajte na Leonardov výpočet, ostatné pokračujú ihneď // inicializácia zariadenia Serial.println (F ("Inicializácia zariadení I2C …")); mpu.initialize (); // overenie pripojenia Serial.println (F ("Testovanie pripojení zariadenia …")); Serial.println (mpu.testConnection ()? F ("Pripojenie MPU6050 bolo úspešné"): F ("Pripojenie MPU6050 zlyhalo")); // načítanie a konfigurácia DMP Serial.println (F ("Inicializácia DMP …")); devStatus = mpu.dmpInitialize (); // tu zadajte svoje vlastné gyroskopy, zmenšené na minimálnu citlivosť mpu.setXGyroOffset (220); mpu.setYGyroOffset (76); mpu.setZGyroOffset (-85); mpu.setZAccelOffset (1788); // 1688 výrobný štandard pre môj testovací čip // uistite sa, že funguje (ak je, vráti 0), ak (devStatus == 0) {// zapnite DMP, keď je pripravený Serial.println (F („Povolenie DMP … ")); mpu.setDMPEnabled (true); // povoliť detekciu prerušenia Arduino Serial.println (F ("Povolenie detekcie prerušenia (externé prerušenie Arduino 0) …")); attachInterrupt (14, dmpDataReady, RISING); mpuIntStatus = mpu.getIntStatus (); // nastavte náš príznak DMP Ready, aby funkcia main loop () vedela, že je v poriadku ho použiť Serial.println (F ("DMP pripravené! Čakanie na prvé prerušenie …")); dmpReady = true; // získať očakávanú veľkosť paketu DMP pre neskoršie porovnanie packetSize = mpu.dmpGetFIFOPacketSize (); // nastavenie PID pid. SetMode (AUTOMATIC); pid. SetSampleTime (10); pid. SetOutputLimits (-255, 255); } else {// CHYBA! // 1 = úvodné načítanie pamäte zlyhalo // 2 = Aktualizácie konfigurácie DMP zlyhali // (ak sa má prerušiť, zvyčajne bude kód 1) Serial.print (F ("Inicializácia DMP zlyhala (kód")); Sériové. print (devStatus); Serial.println (F (")")); }} void loop () {// ak programovanie zlyhalo, nesnažte sa nič robiť, ak sa (! dmpReady) vráti; // počkajte na prerušenie MPU alebo na ďalšie balíky dostupné počas výkon); } // reset príznaku prerušenia a získanie INT_STATUS bajtu mpuInterrupt = false; mpuIntStatus = mpu.getIntStatus (); // získať aktuálny počet FIFO fifoCount = mpu.getFIFOCount (); // kontrola pretečenia (to by sa nikdy nemalo stať, pokiaľ náš kód nie je príliš neefektívny) if ((mpuIntStatus & 0x10) || fifoCount == 1024) {// reset, aby sme mohli čisto pokračovať mpu.resetFIFO (); Serial.println (F ("Prepad FIFO!")); // inak skontrolujte prerušenie pripravenosti údajov DMP (to by sa malo často stávať)} else if (mpuIntStatus & 0x02) {// počkajte na správnu dostupnú dĺžku údajov, malo by to byť VEĽMI krátke čakanie (k dispozícii je paket fifoCount 1 // (tento ihneď si prečítajme viac bez čakania na prerušenie) fifoCount -= packetSize; mpu.dmpGetQuaternion (& q, fifoBuffer); mpu.dmpGetGravity (& gravity, & q); mpu.dmpGetYawPitchRoll (ypr, & q, & gravity); #if LOG_INPUT Ser. print ("ypr / t"); Serial.print (ypr [0] * 180/M_PI); // euler angles 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; ak (PWM> = 0) {// smer dopredu L2 = 0; L1 = abs (PWM); R2 = 0; R1 = abs (PWM); ak (L1> = 255) { L1 = R1 = 255;}} else {// smer dozadu L1 = 0; L2 = abs (PWM); R1 = 0; R2 = abs (PWM); ak (L2> = 255) {L2 = R2 = 255; }} // motorový pohon ledcWrite (0, L1); ledcWrite (1, L2); ledcWrite (2, R1*0,97); // 0,97 je skutočnosť rýchlosti alebo pretože pravý motor má vysokú rýchlosť ako ľavý motor, preto ho znižujeme, kým nie sú otáčky motora rovnaké ledcWrite (3, R2*0,97);

}

Odporúča: