Innholdsfortegnelse:

Selvbalanserende robot fra Magicbit: 6 trinn
Selvbalanserende robot fra Magicbit: 6 trinn

Video: Selvbalanserende robot fra Magicbit: 6 trinn

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

Denne opplæringen viser hvordan du lager en selvbalanserende robot ved hjelp av Magicbit dev board. Vi bruker magicbit som utviklingstavle i dette prosjektet som er basert på ESP32. Derfor kan et hvilket som helst ESP32 -utviklingsbord brukes i dette prosjektet.

Rekvisita:

  • magicbit
  • Dobbelt H-bro L298 motorfører
  • Lineær regulator (7805)
  • Lipo 7,4V 700mah batteri
  • Inertial Measurement Unit (IMU) (6 grader frihet)
  • girmotorer 3V-6V DC

Trinn 1: Historie

Historie
Historie
Historie
Historie

Hei folkens, i dag vil vi i denne opplæringen lære om litt komplekse ting. Det handler om selvbalanserende robot som bruker Magicbit med Arduino IDE. Så la oss komme i gang.

La oss først se på hva som er en selvbalanserende robot. Selvbalanserende robot er tohjulet robot. Spesialfunksjonen er at roboten kan balansere seg selv uten å bruke ekstern støtte. Når strømmen er på, vil roboten stå opp og deretter balansere den kontinuerlig ved å bruke svingningsbevegelser. Så nå har du en grov ide om selvbalanserende robot.

Trinn 2: Teori og metodikk

Teori og metodikk
Teori og metodikk

For å balansere roboten, får vi først data fra en sensor for å måle robotvinkelen til det vertikale planet. Til det formålet brukte vi MPU6050. Etter å ha fått dataene fra sensoren beregner vi tilt til vertikalplan. Hvis roboten er i rett og balansert posisjon, er tiltvinkelen null. Hvis ikke, er vippevinkelen positiv eller negativ verdi. Hvis roboten vippes til forsiden, bør roboten bevege seg til fremre retning. Også hvis roboten vippes til baksiden, bør roboten bevege seg i motsatt retning. Hvis denne vippevinkelen er høy, bør svarhastigheten være høy. Omvendt er vippevinkelen lav og reaksjonshastigheten bør være lav. For å kontrollere denne prosessen brukte vi spesifikk teorem kalt PID. PID er kontrollsystem som brukes til å kontrollere mange prosesser. PID står for 3 prosesser.

  • P- proporsjonal
  • Jeg- integrert
  • D-derivat

Hvert system har inngang og utgang. På samme måte har dette kontrollsystemet også noen input. I dette kontrollsystemet er det avviket fra stabil tilstand. Vi kalte det som feil. I vår robot er feil tiltvinkelen fra det vertikale planet. Hvis roboten er balansert, er vippevinkelen null. Så feilverdien vil være null. Derfor er utgangen til PID -systemet null. Dette systemet inkluderer tre separate matematiske prosesser.

Den første er multipliseringsfeil fra numerisk forsterkning. Denne gevinsten kalles vanligvis Kp

P = feil*Kp

Den andre er å generere integralen av feilen i tidsdomenet og multiplisere den fra en viss gevinst. Denne gevinsten ble kalt Ki

I = Integral (feil)*Ki

Den tredje er avledet av feilen i tidsdomenet og multipliser den med en viss gevinst. Denne gevinsten kalles Kd

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

Etter å ha lagt til operasjonene ovenfor får vi vår endelige utgang

UTGANG = P+I+D

På grunn av P -delen kan roboten få en stabil posisjon som er proporsjonal med avviket. I del beregner området for feil vs tid. Så den prøver å få roboten til stabil posisjon alltid nøyaktig. D -delen måler skråningen i tid vs feilgraf. Hvis feilen øker, er denne verdien positiv. Hvis feilen minker, er denne verdien negativ. På grunn av det, når roboten beveger seg til stabil posisjon, vil reaksjonshastigheten reduseres, og dette vil være nyttig for å fjerne unødvendige overskytinger. Du kan lære mer om PID -teori fra denne lenken vist nedenfor.

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

Utgangen til PID-funksjonen er begrenset til 0-255 område (8 biters PWM-oppløsning), og den vil mates til motorer som PWM-signal.

Trinn 3: Maskinvareoppsett

Maskinvareoppsett
Maskinvareoppsett

Nå er dette en maskinvareoppsettdel. Robotens design er avhengig av deg. Når du designet robotens kropp, må du vurdere symmetrisk den om den vertikale aksen som ligger i motoraksen. Batteripakken nedenfor. Derfor er roboten lett å balansere. I vårt design fester vi Magicbit -bord vertikalt til kroppen. Vi brukte to 12V girmotorer. Men du kan bruke alle typer girmotorer. det er avhengig av robotdimensjonene dine.

Når vi diskuterer om krets, drives den av et 7,4V Lipo -batteri. Magicbit brukte 5V for strømforsyning. Derfor brukte vi 7805 regulator for å regulere batterispenningen til 5V. I senere versjoner av Magicbit er denne regulatoren ikke nødvendig. Fordi den driver opptil 12V. Vi leverer direkte 7,4V for motorfører.

Koble til alle komponentene i henhold til diagrammet nedenfor.

Trinn 4: Programvareoppsett

I koden brukte vi PID -biblioteket for å beregne PID -utgang.

Gå til følgende lenke for å laste den ned.

www.arduinolibraries.info/libraries/pid

Last ned den siste versjonen av den.

For å få bedre sensoravlesninger brukte vi DMP -biblioteket. DMP står for digital motion process. Dette er en innebygd funksjon i MPU6050. Denne brikken har integrert bevegelsesprosessenhet. Så det krever lesing og analyse. Etter at den genererer lydløse, nøyaktige utganger til mikrokontrolleren (i dette tilfellet Magicbit (ESP32)). Men det er mange arbeider på mikrokontrollersiden for å ta avlesningene og beregne vinkelen. Så ganske enkelt at vi brukte MPU6050 DMP -bibliotek. Last den ned ved å gå til følgende lenke.

github.com/ElectronicCats/mpu6050

For å installere bibliotekene, gå til Verktøy-> inkluder bibliotek-> add.zip-biblioteket i Arduino-menyen og velg biblioteksfilen du lastet ned.

I koden må du endre settpunktvinkelen riktig. PID -konstante verdier er forskjellige fra robot til robot. Så ved å stille inn det, sett først Ki- og Kd -verdiene til null og øk deretter Kp til du får bedre reaksjonshastighet. Flere Kp forårsaker flere overskridelser. Øk deretter Kd -verdien. Øk det med alltid i svært liten mengde. Denne verdien er generelt lav enn andre verdier. Øk nå Ki til du har veldig god stabilitet.

Velg riktig COM -port og skriv inn. last opp koden. Nå kan du leke med din DIY -robot.

Trinn 5: Skjemaer

Skjemaer
Skjemaer

Trinn 6: Kode

#inkludere

#include "I2Cdev.h" #include "MPU6050_6Axis_MotionApps20.h" #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE #include "Wire.h" #endif MPU6050 mpu; bool dmpReady = false; // satt true hvis DMP init var vellykket uint8_t mpuIntStatus; // holder faktisk avbruddsstatusbyte fra MPU uint8_t devStatus; // returstatus etter hver enhetsoperasjon (0 = suksess,! 0 = feil) uint16_t packetSize; // forventet DMP -pakkestørrelse (standard er 42 byte) uint16_t fifoCount; // telling av alle byte som for øyeblikket er i FIFO uint8_t fifoBuffer [64]; // FIFO lagringsbuffer Quaternion q; // [w, x, y, z] quaternion container VectorFloat gravity; // [x, y, z] tyngdekraftvektor float ypr [3]; // [yaw, pitch, roll] yaw/pitch/roll container og tyngdekraftvektoren dobbel originalSetpoint = 172,5; dobbelt settpunkt = originalSetpoint; double movingAngleOffset = 0,1; dobbel inngang, utgang; int moveState = 0; dobbel Kp = 23; // sett P først dobbel Kd = 0,8; // denne verdien generelt liten dobbel Ki = 300; // denne verdien skal være høy for bedre stabilitet PID pid (& input, & output, & setpoint, Kp, Ki, Kd, DIRECT); // pid initialize int motL1 = 26; // 4 pins for motordrift int motL2 = 2; int motR1 = 27; int motR2 = 4; flyktig bool mpuInterrupt = false; // angir om MPU -avbruddsnålen har gått høyt tomrom 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); // bli med i I2C -buss (I2Cdev -biblioteket gjør ikke dette automatisk) #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE Wire.begin (); Wire.setClock (400000); // 400kHz I2C klokke. Kommenter denne linjen hvis du har problemer med kompilering #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE Fastwire:: setup (400, true); #endif Serial.println (F ("Initialiserer I2C -enheter …")); pinMode (14, INNGANG); // initialisere seriell kommunikasjon // (115200 valgt fordi det er nødvendig for tekanne -demoutgang, men det er // virkelig opp til deg avhengig av prosjektet ditt) Serial.begin (9600); mens (! Seriell); // vent på Leonardo -oppregning, andre fortsetter umiddelbart // initialiserer enhet Serial.println (F ("Initialiserer I2C -enheter …")); mpu.initialize (); // bekreft tilkoblingen Serial.println (F ("Tilkobling av testenheter …")); Serial.println (mpu.testConnection ()? F ("MPU6050 tilkobling vellykket"): F ("MPU6050 tilkobling mislyktes")); // last inn og konfigurer DMP Serial.println (F ("Initialiserer DMP …")); devStatus = mpu.dmpInitialize (); // levere dine egne gyroforskyvninger her, skalert for min følsomhet mpu.setXGyroOffset (220); mpu.setYGyroOffset (76); mpu.setZGyroOffset (-85); mpu.setZAccelOffset (1788); // 1688 fabrikkstandard for testbrikken min // sørg for at den fungerte (returnerer 0 i så fall) hvis (devStatus == 0) {// slår på DMP, nå som den er klar Serial.println (F ("Aktiverer DMP … ")); mpu.setDMPEnabled (true); // aktiver Arduino avbruddsdeteksjon Serial.println (F ("Aktiverer avbruddsdeteksjon (Arduino ekstern avbrudd 0" …))); attachInterrupt (14, dmpDataReady, RISING); mpuIntStatus = mpu.getIntStatus (); // sett vårt DMP Ready -flagg slik at hovedsløyfen () -funksjonen vet at det er greit å bruke det Serial.println (F ("DMP ready! Waiting for first interrupt…")); dmpReady = true; // få forventet DMP -pakkestørrelse for senere sammenligning packetSize = mpu.dmpGetFIFOPacketSize (); // oppsett PID pid. SetMode (AUTOMATISK); pid. SetSampleTime (10); pid. SetOutputLimits (-255, 255); } annet {// FEIL! // 1 = initial minnelast mislyktes // 2 = DMP -konfigurasjonsoppdateringer mislyktes // (hvis den skal gå i stykker, vil koden vanligvis være 1) Serial.print (F ("DMP -initialisering mislyktes (kode")); Seriell. print (devStatus); Serial.println (F (")"))); }} void loop () {// hvis programmeringen mislyktes, ikke prøv å gjøre noe hvis (! dmpReady) returnerer; // vent på MPU -avbrudd eller ekstra pakke (r) tilgjengelig mens (! mpuInterrupt && fifoCount <packetSize) {pid. Compute (); // denne tidsperioden brukes til å laste inn data, så du kan bruke dette til andre beregninger motorSpeed (produksjon); } // tilbakestill interrupt flagg og få INT_STATUS byte mpuInterrupt = false; mpuIntStatus = mpu.getIntStatus (); // få gjeldende FIFO -telling fifoCount = mpu.getFIFOCount (); // sjekk for overløp (dette bør aldri skje med mindre koden vår er for ineffektiv) hvis ((mpuIntStatus & 0x10) || fifoCount == 1024) {// tilbakestille slik at vi kan fortsette rent mpu.resetFIFO (); Serial.println (F ("FIFO -overløp!")); // ellers, se etter DMP -data klar avbrudd (dette bør skje ofte)} ellers hvis (mpuIntStatus & 0x02) {// vent på riktig tilgjengelig datalengde, bør være en VELDIG kort ventetid mens (fifoCount 1 -pakke tilgjengelig // (denne lar oss umiddelbart lese mer uten å vente på et avbrudd) 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) {// fremoverretning L2 = 0; L1 = abs (PWM); R2 = 0; R1 = abs (PWM); hvis (L1> = 255) { L1 = R1 = 255;}} annet {// bakoverretning L1 = 0; L2 = abs (PWM); R1 = 0; R2 = abs (PWM); hvis (L2> = 255) {L2 = R2 = 255; }} // motordrevet ledcWrite (0, L1); ledcWrite (1, L2); ledcWrite (2, R1*0,97); // 0,97 er hastighetsfakta eller fordi høyre motor har høy hastighet enn venstre motor, så vi reduserer den til motorhastigheten er lik ledcWrite (3, R2*0,97);

}

Anbefalt: