Innehållsförteckning:

Self Balancing Robot From Magicbit: 6 steg
Self Balancing Robot From Magicbit: 6 steg

Video: Self Balancing Robot From Magicbit: 6 steg

Video: Self Balancing Robot From Magicbit: 6 steg
Video: Self Balancing Robot from Magicbit 2024, Juli
Anonim

Denna handledning visar hur du skapar en självbalanserande robot med hjälp av Magicbit dev board. Vi använder magicbit som utvecklingskort i detta projekt som är baserat på ESP32. Därför kan alla ESP32 -utvecklingskort användas i detta projekt.

Tillbehör:

  • trollbit
  • Dubbel H-bridge L298 motorförare
  • Linjär regulator (7805)
  • Lipo 7,4V 700mah batteri
  • Tröghetsmätningsenhet (IMU) (6 graders frihet)
  • växelmotorer 3V-6V DC

Steg 1: Berättelse

Berättelse
Berättelse
Berättelse
Berättelse

Hej killar, idag i den här självstudien lär vi oss lite komplexa saker. Det handlar om självbalanserande robot som använder Magicbit med Arduino IDE. Så låt oss börja.

Låt oss först och främst titta på vad som är en självbalanserande robot. Self balancing robot är tvåhjulig robot. Den speciella egenskapen är att roboten kan balansera sig själv utan att använda något externt stöd. När strömmen är på kommer roboten att stå upp och sedan balanseras den kontinuerligt med hjälp av svängningsrörelser. Så nu har du en grov uppfattning om självbalanseringsrobot.

Steg 2: Teori och metodik

Teori och metodik
Teori och metodik

För att balansera roboten får vi först data från någon sensor för att mäta robotvinkeln till vertikalt plan. För detta ändamål använde vi MPU6050. Efter att ha fått data från sensorn beräknar vi lutningen till det vertikala planet. Om roboten är rak och balanserad är lutningsvinkeln noll. Om inte, är lutningsvinkeln positivt eller negativt värde. Om roboten lutar till framsidan, bör roboten gå framåt. Också om roboten lutar till baksidan så bör roboten flytta i omvänd riktning. Om denna lutningsvinkel är hög bör svarshastigheten vara hög. Omvänt är lutningsvinkeln låg och reaktionshastigheten bör vara låg. För att styra denna process använde vi specifikt sats som kallas PID. PID är ett styrsystem som används för att styra många processer. PID står för 3 processer.

  • P- proportionell
  • Jag- integrerad
  • D-derivat

Varje system har input och output. På samma sätt har detta styrsystem också en viss ingång. I detta styrsystem är det avvikelsen från stabilt tillstånd. Vi kallade det som fel. I vår robot är fel lutningsvinkeln från det vertikala planet. Om roboten är balanserad är lutningsvinkeln noll. Så felvärdet blir noll. Därför är PID -systemets utgång noll. Detta system innehåller tre separata matematiska processer.

Det första är multipliceringsfel från numerisk förstärkning. Denna förstärkning brukar kallas Kp

P = fel*Kp

Det andra är att generera integralen av felet i tidsdomänen och multiplicera det från en viss vinst. Denna vinst kallas Ki

I = Integral (fel)*Ki

Den tredje är ett derivat av felet i tidsdomänen och multiplicera det med en viss vinst. Denna vinst kallas Kd

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

Efter att ha lagt till ovanstående operationer får vi vår slutliga produktion

UTGÅNG = P+I+D

På grund av P -delen kan roboten få en stabil position som är proportionell mot avvikelsen. I del beräknar området för fel vs tid graf. Så den försöker få roboten till stabil position alltid exakt. D -delen mäter lutningen i tid vs felgrafik. Om felet ökar är detta värde positivt. Om felet minskar är värdet negativt. På grund av det, när roboten förflyttas till ett stabilt läge, kommer reaktionshastigheten att minska och detta kommer att vara till hjälp för att ta bort onödiga överskott. Du kan lära dig mer om PID -teori från den här länken som visas nedan.

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

Utsignalen från PID-funktionen är begränsad till 0-255-intervallet (8 bitars PWM-upplösning) och den matas till motorer som PWM-signal.

Steg 3: Hårdvaruinstallation

Hardware Setup
Hardware Setup

Nu är detta en hårdvaruinstallationsdel. Robotens design beror på dig. När du konstruerade robotens kropp måste du överväga symmetrisk den kring den vertikala axeln som ligger i motoraxeln. Batteripaketet nedan. Därför är roboten lätt att balansera. I vår design fixar vi Magicbit -kortet vertikalt på kroppen. Vi använde två 12V -växelmotorer. Men du kan använda alla typer av växelmotorer. det beror på dina robotdimensioner.

När vi diskuterar om krets drivs det av 7,4V Lipo -batteri. Magicbit använde 5V för att driva. Därför använde vi 7805 -regulatorn för att reglera batterispänningen till 5V. I senare versioner av Magicbit behövs ingen regulator. Eftersom den driver upp till 12V. Vi levererar direkt 7,4V för motorförare.

Anslut alla komponenter enligt diagrammet nedan.

Steg 4: Programvaruinstallation

I koden använde vi PID -biblioteket för att beräkna PID -utdata.

Gå till följande länk för att ladda ner den.

www.arduinolibraries.info/libraries/pid

Ladda ner den senaste versionen av den.

För att få bättre sensoravläsningar använde vi DMP -biblioteket. DMP står för digital motion process. Detta är en inbyggd funktion i MPU6050. Detta chip har integrerad rörelseprocess. Så det krävs läsning och analys. Efter det genererar ljudlösa exakta utdata till mikrokontrollern (i detta fall Magicbit (ESP32)). Men det finns många arbeten på mikrokontrollersidan för att ta avläsningarna och beräkna vinkeln. Så helt enkelt att vi använde MPU6050 DMP -bibliotek. Ladda ner den genom att gå till följande länk.

github.com/ElectronicCats/mpu6050

För att installera biblioteken, gå till Arduino-menyn till verktygs-> inkludera bibliotek-> add.zip-bibliotek och välj biblioteksfilen som du laddade ner.

I koden måste du ändra börvärdesvinkeln korrekt. PID -konstantvärdena skiljer sig från robot till robot. Så när du ställer in det, ställ först in Ki och Kd -värdena på noll och öka sedan Kp tills du får bättre reaktionshastighet. Fler Kp orsakar fler överskridanden. Öka sedan Kd -värdet. Öka det med alltid i mycket liten mängd. Detta värde är i allmänhet lågt än andra värden. Öka nu Ki tills du har mycket bra stabilitet.

Välj rätt COM -port och skriv in. ladda upp koden. Nu kan du leka med din DIY -robot.

Steg 5: Scheman

Scheman
Scheman

Steg 6: Kod

#omfatta

#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 om DMP init lyckades uint8_t mpuIntStatus; // håller den faktiska avbrottsstatusbyte från MPU uint8_t devStatus; // returstatus efter varje enhetsåtgärd (0 = framgång,! 0 = fel) uint16_t packetSize; // förväntad DMP -paketstorlek (standard är 42 byte) uint16_t fifoCount; // räkna alla byte som för närvarande finns i FIFO uint8_t fifoBuffer [64]; // FIFO lagringsbuffert Quaternion q; // [w, x, y, z] quaternion container VectorFloat gravitation; // [x, y, z] gravitation vektor float ypr [3]; // [yaw, pitch, roll] yaw/pitch/roll container och gravitation vektor dubbel originalSetpoint = 172,5; dubbel börvärde = originalSetpoint; dubbel movingAngleOffset = 0,1; dubbel ingång, utgång; int moveState = 0; dubbel Kp = 23; // set P första dubbel Kd = 0,8; // detta värde i allmänhet liten dubbel Ki = 300; // detta värde bör vara högt för bättre stabilitet PID pid (& input, & output, & setpoint, Kp, Ki, Kd, DIRECT); // pid initiera int motL1 = 26; // 4 stift för motordrift int motL2 = 2; int motR1 = 27; int motR2 = 4; flyktig bool mpuInterrupt = false; // anger om MPU -avbrottsstiftet har gått högt tomrum 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); // pinmode av motorer ledcAttachPin (motL2, 1); ledcAttachPin (motR1, 2); ledcAttachPin (motR2, 3); // gå med i I2C -buss (I2Cdev -biblioteket gör inte detta automatiskt) #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE Wire.begin (); Wire.setClock (400000); // 400kHz I2C klocka. Kommentera den här raden om du har problem med sammanställning #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE Fastwire:: setup (400, true); #endif Serial.println (F ("Initierar I2C -enheter …")); pinMode (14, INPUT); // initiera seriell kommunikation // (115200 valts eftersom det krävs för Teapot Demo -utdata, men det är // verkligen upp till dig beroende på ditt projekt) Serial.begin (9600); medan (! Seriell); // vänta på Leonardo -uppräkning, andra fortsätter omedelbart // initierar enhet Serial.println (F ("Initierar I2C -enheter …")); mpu.initialize (); // verifiera anslutning Serial.println (F ("Testenhetsanslutningar …")); Serial.println (mpu.testConnection ()? F ("MPU6050 -anslutningen lyckades"): F ("MPU6050 -anslutningen misslyckades")); // ladda och konfigurera DMP Serial.println (F ("Initierar DMP …")); devStatus = mpu.dmpInitialize (); // ange dina egna gyroförskjutningar här, skalade för min känslighet mpu.setXGyroOffset (220); mpu.setYGyroOffset (76); mpu.setZGyroOffset (-85); mpu.setZAccelOffset (1788); // 1688 fabriksinställning för mitt testchip // se till att det fungerade (returnerar 0 i så fall) om (devStatus == 0) {// slår på DMP, nu när det är klart Serial.println (F ("Aktiverar DMP … ")); mpu.setDMPEnabled (true); // aktivera Arduino avbrottsdetektering Serial.println (F ("Aktivera avbrottsdetektering (Arduino externt avbrott 0) …")); attachInterrupt (14, dmpDataReady, RISING); mpuIntStatus = mpu.getIntStatus (); // ställ in vår DMP Ready -flagga så att huvudslingan () -funktionen vet att det är okej att använda den Serial.println (F ("DMP ready! Waiting for first interrupt …")); dmpReady = true; // få förväntad DMP -paketstorlek för senare jämförelse packetSize = mpu.dmpGetFIFOPacketSize (); // setup PID pid. SetMode (AUTOMATIC); pid. SetSampleTime (10); pid. SetOutputLimits (-255, 255); } annat {// FEL! // 1 = initial minnesbelastning misslyckades // 2 = DMP -konfigurationsuppdateringar misslyckades // (om den kommer att gå sönder brukar koden vara 1) Serial.print (F ("DMP -initialisering misslyckades (kod")); Serial. print (devStatus); Serial.println (F (")")); }} void loop () {// om programmeringen misslyckades, försök inte göra något om (! dmpReady) returnerar; // vänta på MPU -avbrott eller extra paket (er) medan (! mpuInterrupt && fifoCount <packetSize) {pid. Compute (); // denna tidsperiod används för att ladda data, så att du kan använda detta för andra beräkningar motorSpeed (produktion); } // återställ avbrottsflagga och få INT_STATUS byte mpuInterrupt = false; mpuIntStatus = mpu.getIntStatus (); // få aktuell FIFO -räkning fifoCount = mpu.getFIFOCount (); // kolla efter överflöd (detta ska aldrig hända om inte vår kod är för ineffektiv) om ((mpuIntStatus & 0x10) || fifoCount == 1024) {// återställ så att vi kan fortsätta rent mpu.resetFIFO (); Serial.println (F ("FIFO -överflöd!")); // annars, kolla efter DMP -data redo avbrott (detta ska hända ofta)} annars om (mpuIntStatus & 0x02) {// vänta på korrekt tillgänglig datalängd, bör vara en MYCKET kort väntetid medan (fifoCount 1 -paket tillgängligt // (detta låter oss genast läsa mer utan att vänta på ett avbrott) fifoCount -= packetSize; mpu.dmpGetQuaternion (& q, fifoBuffer); mpu.dmpGetGravity (& gravity, & q); mpu.dmpGetYawPitchRoll (ypr, & q, & gravity); #if LOG_IN. print ("ypr / t"); Serial.print (ypr [0] * 180/M_PI); // euler vinklar 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; om (PWM> = 0) {// riktning framåt L2 = 0; L1 = abs (PWM); R2 = 0; R1 = abs (PWM); om (L1> = 255) { L1 = R1 = 255;}} annat {// bakåtriktning L1 = 0; L2 = abs (PWM); R1 = 0; R2 = abs (PWM); om (L2> = 255) {L2 = R2 = 255; }} // motordriven ledcWrite (0, L1); ledcWrite (1, L2); ledcWrite (2, R1*0,97); // 0,97 är hastighetsfakta eller, eftersom höger motor har hög hastighet än vänster motor, så vi reducerar den tills motorvarvtalet är lika ledcWrite (3, R2*0,97);

}

Rekommenderad: