Obsah:

Samovyvažovací robot od Magicbit: 6 kroků
Samovyvažovací robot od Magicbit: 6 kroků

Video: Samovyvažovací robot od Magicbit: 6 kroků

Video: Samovyvažovací robot od Magicbit: 6 kroků
Video: Making a robot arm with popsicle sticks - Magicbit 2024, Červenec
Anonim

Tento tutoriál ukazuje, jak vytvořit robota s vlastním vyvažováním pomocí vývojové desky Magicbit. Jako vývojovou desku v tomto projektu, který je založen na ESP32, používáme magicbit. V tomto projektu lze tedy použít jakoukoli vývojovou desku ESP32.

Zásoby:

  • magický bit
  • Duální ovladač motoru H-bridge L298
  • Lineární regulátor (7805)
  • Baterie Lipo 7,4 V 700 mAh
  • Inerciální měřicí jednotka (IMU) (6 stupňů volnosti)
  • převodové motory 3V-6V DC

Krok 1: Příběh

Příběh
Příběh
Příběh
Příběh

Ahoj lidi, dnes se v tomto tutoriálu naučíme trochu složitou věc. Jedná se o robota s vlastním vyvažováním využívající Magicbit s Arduino IDE. Pojďme tedy začít.

Nejprve se podívejme na to, co je samovyvažovací robot. Samovyvažovací robot je dvoukolový robot. Zvláštností je, že se robot dokáže vyvažovat bez použití jakékoli externí podpory. Když je napájení zapnuto, robot se postaví a poté se plynule vyrovnává pomocí oscilačních pohybů. Takže teď máte jen přibližnou představu o samovyvažovacím robotu.

Krok 2: Teorie a metodologie

Teorie a metodologie
Teorie a metodologie

Abychom vyvážili robota, nejprve získáme data z nějakého senzoru pro měření úhlu robota ke svislé rovině. K tomu jsme použili MPU6050. Po získání dat ze senzoru vypočítáme náklon do svislé roviny. Pokud je robot v přímé a vyvážené poloze, pak je úhel náklonu nulový. Pokud ne, pak úhel náklonu je kladná nebo záporná hodnota. Pokud je robot nakloněn na přední stranu, měl by se robot přesunout dopředu. Pokud je robot nakloněn na opačnou stranu, měl by se robot pohybovat ve zpětném směru. Pokud je tento úhel náklonu vysoký, pak by rychlost odezvy měla být vysoká. Naopak úhel náklonu je nízký, pak by rychlost reakce měla být nízká. K řízení tohoto procesu jsme použili konkrétní větu zvanou PID. PID je řídicí systém, který slouží k řízení mnoha procesů. PID znamená 3 procesy.

  • P- proporcionální
  • I- integrál
  • D- derivát

Každý systém má vstup a výstup. Stejným způsobem má tento řídicí systém také nějaký vstup. V tomto řídicím systému je to odchylka od stabilního stavu. Nazvali jsme to jako chybu. V našem robotu je chyba úhel naklonění od svislé roviny. Pokud je robot vyvážený, je úhel náklonu nulový. Chybová hodnota tedy bude nulová. Proto je výstup systému PID nulový. Tento systém zahrnuje tři samostatné matematické procesy.

První z nich je násobení chyby z číselného zisku. Tento zisk se obvykle nazývá Kp

P = chyba*Kp

Druhým je vygenerování integrálu chyby v časové oblasti a její vynásobení nějakým ziskem. Tento zisk se nazývá Ki

I = integrální (chyba)*Ki

Třetí je derivace chyby v časové oblasti a její vynásobení nějakým množstvím zisku. Tento zisk se nazývá Kd

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

Po přidání výše uvedených operací získáme konečný výstup

VÝSTUP = P+I+D

Díky části P může robot získat stabilní polohu, která je úměrná odchylce. Část vypočítává graf chyby a času. Snaží se tedy dostat robota do stabilní polohy vždy přesně. D část měří sklon v čase vs. graf chyby. Pokud se chyba zvyšuje, je tato hodnota kladná. Pokud chyba klesá, je tato hodnota záporná. Z tohoto důvodu, když se robot přesune do stabilní polohy, rychlost reakce se sníží, což pomůže odstranit zbytečné překmity. Můžete se dozvědět více o teorii PID z tohoto odkazu uvedeného níže.

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

Výstup funkce PID je omezen na rozsah 0-255 (rozlišení 8 bitů PWM) a bude se napájet do motorů jako signál PWM.

Krok 3: Nastavení hardwaru

Nastavení hardwaru
Nastavení hardwaru

Nyní je to část nastavení hardwaru. Konstrukce robota závisí na vás. Při navrhování těla robota musíte zvážit jeho symetrii vůči svislé ose, která leží v ose motoru. Sada baterií umístěná níže. Robot se proto snadno vyvažuje. V našem designu připevňujeme desku Magicbit svisle k tělu. Použili jsme dva 12V převodové motory. Můžete však použít jakýkoli druh převodových motorů. to závisí na rozměrech vašeho robota.

Když diskutujeme o obvodu, je napájen 7,4V baterií Lipo. Magicbit pro napájení používal 5V. Proto jsme použili regulátor 7805 k regulaci napětí baterie na 5V. V novějších verzích Magicbit tento regulátor není potřeba. Protože napájí až 12V. Přímo dodáváme 7,4 V pro řidiče motoru.

Připojte všechny součásti podle níže uvedeného schématu.

Krok 4: Nastavení softwaru

V kódu jsme pro výpočet výstupu PID použili knihovnu PID.

Přejděte na následující odkaz a stáhněte si jej.

www.arduinolibraries.info/libraries/pid

Stáhněte si jeho nejnovější verzi.

Pro lepší odečty senzorů jsme použili knihovnu DMP. DMP znamená digitální pohybový proces. Toto je integrovaná funkce MPU6050. Tento čip má integrovanou jednotku procesního pohybu. Chce to tedy číst a analyzovat. Poté, co generuje bezhlučné přesné výstupy do mikrokontroléru (v tomto případě Magicbit (ESP32)). Ale na straně mikrokontroléru je spousta prací, které by odečetly tyto hodnoty a vypočítaly úhel. Jednoduše jsme použili knihovnu MPU6050 DMP. Stáhněte si jej goint na následující odkaz.

github.com/ElectronicCats/mpu6050

Chcete-li nainstalovat knihovny, v nabídce Arduino přejděte na nástroje-> zahrnout knihovnu-> knihovnu add.zip a vyberte soubor knihovny, který jste stáhli.

V kódu musíte správně změnit úhel požadované hodnoty. Konstantní hodnoty PID se u jednotlivých robotů liší. Při ladění tedy nejprve nastavte hodnoty Ki a Kd na nulu a poté zvyšujte Kp, dokud nezískáte lepší reakční rychlost. Více příčin Kp pro další překročení. Poté zvyšte hodnotu Kd. Zvyšte to vždy ve velmi malém množství. Tato hodnota je obecně nízká než jiné hodnoty. Nyní zvyšujte Ki, dokud nebudete mít velmi dobrou stabilitu.

Vyberte správný port COM a typ desky. nahrajte kód. Nyní si můžete hrát se svým robotem pro kutily.

Krok 5: Schémata

Schémata
Schémata

Krok 6: Kód

#zahrnout

#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, pokud byl DMP init úspěšný uint8_t mpuIntStatus; // uchovává skutečný stavový byte přerušení z MPU uint8_t devStatus; // návrat stavu po každé operaci zařízení (0 = úspěch,! 0 = chyba) uint16_t packetSize; // očekávaná velikost paketu DMP (výchozí hodnota je 42 bajtů) uint16_t fifoCount; // počet všech bytů aktuálně ve FIFO uint8_t fifoBuffer [64]; // vyrovnávací paměť FIFO Quaternion q; // [w, x, y, z] čtveřičný kontejner VectorFloat gravitace; // [x, y, z] gravitační vektor float ypr [3]; // [zatáčení, rozteč, výkyv] zatáčení/stoupání/převíjení kontejner a gravitační vektor double originalSetpoint = 172,5; dvojnásobná žádaná hodnota = původní Nastavená hodnota; 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 initialize int motL1 = 26; // 4 piny pro pohon motoru int motL2 = 2; int motR1 = 27; int motR2 = 4; volatile bool mpuInterrupt = false; // indikuje, zda pin přerušení MPU dosáhl vysoké hodnoty neplatné dmpDataReady () {mpuInterrupt = true; } void setup () {ledcSetup (0, 20000, 8); // nastavení pwm ledcSetup (1, 20000, 8); ledcSetup (2, 20 000, 8); ledcSetup (3, 20 000, 8); ledcAttachPin (motL1, 0); // pinmode motorů ledcAttachPin (motL2, 1); ledcAttachPin (motR1, 2); ledcAttachPin (motR2, 3); // připojení ke sběrnici I2C (knihovna I2Cdev to nedělá automaticky) #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE Wire.begin (); Wire.setClock (400000); // 400kHz I2C hodiny. Komentujte tento řádek, pokud máte potíže s kompilací #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE Fastwire:: setup (400, true); #endif Serial.println (F („Inicializace zařízení I2C…“)); pinMode (14, VSTUP); // inicializace sériové komunikace // (115200 zvoleno, protože je vyžadováno pro ukázkový výstup Teapot, ale // je to opravdu na vás v závislosti na vašem projektu) Serial.begin (9600); while (! Serial); // počkejte na výčet Leonarda, ostatní pokračují okamžitě // inicializace zařízení Serial.println (F ("Inicializace zařízení I2C …")); mpu.initialize (); // ověření připojení Serial.println (F ("Testování připojení zařízení …")); Serial.println (mpu.testConnection ()? F ("Připojení MPU6050 úspěšné"): F ("Připojení MPU6050 se nezdařilo")); // načtěte a nakonfigurujte DMP Serial.println (F ("Inicializace DMP …")); devStatus = mpu.dmpInitialize (); // zde zadejte své vlastní gyro offsety, zmenšené na minimální citlivost mpu.setXGyroOffset (220); mpu.setYGyroOffset (76); mpu.setZGyroOffset (-85); mpu.setZAccelOffset (1788); // 1688 tovární nastavení mého testovacího čipu // ujistěte se, že to fungovalo (vrací 0, pokud ano), pokud (devStatus == 0) {// zapněte DMP, když je připraven Serial.println (F ("Povolení DMP … ")); mpu.setDMPEnabled (true); // povolit detekci přerušení Arduino Serial.println (F ("Povolení detekce přerušení (externí přerušení Arduino 0) …")); attachInterrupt (14, dmpDataReady, RISING); mpuIntStatus = mpu.getIntStatus (); // nastavte náš příznak DMP Ready, aby funkce main loop () věděla, že je v pořádku jej použít Serial.println (F ("DMP připraven! Čekání na první přerušení …")); dmpReady = true; // získat očekávanou velikost DMP paketu pro pozdější srovnání packetSize = mpu.dmpGetFIFOPacketSize (); // nastavení PID pid. SetMode (AUTOMATIC); pid. SetSampleTime (10); pid. SetOutputLimits (-255, 255); } else {// CHYBA! // 1 = počáteční načtení paměti se nezdařilo // 2 = Aktualizace konfigurace DMP selhaly // (pokud dojde k přerušení, obvykle bude kód 1) Serial.print (F ("DMP Initialization failed (code")); Serial. print (devStatus); Serial.println (F (")")); }} void loop () {// pokud programování selhalo, nepokoušejte se nic dělat, pokud (! dmpReady) return; // počkejte na přerušení MPU nebo další pakety, které jsou k dispozici, když výstup); } // reset vlajky přerušení a získání INT_STATUS bajtu mpuInterrupt = false; mpuIntStatus = mpu.getIntStatus (); // získat aktuální počet FIFO fifoCount = mpu.getFIFOCount (); // kontrola přetečení (to by se nikdy nemělo stát, pokud náš kód není příliš neefektivní) if ((mpuIntStatus & 0x10) || fifoCount == 1024) {// reset, abychom mohli čistě pokračovat mpu.resetFIFO (); Serial.println (F („Přetečení FIFO!“)); // jinak zkontrolujte přerušení připravenosti dat DMP (to by se mělo často stát)} else if (mpuIntStatus & 0x02) {// čekání na správnou dostupnou délku dat, mělo by být VELMI krátké čekání (paket fifoCount 1 k dispozici // (tento okamžitě si přečteme více bez čekání na přerušení) 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; if (PWM> = 0) {// směr vpřed L2 = 0; L1 = abs (PWM); R2 = 0; R1 = abs (PWM); pokud (L1> = 255) { L1 = R1 = 255;}} else {// zpětný směr L1 = 0; L2 = abs (PWM); R1 = 0; R2 = abs (PWM); if (L2> = 255) {L2 = R2 = 255; }} // motorový pohon ledcWrite (0, L1); ledcWrite (1, L2); ledcWrite (2, R1*0,97); // 0,97 je rychlostní fakt nebo, protože pravý motor má vysokou rychlost než levý motor, tak ho snižujeme, dokud nejsou otáčky motoru stejné ledcWrite (3, R2*0,97);

}

Doporučuje: