Përmbajtje:

Robot vetë -balancues nga Magicbit: 6 hapa
Robot vetë -balancues nga Magicbit: 6 hapa

Video: Robot vetë -balancues nga Magicbit: 6 hapa

Video: Robot vetë -balancues nga Magicbit: 6 hapa
Video: ЛЮБОВЬ С ДОСТАВКОЙ НА ДОМ (2020). Романтическая комедия. Хит 2024, Nëntor
Anonim

Ky tutorial tregon se si të bëni një robot vetë -balancues duke përdorur bordin Magicbit dev. Ne po përdorim magicbit si bordin e zhvillimit në këtë projekt i cili bazohet në ESP32. Prandaj, çdo bord zhvillimi ESP32 mund të përdoret në këtë projekt.

Furnizimet:

  • magjistar
  • Drejtues motorik i dyfishtë H-urë L298
  • Rregullatori linear (7805)
  • Bateri Lipo 7.4V 700mah
  • Njësia e Matjes Inerciale (IMU) (6 gradë liri)
  • motorët e marsheve 3V-6V DC

Hapi 1: Histori

Histori
Histori
Histori
Histori

Hej djema, sot në këtë tutorial do të mësojmë për gjëra pak komplekse. Bëhet fjalë për një robot vetë -balancues duke përdorur Magicbit me Arduino IDE. Pra, le të fillojmë.

Para së gjithash, le të shohim se çfarë është një robot vetë -balancues. Roboti vetë -balancues është një robot me dy rrota. Karakteristika e veçantë është se roboti mund të balancojë veten pa përdorur ndonjë mbështetje të jashtme. Kur fuqia është në robot do të ngrihet dhe pastaj ai balancohet vazhdimisht duke përdorur lëvizjet e lëkundjeve. Pra, tani të gjithë ju keni një ide të përafërt për robotin vetë -balancues.

Hapi 2: Teori dhe Metodologji

Teori dhe Metodologji
Teori dhe Metodologji

Për të balancuar robotin, së pari marrim të dhëna nga një sensor për të matur këndin e robotit në planin vertikal. Për atë qëllim ne përdorëm MPU6050. Pas marrjes së të dhënave nga sensori ne llogarisim pjerrësinë në planin vertikal. Nëse roboti është në pozicion të drejtë dhe të balancuar, atëherë këndi i pjerrësisë është zero. Nëse jo, atëherë këndi i pjerrësisë është vlerë pozitive ose negative. Nëse roboti është i përkulur në anën e përparme, atëherë roboti duhet të lëvizë në drejtimin e përparmë. Gjithashtu nëse roboti është i përkulur në anën e kundërt, atëherë roboti duhet të lëvizë në drejtim të kundërt. Nëse ky kënd i pjerrësisë është i lartë atëherë shpejtësia e përgjigjes duhet të jetë e lartë. Anasjelltas këndi i pjerrësisë është i ulët atëherë shpejtësia e reagimit duhet të jetë e ulët. Për të kontrolluar këtë proces ne përdorëm teoremë specifike të quajtur PID. PID është sistemi i kontrollit i cili përdoret për të kontrolluar shumë procese. PID nënkupton 3 procese.

  • P- proporcionale
  • I- integrale
  • D- derivat

Çdo sistem ka hyrje dhe dalje. Në të njëjtën mënyrë ky sistem kontrolli gjithashtu ka një hyrje. Në këtë sistem kontrolli është devijimi nga gjendja e qëndrueshme. Ne e quajtëm atë si gabim. Në robotin tonë, gabimi është këndi i pjerrësisë nga rrafshi vertikal. Nëse roboti është i balancuar atëherë këndi i pjerrësisë është zero. Pra, vlera e gabimit do të jetë zero. Prandaj dalja e sistemit PID është zero. Ky sistem përfshin tre procese të veçanta matematikore.

E para është shumëzimi i gabimit nga fitimi numerik. Ky fitim zakonisht quhet Kp

P = gabim*Kp

E dyta është të gjeneroni integralin e gabimit në fushën e kohës dhe ta shumëzoni atë nga një fitim. Ky fitim i quajtur si Ki

I = Integral (gabim)*Ki

E treta është derivat i gabimit në fushën kohore dhe shumëzojeni atë me një sasi fitimi. Ky fitim quhet Kd

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

Pas shtimit të operacioneve të mësipërme marrim daljen tonë përfundimtare

DALJA = P+I+D

Për shkak të pjesës P, roboti mund të marrë një pozicion të qëndrueshëm, i cili është proporcional me devijimin. Pjesa I llogarit zonën e gabimit kundrejt grafikut kohor. Kështu që përpiqet ta çojë robotin në pozicion të qëndrueshëm gjithmonë me saktësi. Pjesa D mat pjerrësinë në kohë kundrejt grafikut të gabimit. Nëse gabimi po rritet kjo vlerë është pozitive. Nëse gabimi po zvogëlohet, kjo vlerë është negative. Për shkak të kësaj, kur roboti lëviz në pozicion të qëndrueshëm, atëherë shpejtësia e reagimit do të ulet dhe kjo do të ndihmojë për të hequr tejkalimet e panevojshme. Mund të mësoni më shumë rreth teorisë PID nga kjo lidhje e treguar më poshtë.

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

Dalja e funksionit PID është e kufizuar në intervalin 0-255 (rezolucion 8 bit PWM) dhe që do të ushqehet me motorët si sinjal PWM.

Hapi 3: Konfigurimi i harduerit

Konfigurimi i harduerit
Konfigurimi i harduerit

Tani kjo është pjesa e konfigurimit të harduerit. Dizajni i robotit varet nga ju. Kur projektoni trupin e robotit, duhet ta konsideroni atë simetrik rreth boshtit vertikal i cili shtrihet në boshtin motorik. Paketa e baterive e vendosur më poshtë. Prandaj, roboti është i lehtë për t'u balancuar. Në modelin tonë ne e fiksojmë bordin Magicbit vertikalisht në trup. Ne përdorëm dy motorë me shpejtësi 12V. Por mund të përdorni çdo lloj motori ingranazhesh. që varet nga dimensionet e robotit tuaj.

Kur diskutojmë për qarkun mundësohet nga bateria 7.4V Lipo. Magicbit përdori 5V për furnizimin me energji. Prandaj ne përdorëm rregullatorin 7805 për të rregulluar tensionin e baterisë në 5V. Në versionet e mëvonshme të Magicbit atij rregullator nuk i nevojitet. Sepse mund të furnizohet me energji deri në 12 V. Ne furnizojmë drejtpërdrejt 7.4V për drejtuesin e motorit.

Lidhni të gjithë përbërësit sipas diagramit më poshtë.

Hapi 4: Konfigurimi i softuerit

Në kodin kemi përdorur bibliotekën PID për llogaritjen e daljes PID.

Shkoni në lidhjen e mëposhtme për ta shkarkuar.

www.arduinolibraries.info/libraries/pid

Shkarkoni versionin e fundit të tij.

Për të marrë lexime më të mira të sensorit, ne përdorëm bibliotekën DMP. DMP qëndron për procesin e lëvizjes dixhitale. Kjo është veçori e integruar e MPU6050. Ky çip ka njësi të integruar të procesit të lëvizjes. Kështu që duhet lexuar dhe analizuar. Pasi gjeneron rezultate të sakta pa zhurmë te mikrokontrolluesi (në këtë rast Magicbit (ESP32)). Por ka shumë punë në anën e mikrokontrolluesit për të marrë ato lexime dhe për të llogaritur këndin. Pra, thjesht kemi përdorur bibliotekën MPU6050 DMP. Shkarkoni atë duke shkuar në lidhjen e mëposhtme.

github.com/ElectronicCats/mpu6050

Për të instaluar bibliotekat, në menunë Arduino shkoni te mjetet-> përfshini bibliotekën-> bibliotekën add.zip dhe zgjidhni skedarin e bibliotekës që keni shkarkuar.

Në kod duhet të ndryshoni saktë këndin e pikës së caktuar. Vlerat konstante të PID janë të ndryshme nga roboti në robot. Pra, në akordimin e tij, së pari vendosni vlerat Ki dhe Kd zero dhe më pas rriteni Kp derisa të merrni shpejtësi më të mirë të reagimit. Më shumë Kp shkakton për më shumë tejkalime. Pastaj rrisni vlerën Kd. Rriteni atë gjithmonë në sasi shumë të vogël. Kjo vlerë është përgjithësisht e ulët se vlerat e tjera. Tani shtoni Ki derisa të keni stabilitet shumë të mirë.

Zgjidhni portën e duhur COM dhe llojin e bordit. ngarkoni kodin. Tani mund të luani me robotin tuaj DIY.

Hapi 5: Skemat

Skematike
Skematike

Hapi 6: Kodi

#përfshi

#përfshi "I2Cdev.h" #include "MPU6050_6Axis_MotionApps20.h" #ifo I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE #përfshi "Wire.h" #endif MPU6050 mpu; bool dmpReady = false; // vendoset e vërtetë nëse DMP init ishte i suksesshëm uint8_t mpuIntStatus; // mban bajt të statusit aktual të ndërprerjes nga MPU uint8_t devStatus; // kthe statusin pas çdo operacioni të pajisjes (0 = sukses,! 0 = gabim) uint16_t packetSize; // madhësia e pritshme e paketës DMP (parazgjedhja është 42 bajt) uint16_t fifoCount; // numërimi i të gjithë byteve aktualisht në FIFO uint8_t fifoBuffer [64]; // Tampon i ruajtjes FIFO Quaternion q; // [w, x, y, z] enë kuaternion VectorFloat graviteti; // [x, y, z] vektori i gravitetit noton ypr [3]; // [yaw, pitch, roll] yaw/katran/rrotull enë dhe vektor graviteti dyfish origjinalSetpoint = 172.5; pika e dyfishtë = pika origjinale; lëvizje e dyfishtëAngleOffset = 0.1; hyrje, dalje e dyfishtë; int moveState = 0; dyshe Kp = 23; // vendos P dyfishin e parë Kd = 0.8; // kjo vlerë përgjithësisht e vogël dyshe Ki = 300; // kjo vlerë duhet të jetë e lartë për qëndrueshmëri më të mirë PID pid (& input, & output, & point set, Kp, Ki, Kd, DIREKT); // pid inicializon int motL1 = 26; // 4 kunja për motor motor int motL2 = 2; int motR1 = 27; int motR2 = 4; bool i paqëndrueshëm mpuInterrupt = false; // tregon nëse kunja e ndërprerjes MPU ka shkuar shumë lart void 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); // modaliteti i motorëve ledcAttachPin (motL2, 1); ledcAttachPin (motR1, 2); ledcAttachPin (motR2, 3); // bashkohu me autobusin I2C (biblioteka I2Cdev nuk e bën këtë automatikisht) #nëse I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE Wire.begin (); Wire.setClock (400000); // Ora 400kHz I2C. Komentoni këtë rresht nëse keni vështirësi në përpilim #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE Fastwire:: konfigurimi (400, e vërtetë); #endif Serial.println (F ("Fillimi i pajisjeve I2C …")); pinMode (14, INPUT); // iniconi komunikimin serik // (115200 i zgjedhur sepse kërkohet për daljen e Teapot Demo, por është // varet nga ju në varësi të projektit tuaj) Serial.begin (9600); ndërsa (! Serial); // prisni për regjistrimin e Leonardos, të tjerët vazhdojnë menjëherë // inicializojnë pajisjen Serial.println (F ("Fillimi i pajisjeve I2C …")); mpu.initialize (); // verifikoni lidhjen Serial.println (F ("Testimi i lidhjeve të pajisjes …")); Serial.println (mpu.testConnection ()? F ("Lidhja MPU6050 e suksesshme"): F ("Lidhja MPU6050 dështoi")); // ngarkoni dhe konfiguroni DMP Serial.println (F ("Initializing DMP …")); devStatus = mpu.dmpInitialize (); // furnizoni kompensimet tuaja xhiro këtu, të shkallëzuara për ndjeshmërinë minimale mpu.setXGyroOffset (220); mpu.setYGyroOffset (76); mpu.setZGyroOffset (-85); mpu.setZAccelOffset (1788); // 1688 parazgjedhja e fabrikës për çipin tim të provës // sigurohuni që ka punuar (kthen 0 nëse është kështu) nëse (devStatus == 0) {// ndizni DMP, tani që është gati Serial.println (F ("Aktivizimi i DMP … ")); mpu.setDMPE aktivizuar (e vërtetë); // aktivizoni zbulimin e ndërprerjes Arduino Serial.println (F ("Aktivizimi i zbulimit të ndërprerjeve (ndërprerja e jashtme Arduino 0) …")); attachInterrupt (14, dmpDataReady, RISING); mpuIntStatus = mpu.getIntStatus (); // vendosni flamurin tonë DMP Ready në mënyrë që funksioni kryesor i lakut () të dijë se është në rregull ta përdorni atë Serial.println (F ("DMP gati! Duke pritur ndërprerjen e parë …")); dmpReady = e vërtetë; // merrni madhësinë e pritshme të paketës DMP për pakot e krahasimit të mëvonshëmSize = mpu.dmpGetFIFOPacketSize (); // konfiguro PID pid. SetMode (AUTOMATIKE); pid. SetSampleTime (10); pid. SetOutputLimits (-255, 255); } tjetër {// GABIM! // 1 = Ngarkesa fillestare e kujtesës dështoi // 2 = Përditësimet e konfigurimit të DMP dështuan // (nëse do të prishet, zakonisht kodi do të jetë 1) Serial.print (F ("Inicimi i DMP dështoi (kodi")); Serial. print (devStatus); Serial.println (F (")")); }} void loop () {// nëse programimi dështoi, mos u përpiqni të bëni asgjë nëse (! dmpReady) kthehet; // prisni për ndërprerjen e MPU ose paketat shtesë të disponueshme derisa (! mpuInterrupt && fifoCount <packetSize) {pid. Compute (); // kjo periudhë kohore përdoret për të ngarkuar të dhënat, kështu që ju mund ta përdorni këtë për llogaritjet e tjera motorSpeed (dalje); } // rivendosni flamurin e ndërprerjes dhe merrni INT_STATUS bajt mpuInterrupt = false; mpuIntStatus = mpu.getIntStatus (); // merrni numrin aktual të FIFO fifoCount = mpu.getFIFOCount (); // kontrolloni për tejmbushje (kjo nuk duhet të ndodhë kurrë nëse kodi ynë nuk është shumë efikas) nëse ((mpuIntStatus & 0x10) || fifoCount == 1024) {// rivendoset që të mund të vazhdojmë pastër mpu.resetFIFO (); Serial.println (F ("FIFO overflow!")); // përndryshe, kontrolloni për ndërprerjen e gatshme të të dhënave DMP (kjo duhet të ndodhë shpesh)} përndryshe nëse (mpuIntStatus & 0x02) {// prisni për gjatësinë e saktë të të dhënave të disponueshme, duhet të jetë një pritje SHUMY e shkurtër derisa (fifoCount 1 pako në dispozicion // (kjo na lejon të lexojmë menjëherë më shumë pa pritur ndërprerjen) print ("ypr / t"); Serial.print (ypr [0] * 180/M_PI); // këndet euler 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;}} motor voidSpeed (int PWM) {noton L1, L2, R1, R2; nëse (PWM> = 0) {// drejtimi përpara L2 = 0; L1 = abs (PWM); R2 = 0; R1 = abs (PWM); nëse (L1> = 255) { L1 = R1 = 255;}} tjetër {// drejtim mbrapa L1 = 0; L2 = abs (PWM); R1 = 0; R2 = abs (PWM); nëse (L2> = 255) {L2 = R2 = 255; }} // makinë me makinë ledcWrite (0, L1); ledcWrite (1, L2); ledcWrite (2, R1*0.97); // 0.97 është fakt i shpejtësisë ose, sepse motori i djathtë ka shpejtësi më të madhe se motori i majtë, kështu që ne e zvogëlojmë atë derisa shpejtësitë e motorit të jenë të barabarta ledcWrite (3, R2*0.97);

}

Recommended: