Sadržaj:

Samobalansirajući robot iz Magicbita: 6 koraka
Samobalansirajući robot iz Magicbita: 6 koraka

Video: Samobalansirajući robot iz Magicbita: 6 koraka

Video: Samobalansirajući robot iz Magicbita: 6 koraka
Video: DR - Dostavni robot / Delivery robot 2024, Studeni
Anonim

Ovaj vodič prikazuje kako napraviti samobalansirajućeg robota pomoću Magicbit dev ploče. Koristimo magicbit kao razvojnu ploču u ovom projektu koji se temelji na ESP32. Stoga se u ovom projektu može koristiti bilo koja razvojna ploča ESP32.

Pribor:

  • magicbit
  • Pokretač motora s dvostrukim H-mostom L298
  • Linearni regulator (7805)
  • Lipo baterija 7,4V 700mah
  • Inercijalna mjerna jedinica (IMU) (6 stupnjeva slobode)
  • motori zupčanika 3V-6V DC

Korak 1: Priča

Priča
Priča
Priča
Priča

Hej dečki, danas ćemo u ovom vodiču naučiti o malo složenim stvarima. Riječ je o samo balansirajućem robotu koji koristi Magicbit s Arduino IDE -om. Pa krenimo.

Prije svega, pogledajmo što je samo balansirajući robot. Samobalansirajući robot je robot na dva kotača. Posebnost je u tome što se robot može balansirati bez upotrebe vanjske podrške. Kad je napajanje uključeno, robot će ustati, a zatim će kontinuirano balansirati pomoću oscilacijskih pokreta. Dakle, sada imate samo grubu ideju o samo balansirajućem robotu.

Korak 2: Teorija i metodologija

Teorija i metodologija
Teorija i metodologija

Kako bismo uravnotežili robota, prvo dobijemo podatke od nekog senzora za mjerenje kuta robota u okomitoj ravnini. U tu svrhu koristili smo MPU6050. Nakon dobivanja podataka sa senzora izračunavamo nagib u okomitu ravninu. Ako je robot u izravnom i uravnoteženom položaju, kut nagiba je nula. Ako nije, tada je kut nagiba pozitivna ili negativna vrijednost. Ako je robot nagnut prema prednjoj strani, tada bi se robot trebao pomaknuti prema naprijed. Također, ako je robot nagnut na obrnutu stranu, robot bi se trebao kretati u obrnutom smjeru. Ako je ovaj kut nagiba veliki, brzina odziva bi trebala biti velika. Obrnuto, kut nagiba je nizak, a brzina reakcije treba biti mala. Za kontrolu ovog procesa koristili smo poseban teorem zvan PID. PID je upravljački sustav koji kontrolira mnoge procese. PID označava 3 procesa.

  • P- proporcionalna
  • I- integral
  • D- izvedenica

Svaki sustav ima ulaz i izlaz. Na isti način i ovaj upravljački sustav ima neki ulaz. U ovom sustavu upravljanja to je odstupanje od stabilnog stanja. To smo nazvali pogreškom. U našem robotu pogreška je kut nagiba iz okomite ravnine. Ako je robot uravnotežen, kut nagiba je nula. Dakle, vrijednost pogreške bit će nula. Stoga je izlaz PID sustava nula. Ovaj sustav uključuje tri odvojena matematička procesa.

Prva je višestruka pogreška iz numeričkog dobitka. Taj dobitak obično se naziva Kp

P = pogreška*Kp

Drugi je generiranje integrala greške u vremenskoj domeni i pomnožavanje s nekim dobitkom. Taj dobitak naziva se Ki

I = Integral (pogreška)*Ki

Treća je izvedenica pogreške u vremenskoj domeni i pomnoži je s nekom količinom dobitka. Taj dobitak naziva se Kd

D = (d (pogreška)/dt)*kd

Nakon dodavanja gore navedenih operacija dobivamo konačni rezultat

IZLAZAK = P+I+D

Zbog P dijela robot može dobiti stabilan položaj koji je proporcionalan odstupanju. I dio izračunava područje greške u odnosu na grafikon vremena. Stoga pokušava uvijek dovesti robot u stabilan položaj. D dio mjeri nagib u vremenu u odnosu na grafikon pogreške. Ako se greška povećava, ova vrijednost je pozitivna. Ako se pogreška smanjuje, vrijednost je negativna. Zbog toga, kada se robot pomakne u stabilan položaj, brzina reakcije će se smanjiti, što će pomoći u uklanjanju nepotrebnih prekoračenja. Više o PID teoriji možete saznati s ove veze prikazane u nastavku.

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

Izlaz PID funkcije je ograničen na 0-255 raspona (8 bitna PWM rezolucija) i koji će se napajati motorima kao PWM signal.

Korak 3: Postavljanje hardvera

Postavljanje hardvera
Postavljanje hardvera

Ovo je dio podešavanja hardvera. Dizajn robota ovisi o vama. Prilikom projektiranja tijela robota morate uzeti u obzir njegovo simetrično okomito osi koje leži u osi motora. Baterija se nalazi ispod. Zbog toga je robota lako uravnotežiti. U našem dizajnu Magicbit ploču pričvršćujemo okomito na tijelo. Koristili smo dva motora sa 12V zupčanika. Ali možete koristiti bilo koju vrstu zupčanika. to ovisi o dimenzijama vašeg robota.

Kad govorimo o krugu, napaja se Lipo baterijom od 7,4 V. Magicbit je koristio 5V za napajanje. Stoga smo koristili regulator 7805 za regulaciju napona baterije na 5V. U kasnijim verzijama Magicbita taj regulator nije potreban. Zato što napaja do 12V. Izravno isporučujemo 7,4 V za vozača motora.

Spojite sve komponente prema donjem dijagramu.

Korak 4: Postavljanje softvera

U kodu smo koristili PID knjižnicu za izračun PID izlaza.

Idite na sljedeću vezu da biste je preuzeli.

www.arduinolibraries.info/libraries/pid

Preuzmite njegovu najnoviju verziju.

Za bolje očitanje senzora koristili smo DMP biblioteku. DMP označava proces digitalnog kretanja. Ovo je ugrađena značajka MPU6050. Ovaj čip ima integriranu jedinicu procesa kretanja. Stoga je potrebno čitanje i analiza. Nakon što generira bešumne točne izlaze na mikrokontroler (u ovom slučaju Magicbit (ESP32)). Ali postoji mnogo radova na strani mikrokontrolera kako bi se uzela ta očitanja i izračunao kut. Jednostavno, koristili smo MPU6050 DMP knjižnicu. Preuzmite ga gointom na sljedeću vezu.

github.com/ElectronicCats/mpu6050

Za instaliranje knjižnica u izborniku Arduino idite na alati-> uključi biblioteku-> dodaj.zip knjižnicu i odaberite datoteku knjižnice koju ste preuzeli.

U kodu morate ispravno promijeniti kut zadane vrijednosti. Vrijednosti PID konstante razlikuju se od robota do robota. Dakle, pri ugađanju toga, prvo postavite vrijednosti Ki i Kd na nulu, a zatim povećavajte Kp dok ne dobijete bolju brzinu reakcije. Više Kp uzrokuje više preskakanja. Zatim povećajte vrijednost Kd. Povećajte ga uvijek u vrlo maloj količini. Ta je vrijednost općenito niska od ostalih vrijednosti. Sada povećavajte Ki dok ne dobijete vrlo dobru stabilnost.

Odaberite ispravan COM port i vrstu ploče. učitajte kôd. Sada se možete igrati sa svojim DIY robotom.

Korak 5: Sheme

Sheme
Sheme

Korak 6: Kodiranje

#uključi

#include "I2Cdev.h" #include "MPU6050_6Axis_MotionApps20.h" #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE #include "Wire.h" #endif MPU6050 mpu; bool dmpReady = netočno; // postavljanje true ako je DMP init bio uspješan uint8_t mpuIntStatus; // sadrži stvarni bajt statusa prekida iz MPU -a uint8_t devStatus; // vraća status nakon svake operacije uređaja (0 = uspjeh,! 0 = pogreška) uint16_t packetSize; // očekivana veličina paketa DMP (zadana vrijednost je 42 bajta) uint16_t fifoCount; // broj svih bajtova trenutno u FIFO uint8_t fifoBuffer [64]; // FIFO međuspremnik za pohranu Quaternion q; // [w, x, y, z] kvaterionski spremnik VectorFloat gravitacija; // [x, y, z] plovak gravitacijskog vektora ypr [3]; // [skretanje, nagib, kotrljanje] spremnik za skretanje/nagib/kotrljanje i gravitacijski vektor dvostruki originalSetpoint = 172,5; dvostruka zadana vrijednost = originalnaSetpoint; dvostruko pomicanjeAngleOffset = 0,1; dvostruki ulaz, izlaz; int moveState = 0; double Kp = 23; // postavite P prvi double Kd = 0,8; // ova vrijednost općenito je mala double Ki = 300; // ova vrijednost bi trebala biti visoka za bolju stabilnost PID pid (& ulaz, & izlaz, & zadana vrijednost, Kp, Ki, Kd, DIRECT); // pid inicijalize int motL1 = 26; // 4 pina za motorni pogon int motL2 = 2; int motR1 = 27; int motR2 = 4; volatile bool mpuInterrupt = false; // označava je li pin za prekid MPU -a otišao visoko void dmpDataReady () {mpuInterrupt = true; } void setup () {ledcSetup (0, 20000, 8); // postavljanje pwm ledcSetup (1, 20000, 8); ledcSetup (2, 20000, 8); ledcSetup (3, 20000, 8); ledcAttachPin (motL1, 0); // pinmode motora ledcAttachPin (motL2, 1); ledcAttachPin (motR1, 2); ledcAttachPin (motR2, 3); // pridruživanje sabirnici I2C (knjižnica I2Cdev to ne radi automatski) #ako I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE Wire.begin (); Wire.setClock (400000); // 400 kHz I2C sat. Komentirajte ovaj redak ako imate poteškoća s sastavljanjem #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE Fastwire:: setup (400, istina); #endif Serial.println (F ("Inicijalizacija I2C uređaja …")); pinMode (14, INPUT); // inicirali serijsku komunikaciju // (115200 odabrano jer je potrebno za Teapot Demo izlaz, ali // doista ovisi o vama, ovisno o vašem projektu) Serial.begin (9600); while (! Serijski); // čekamo Leonardovo nabrajanje, drugi nastavljaju odmah // inicijaliziramo uređaj Serial.println (F ("Inicijalizacija I2C uređaja …")); mpu.initialize (); // provjeravamo vezu Serial.println (F ("Testiranje veza uređaja …")); Serial.println (mpu.testConnection ()? F ("Veza MPU6050 uspješna"): F ("Veza MPU6050 nije uspjela")); // učitavanje i konfiguriranje DMP Serial.println (F ("Inicijalizacija DMP …")); devStatus = mpu.dmpInitialize (); // ovdje unosite vlastite pomake žiroa, prilagođene za minimalnu osjetljivost mpu.setXGyroOffset (220); mpu.setYGyroOffset (76); mpu.setZGyroOffset (-85); mpu.setZAccelOffset (1788); // 1688 tvornički zadane vrijednosti za moj testni čip // provjerite radi li (vraća 0 ako je tako) if (devStatus == 0) {// uključite DMP, sada kada je spreman Serial.println (F ("Omogućavanje DMP … ")); mpu.setDMPEnabled (true); // omogućujemo otkrivanje prekida Arduino Serial.println (F ("Omogućavanje otkrivanja prekida (Arduino vanjski prekid 0) …")); attachInterrupt (14, dmpDataReady, RISING); mpuIntStatus = mpu.getIntStatus (); // postavljamo zastavu DMP Ready tako da funkcija main loop () zna da je u redu koristiti je Serial.println (F ("DMP spreman! Čeka prvi prekid …")); dmpReady = istina; // dobiti očekivanu veličinu paketa DMP za kasniju usporedbu packetSize = mpu.dmpGetFIFOPacketSize (); // postavljanje PID pid. SetMode (AUTOMATSKO); pid. SetSampleTime (10); pid. SetOutputLimits (-255, 255); } else {// GREŠKA! // 1 = početno učitavanje memorije nije uspjelo // 2 = ažuriranja konfiguracije DMP -a nisu uspjela // (ako će se prekinuti, obično će kôd biti 1) Serial.print (F ("DMP Initialization failed (code")); Serial. ispis (devStatus); Serial.println (F (")")); }} void loop () {// ako programiranje nije uspjelo, ne pokušavajte ništa učiniti ako se (! dmpReady) vrati; // čekamo prekid MPU -a ili dodatne pakete koji su dostupni dok (! mpuInterrupt && fifoCount <packetSize) {pid. Compute (); // ovo se vremensko razdoblje koristi za učitavanje podataka, pa ga možete koristiti za druge izračune motorSpeed (izlaz); } // resetirati zastavu prekida i dobiti INT_STATUS bajt mpuInterrupt = false; mpuIntStatus = mpu.getIntStatus (); // dobiti trenutni broj FIFO fifoCount = mpu.getFIFOCount (); // provjeravamo ima li prelijevanja (to se nikada ne bi trebalo dogoditi osim ako je naš kod previše neučinkovit) if ((mpuIntStatus & 0x10) || fifoCount == 1024) {// reset kako bismo mogli nastaviti čisto mpu.resetFIFO (); Serial.println (F ("FIFO prelijevanje!")); // u protivnom, provjerite ima li prekida za spremanje DMP podataka (to bi se trebalo događati često)} inače ako (mpuIntStatus & 0x02) {// pričeka ispravnu raspoloživu duljinu podataka, trebalo bi biti JAKO kratko čekanje ((fifoCount 1 paket dostupan // (ovo dopušta nam da odmah čitamo više bez čekanja na prekid) fifoCount -= packetSize; mpu.dmpGetQuaternion (& q, fifoBuffer); mpu.dmpGetGravity (& gravity, & q); mpu.dmpGetYawPitchRoll (ypr, & q, & gravity); #IF LOG_ print ("ypr / t"); Serial.print (ypr [0] * 180/M_PI); // euler kutovi 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) {// smjer naprijed L2 = 0; L1 = abs (PWM); R2 = 0; R1 = abs (PWM); ako je (L1> = 255) { L1 = R1 = 255;}} else {// smjer unatrag L1 = 0; L2 = abs (PWM); R1 = 0; R2 = abs (PWM); ako je (L2> = 255) {L2 = R2 = 255; }} // motorni pogon ledcWrite (0, L1); ledcWrite (1, L2); ledcWrite (2, R1*0,97); // 0,97 je činjenica o brzini ili, jer desni motor ima veću brzinu od lijevog motora, pa ga smanjujemo dok brzine motora ne budu jednake ledcWrite (3, R2*0,97);

}

Preporučeni: