Indholdsfortegnelse:

Selvbalancerende robot fra Magicbit: 6 trin
Selvbalancerende robot fra Magicbit: 6 trin

Video: Selvbalancerende robot fra Magicbit: 6 trin

Video: Selvbalancerende robot fra Magicbit: 6 trin
Video: Makeblock Untimate Robot Kit Part 1 : Step by Step Assembly Robot of Aram Tank 2024, Juli
Anonim

Denne vejledning viser, hvordan man laver en selvbalancerende robot ved hjælp af Magicbit dev board. Vi bruger magicbit som udviklingstavle i dette projekt, der er baseret på ESP32. Derfor kan enhver ESP32 udviklingsplade bruges i dette projekt.

Tilbehør:

  • magicbit
  • Dobbelt H-bridge L298 motor driver
  • Lineær regulator (7805)
  • Lipo 7,4V 700mah batteri
  • Inertial Measurement Unit (IMU) (6 graders frihed)
  • gearmotorer 3V-6V DC

Trin 1: Historie

Historie
Historie
Historie
Historie

Hej fyre, i dag i denne vejledning lærer vi om lidt komplekse ting. Det handler om selvbalancerende robot ved hjælp af Magicbit med Arduino IDE. Så lad os komme i gang.

Lad os først og fremmest se på, hvad der er en selvbalancerende robot. Selvbalancerende robot er tohjulet robot. Den særlige funktion er, at robotten kan balancere sig selv uden at bruge ekstern understøttelse. Når strømmen er på, vil robotten stå op og derefter balancere kontinuerligt ved hjælp af svingningsbevægelser. Så nu har du bare en grov ide om selvbalancerende robot.

Trin 2: Teori og metode

Teori og metode
Teori og metode

For at balancere robotten får vi først data fra en sensor til at måle robotvinklen til det lodrette plan. Til det formål brugte vi MPU6050. Efter at have fået data fra sensoren beregner vi tilt til lodret plan. Hvis robotten er i lige og afbalanceret position, er vippevinklen nul. Hvis ikke, er hældningsvinklen positiv eller negativ værdi. Hvis robotten vippes til forsiden, skal robotten bevæge sig fremad. Hvis robotten også vippes til bagsiden, skal robotten bevæge sig i baglæns retning. Hvis denne hældningsvinkel er høj, skal svarhastigheden være høj. Omvendt er vippevinklen lav, og reaktionshastigheden skal være lav. For at kontrollere denne proces brugte vi specifik sætning kaldet PID. PID er et kontrolsystem, der bruges til at styre mange processer. PID står for 3 processer.

  • P- proportional
  • I- integreret
  • D-derivat

Hvert system har input og output. På samme måde har dette kontrolsystem også noget input. I dette kontrolsystem er det afvigelsen fra stabil tilstand. Vi kaldte det som en fejl. I vores robot er fejl hældningsvinklen fra det lodrette plan. Hvis robotten er afbalanceret, er hældningsvinklen nul. Så fejlværdien vil være nul. Derfor er output fra PID -systemet nul. Dette system omfatter tre separate matematiske processer.

Den første er multiplikationsfejl fra numerisk forstærkning. Denne gevinst kaldes normalt som Kp

P = fejl*Kp

Den anden er at generere integralet af fejlen i tidsdomænet og multiplicere det fra nogle af gevinster. Denne gevinst kaldes som Ki

I = Integral (fejl)*Ki

Den tredje er afledt af fejlen i tidsdomænet og gang den med en vis gevinst. Denne gevinst kaldes som Kd

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

Efter at have tilføjet ovenstående operationer får vi vores endelige output

UDGANG = P+I+D

På grund af P -delen kan robotten få en stabil position, der er proportional med afvigelsen. I del beregner område med fejl vs tid graf. Så det forsøger altid at få robotten til en stabil position præcist. D -del måler hældningen i tid vs fejlgraf. Hvis fejlen stiger, er denne værdi positiv. Hvis fejlen falder, er denne værdi negativ. På grund af det, når robotten bevæger sig til en stabil position, reduceres reaktionshastigheden, og det vil være nyttigt at fjerne unødvendige overskridelser. Du kan lære mere om PID -teori fra dette link vist nedenfor.

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

Output fra PID-funktionen er begrænset til 0-255 område (8 bit PWM-opløsning), og det vil føde til motorer som PWM-signal.

Trin 3: Hardwareopsætning

Hardwareopsætning
Hardwareopsætning

Nu er dette hardwareopsætningsdel. Robotens design afhænger af dig. Når du designede robottens krop, skal du overveje at symmetriske den omkring den lodrette akse, der ligger i motoraksen. Batteripakken placeret herunder. Derfor er robotten let at balancere. I vores design fastgør vi Magicbit board lodret til kroppen. Vi brugte to 12V gearmotorer. Men du kan bruge enhver form for gearmotorer. det afhænger af dine robotdimensioner.

Når vi diskuterer om kredsløb, drives det af et 7,4V Lipo -batteri. Magicbit brugte 5V til strømforsyning. Derfor brugte vi 7805 regulator til at regulere batterispændingen til 5V. I senere versioner af Magicbit er denne regulator ikke nødvendig. Fordi den driver op til 12V. Vi leverer direkte 7,4V til motorfører.

Tilslut alle komponenter i henhold til nedenstående diagram.

Trin 4: Softwareopsætning

I koden brugte vi PID -bibliotek til beregning af PID -output.

Gå til følgende link for at downloade det.

www.arduinolibraries.info/libraries/pid

Download den nyeste version af den.

For at få bedre sensoraflæsninger brugte vi DMP -bibliotek. DMP står for digital motion process. Dette er en indbygget funktion i MPU6050. Denne chip har integreret bevægelsesprocesenhed. Så det kræver læsning og analyse. Efter det genererer støjsvage nøjagtige output til mikrokontrolleren (i dette tilfælde Magicbit (ESP32)). Men der er mange værker på mikrokontrollersiden for at tage disse målinger og beregne vinklen. Så simpelthen at vi brugte MPU6050 DMP -bibliotek. Download det ved at gå til følgende link.

github.com/ElectronicCats/mpu6050

For at installere bibliotekerne skal du i Arduino-menuen gå til værktøjer-> inkludere bibliotek-> add.zip-bibliotek og vælge den biblioteksfil, som du downloadede.

I koden skal du ændre setpunktvinklen korrekt. PID -konstante værdier er forskellige fra robot til robot. Så ved at indstille det, skal du først indstille Ki og Kd værdier til nul og derefter øge Kp, indtil du får bedre reaktionshastighed. Flere Kp forårsager flere overskridelser. Forøg derefter Kd -værdien. Forøg det med altid i meget lille mængde. Denne værdi er generelt lav end andre værdier. Forøg nu Ki, indtil du har en meget god stabilitet.

Vælg den korrekte COM -port, og skriv typen. uploade koden. Nu kan du lege med din DIY -robot.

Trin 5: Skemaer

Skemaer
Skemaer

Trin 6: Kode

#omfatte

#include "I2Cdev.h" #include "MPU6050_6Axis_MotionApps20.h" #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE #include "Wire.h" #endif MPU6050 mpu; bool dmpReady = falsk; // sæt sand, hvis DMP init var vellykket uint8_t mpuIntStatus; // holder den faktiske afbrydelsesstatusbyte fra MPU uint8_t devStatus; // returstatus efter hver enhedsoperation (0 = succes,! 0 = fejl) uint16_t packetSize; // forventet DMP -pakkestørrelse (standard er 42 bytes) uint16_t fifoCount; // tæller alle bytes i øjeblikket i FIFO uint8_t fifoBuffer [64]; // FIFO opbevaringsbuffer Quaternion q; // [w, x, y, z] quaternion container VectorFloat tyngdekraft; // [x, y, z] tyngdekraftsvektor float ypr [3]; // [yaw, pitch, roll] yaw/pitch/roll container og tyngdekraftvektor dobbelt originalSetpoint = 172,5; dobbelt setpunkt = originalSetpoint; dobbelt movingAngleOffset = 0,1; dobbelt input, output; int moveState = 0; dobbelt Kp = 23; // sæt P først dobbelt Kd = 0,8; // denne værdi generelt lille dobbelt Ki = 300; // denne værdi skal være høj for bedre stabilitet PID pid (& input, & output, & setpoint, Kp, Ki, Kd, DIRECT); // pid initialiser int motL1 = 26; // 4 ben til motordrev int motL2 = 2; int motR1 = 27; int motR2 = 4; flygtig bool mpuInterrupt = falsk; // angiver, om MPU -afbrydelsesnål er gået højt 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 af motorer ledcAttachPin (motL2, 1); ledcAttachPin (motR1, 2); ledcAttachPin (motR2, 3); // slutte sig til I2C -bus (I2Cdev -bibliotek gør dette ikke automatisk) #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE Wire.begin (); Wire.setClock (400000); // 400kHz I2C ur. Kommenter denne linje, hvis du har problemer med kompilering #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE Fastwire:: setup (400, true); #endif Serial.println (F ("Initialiserer I2C -enheder …")); pinMode (14, INPUT); // initialiser seriel kommunikation // (115200 valgt, fordi det er påkrævet for Teapot Demo -output, men det er // virkelig op til dig afhængigt af dit projekt) Serial.begin (9600); mens (! Seriel); // vent på Leonardo -optælling, andre fortsætter med det samme // initialiserer enhed Serial.println (F ("Initialiserer I2C -enheder …")); mpu.initialize (); // verificer forbindelsen Serial.println (F ("Test af enhedsforbindelser …")); Serial.println (mpu.testConnection ()? F ("MPU6050 forbindelse lykkedes"): F ("MPU6050 forbindelse mislykkedes")); // indlæse og konfigurere DMP Serial.println (F ("Initialiserer DMP …")); devStatus = mpu.dmpInitialize (); // angiv dine egne gyrokompensationer her, skaleret til min følsomhed mpu.setXGyroOffset (220); mpu.setYGyroOffset (76); mpu.setZGyroOffset (-85); mpu.setZAccelOffset (1788); // 1688 fabriksstandard for min testchip // sørg for, at den fungerede (returnerer 0 i så fald), hvis (devStatus == 0) {// tænder DMP, nu hvor den er klar Serial.println (F ("Aktivering af DMP … ")); mpu.setDMPEnabled (true); // aktiver Arduino -afbrydelsesdetektering Serial.println (F ("Aktivering af afbrydelsesdetektering (Arduino ekstern afbrydelse 0) …")); attachInterrupt (14, dmpDataReady, RISING); mpuIntStatus = mpu.getIntStatus (); // indstil vores DMP Ready -flag, så hovedsløjfen () -funktionen ved, at det er i orden at bruge det Serial.println (F ("DMP klar! Venter på første afbrydelse …")); dmpReady = sand; // få forventet DMP -pakkestørrelse til senere sammenligning packetSize = mpu.dmpGetFIFOPacketSize (); // opsætning af PID pid. SetMode (AUTOMATISK); pid. SetSampleTime (10); pid. SetOutputLimits (-255, 255); } andet {// FEJL! // 1 = initial hukommelsesindlæsning mislykkedes // 2 = DMP -konfigurationsopdateringer mislykkedes // (hvis den går i stykker, vil koden normalt være 1) Serial.print (F ("DMP -initialisering mislykkedes (kode")); Seriel. print (devStatus); Serial.println (F (")")); }} void loop () {// hvis programmeringen mislykkedes, prøv ikke at gøre noget, hvis (! dmpReady) vender tilbage; // vent på MPU -afbrydelse eller ekstra pakker, mens (! mpuInterrupt && fifoCount <packetSize) {pid. Compute (); // denne periode bruges til at indlæse data, så du kan bruge dette til andre beregninger motorSpeed (produktion); } // nulstil interrupt flag og få INT_STATUS byte mpuInterrupt = false; mpuIntStatus = mpu.getIntStatus (); // få det aktuelle FIFO -tal fifoCount = mpu.getFIFOCount (); // tjek for overløb (dette bør aldrig ske, medmindre vores kode er for ineffektiv) hvis ((mpuIntStatus & 0x10) || fifoCount == 1024) {// nulstilles, så vi kan fortsætte rent mpu.resetFIFO (); Serial.println (F ("FIFO -overløb!")); // ellers skal du kontrollere, om DMP -data er klar til afbrydelse (dette skal ske ofte)} ellers hvis (mpuIntStatus & 0x02) {// vente på korrekt tilgængelig datalængde, skulle være en MEGET kort ventetid, mens (fifoCount 1 -pakke tilgængelig // (denne lader os straks læse mere uden at vente på en afbrydelse) 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 vinkler 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; hvis (PWM> = 0) {// fremadgående retning L2 = 0; L1 = abs (PWM); R2 = 0; R1 = abs (PWM); hvis (L1> = 255) { L1 = R1 = 255;}} ellers {// baglæns retning L1 = 0; L2 = abs (PWM); R1 = 0; R2 = abs (PWM); hvis (L2> = 255) {L2 = R2 = 255; }} // motordrev ledcWrite (0, L1); ledcWrite (1, L2); ledcWrite (2, R1*0,97); // 0,97 er hastighedsfakta eller, fordi højre motor har høj hastighed end venstre motor, så vi reducerer den, indtil motorhastighederne er ens ledcWrite (3, R2*0,97);

}

Anbefalede: