INHOUDSOPGAWE:

Selfbalanserende robot van Magicbit: 6 stappe
Selfbalanserende robot van Magicbit: 6 stappe

Video: Selfbalanserende robot van Magicbit: 6 stappe

Video: Selfbalanserende robot van Magicbit: 6 stappe
Video: Энтони Метивье: трюки с повышением IQ и памяти 2024, Julie
Anonim

Hierdie handleiding wys hoe u 'n selfbalanserende robot kan maak met behulp van Magicbit dev -bord. Ons gebruik magicbit as die ontwikkelingsbord in hierdie projek wat op ESP32 gebaseer is. Daarom kan enige ESP32 -ontwikkelingsbord in hierdie projek gebruik word.

Benodighede:

  • towerkuns
  • Dubbele H-brug L298 motorbestuurder
  • Lineêre reguleerder (7805)
  • Lipo 7.4V 700mah battery
  • Traagmeeteenheid (IMU) (6 grade vryheid)
  • ratmotors 3V-6V DC

Stap 1: Verhaal

Verhaal
Verhaal
Verhaal
Verhaal

Hey ouens, vandag leer ons in hierdie tutoriaal oor 'n bietjie ingewikkelde ding. Dit gaan oor selfbalanserende robot wat Magicbit gebruik met Arduino IDE. Laat ons dus begin.

Kom ons kyk eerstens na die selfbalanserende robot. Selfbalanserende robot is 'n tweewielige robot. Die spesiale kenmerk is dat die robot homself kan balanseer sonder om eksterne ondersteuning te gebruik. As die krag aan is, sal die robot opstaan en dan deurlopend gebalanseer word deur ossillasiebewegings te gebruik. So, nou het u 'n bietjie idee oor die selfbalanserende robot.

Stap 2: Teorie en metodiek

Teorie en metodiek
Teorie en metodiek

Om die robot te balanseer, kry ons eers data van 'n sensor om die hoek van die robot na die vertikale vlak te meet. Vir hierdie doel het ons MPU6050 gebruik. Nadat ons die data van die sensor gekry het, bereken ons die kanteling na die vertikale vlak. As die robot in 'n reguit en gebalanseerde posisie is, is die kantelhoek nul. Indien nie, dan is die kantelhoek positiewe of negatiewe waarde. As die robot na die voorkant kantel, moet die robot na die voorste rigting beweeg. As die robot ook na die agterkant kantel, moet die robot in die omgekeerde rigting beweeg. As hierdie kantelhoek hoog is, moet die reaksiesnelheid hoog wees. Omgekeerd is die kantelhoek laag, dan moet die reaksiesnelheid laag wees. Om hierdie proses te beheer, het ons 'n spesifieke stelling, PID, gebruik. PID is 'n beheerstelsel wat gebruik is om baie prosesse te beheer. PID staan vir 3 prosesse.

  • P- proporsioneel
  • Ek- integraal
  • D- afgeleide

Elke stelsel het insette en uitsette. Op dieselfde manier het hierdie beheerstelsel ook insette. In hierdie beheerstelsel is dit die afwyking van die stabiele toestand. Ons noem dit 'n fout. In ons robot is die fout die kantelhoek vanaf die vertikale vlak. As die robot gebalanseer is, is die kantelhoek nul. Die foutwaarde is dus nul. Die uitset van die PID -stelsel is dus nul. Hierdie stelsel bevat drie afsonderlike wiskundige prosesse.

Die eerste is die vermenigvuldigingsfout van numeriese versterking. Hierdie wins word gewoonlik Kp genoem

P = fout*Kp

Die tweede is om die integraal van die fout in die tyddomein te genereer en dit te vermenigvuldig met 'n mate van wins. Hierdie wins word Ki genoem

I = Integral (fout)*Ki

Die derde is die afgeleide van die fout in die tyddomein en vermenigvuldig dit met 'n mate van wins. Hierdie wins word Kd genoem

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

Nadat ons bogenoemde bewerkings bygevoeg het, kry ons ons finale uitset

UITGANG = P+I+D

As gevolg van die P -deel kan die robot 'n stabiele posisie kry, wat in verhouding is tot die afwyking. I deel bereken die oppervlakte van die fout teenoor die tydgrafiek. Dit probeer dus om die robot altyd akkuraat in 'n stabiele posisie te kry. D deel meet die helling in tyd vs fout grafiek. As die fout toeneem, is hierdie waarde positief. As die fout afneem, is hierdie waarde negatief. As gevolg hiervan, wanneer die robot na 'n stabiele posisie beweeg, sal die reaksiesnelheid verminder word, wat sal help om onnodige oorskiet te verwyder. U kan meer te wete kom oor die PID -teorie op die onderstaande skakel.

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

Die uitset van die PID-funksie is beperk tot die 0-255-reeks (8-bits PWM-resolusie) en dit sal na die motors as PWM-sein voorsien word.

Stap 3: hardeware -opstelling

Hardeware -opstelling
Hardeware -opstelling

Dit is nou 'n deel van die hardeware -opstelling. Die ontwerp van die robot hang van u af. As u die liggaam van die robot ontwerp het, moet u dit simmetries oor die vertikale as wat in die motoras lê, oorweeg. Die batterypak hieronder. Daarom is die robot maklik om te balanseer. In ons ontwerp maak ons die Magicbit -bord vertikaal vas aan die liggaam. Ons het twee 12V -ratmotors gebruik. Maar u kan enige soort ratmotors gebruik. Dit hang af van u robotafmetings.

As ons oor die stroombaan praat, word dit aangedryf deur 'n 7,4V Lipo -battery. Magicbit het 5V gebruik vir krag. Daarom het ons 'n 7805 -reguleerder gebruik om die batteryspanning na 5V te reguleer. In latere weergawes van Magicbit is die reguleerder nie nodig nie. Omdat dit tot 12 V. Ons lewer 7.4V direk vir motorbestuurders.

Verbind alle komponente volgens die diagram hieronder.

Stap 4: sagteware -opstelling

In die kode het ons die PID -biblioteek gebruik om die PID -uitset te bereken.

Gaan na die volgende skakel om dit af te laai.

www.arduinolibraries.info/libraries/pid

Laai die nuutste weergawe daarvan af.

Om beter sensorlesings te kry, het ons die DMP -biblioteek gebruik. DMP staan vir digitale bewegingsproses. Dit is 'n ingeboude kenmerk van MPU6050. Hierdie chip het 'n geïntegreerde bewegingsproses -eenheid. Dit verg dus lees en ontleed. Nadat dit geruislose akkurate uitsette na die mikrokontroleerder genereer (in hierdie geval Magicbit (ESP32)). Maar daar is baie werke aan die kant van die mikrobeheerder om die metings te neem en die hoek te bereken. So eenvoudig dat ons die MPU6050 DMP -biblioteek gebruik het. Laai dit af na die volgende skakel.

github.com/ElectronicCats/mpu6050

Om die biblioteke te installeer, gaan in die Arduino-kieslys na tools-> include library-> add.zip biblioteek en kies die biblioteeklêer wat u afgelaai het.

In die kode moet u die setpointhoek korrek verander. Die PID konstante waardes verskil van robot tot robot. Stel dit dus in, stel eers Ki en Kd waardes op nul en verhoog dan Kp totdat u 'n beter reaksiesnelheid kry. Meer Kp veroorsaak meer oorskiet. Verhoog dan die Kd -waarde. Verhoog dit altyd met 'n baie klein hoeveelheid. Hierdie waarde is oor die algemeen laag as ander waardes. Verhoog nou die Ki totdat u baie goeie stabiliteit het.

Kies die korrekte COM -poort en tik die. laai die kode op. Nou kan u met u selfdoenrobot speel.

Stap 5: Skema's

Skemas
Skemas

Stap 6: Kode

#insluit

#include "I2Cdev.h" #include "MPU6050_6Axis_MotionApps20.h" #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE #include "Wire.h" #endif MPU6050 mpu; bool dmpReady = vals; // stel waar as DMP init suksesvol was uint8_t mpuIntStatus; // hou die werklike onderbrekingsstatusbyte van MPU uint8_t devStatus; // terugkeerstatus na elke apparaatbewerking (0 = sukses,! 0 = fout) uint16_t packetSize; // verwagte DMP -pakkiegrootte (standaard is 42 grepe) uint16_t fifoCount; // telling van alle grepe wat tans in FIFO uint8_t fifoBuffer [64] is; // FIFO -stoorbuffer Quaternion q; // [w, x, y, z] quaternion houer VectorFloat swaartekrag; // [x, y, z] swaartekragvektor float ypr [3]; // [yaw, pitch, roll] yaw/pitch/roll container and gravity vector double originalSetpoint = 172.5; dubbele setpoint = originalSetpoint; dubbel movingAngleOffset = 0,1; dubbele invoer, uitset; int moveState = 0; dubbel Kp = 23; // stel P eerste dubbel Kd = 0,8; // hierdie waarde oor die algemeen klein dubbel Ki = 300; // hierdie waarde behoort hoog te wees vir beter stabiliteit PID pid (& invoer, & uitset, & setpoint, Kp, Ki, Kd, DIRECT); // pid initialiseer int motL1 = 26; // 4 penne vir motor drive int motL2 = 2; int motR1 = 27; int motR2 = 4; vlugtige bool mpuInterrupt = vals; // dui aan of MPU -onderbrekingspen hoog geraak het dmpDataReady () {mpuInterrupt = true; } ongeldige opstelling () {ledcSetup (0, 20000, 8); // pwm setup ledcSetup (1, 20000, 8); ledcSetup (2, 20000, 8); ledcSetup (3, 20000, 8); ledcAttachPin (motL1, 0); // pinmode van motors ledcAttachPin (motL2, 1); ledcAttachPin (motR1, 2); ledcAttachPin (motR2, 3); // sluit aan by I2C -bus (I2Cdev -biblioteek doen dit nie outomaties nie) #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE Wire.begin (); Wire.setClock (400000); // 400kHz I2C klok. Lewer kommentaar op hierdie reël as u probleme met die opstel het #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE Fastwire:: setup (400, true); #endif Serial.println (F ("Initialiseer I2C -toestelle …")); pinMode (14, INVOER); // initialiseer reekskommunikasie // (115200 gekies omdat dit nodig is vir Teapot Demo -uitvoer, maar dit is // afhangend van u projek) Serial.begin (9600); terwyl (! Serial); // wag vir Leonardo se opsomming, ander gaan onmiddellik voort // begin toestel Serial.println (F ("Initialiseer I2C -toestelle …")); mpu.initialize (); // verifieer verbinding Serial.println (F ("Toestelverbindings toets …")); Serial.println (mpu.testConnection ()? F ("MPU6050 verbinding suksesvol"): F ("MPU6050 verbinding misluk")); // laai en konfigureer die DMP Serial.println (F ("Initialiseer DMP …")); devStatus = mpu.dmpInitialize (); // verskaf u eie gyro -offset hier, afgeskaal vir min sensitiwiteit mpu.setXGyroOffset (220); mpu.setYGyroOffset (76); mpu.setZGyroOffset (-85); mpu.setZAccelOffset (1788); // 1688 fabrieksinstellings vir my toetsskyfie // maak seker dat dit gewerk het (gee 0 terug indien wel) as (devStatus == 0) {// die DMP aanskakel, noudat dit gereed is Serial.println (F ("DMP aktiveer … ")); mpu.setDMPEnabled (waar); // aktiveer Arduino onderbrekingsopsporing Serial.println (F ("Onderbreking opsporing moontlik maak (Arduino eksterne onderbreking 0) …")); attachInterrupt (14, dmpDataReady, RISING); mpuIntStatus = mpu.getIntStatus (); // stel ons DMP Ready -vlag in sodat die hooflus () -funksie weet dat dit goed is om dit te gebruik Serial.println (F ("DMP gereed! Wag vir eerste onderbreking …")); dmpReady = waar; // kry verwagte DMP -pakkiegrootte vir latere vergelyking packetSize = mpu.dmpGetFIFOPacketSize (); // opstel van PID pid. SetMode (AUTOMATIES); pid. SetSampleTime (10); pid. SetOutputLimits (-255, 255); } anders {// FOUT! // 1 = aanvanklike geheue laai misluk // 2 = DMP -konfigurasie -opdaterings misluk // (as dit gaan breek, sal die kode gewoonlik 1 wees) Serial.print (F ("DMP -inisialisering misluk (kode")); Serial. print (devStatus); Serial.println (F (")"))); }} void loop () {// as programmering misluk, probeer niks doen as (! dmpReady) terugkeer; // wag vir MPU -onderbreking of ekstra pakkie (s) beskikbaar terwyl (! mpuInterrupt && fifoCount <packetSize) {pid. Compute (); // hierdie tydperk gebruik word om data te laai, sodat u dit kan gebruik vir ander berekeninge motorSpeed (uitset); } // herstel interrupt -vlag en kry INT_STATUS -byte mpuInterrupt = false; mpuIntStatus = mpu.getIntStatus (); // kry die huidige FIFO -telling fifoCount = mpu.getFIFOCount (); // kyk vir oorloop (dit moet nooit gebeur nie, tensy ons kode te ondoeltreffend is) as ((mpuIntStatus & 0x10) || fifoCount == 1024) {// herstel sodat ons skoon kan voortgaan met mpu.resetFIFO (); Serial.println (F ("FIFO -oorloop!")); // kyk anders of DMP -data gereed is om te onderbreek (dit moet gereeld gebeur)} anders as (mpuIntStatus & 0x02) {// wag vir die korrekte beskikbare datalengte, 'n BAIE kort wag moet wag terwyl (fifoCount 1 pakkie beskikbaar // (hierdie laat ons onmiddellik meer lees sonder om op 'n onderbreking te wag) 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 hoeke 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; as (PWM> = 0) {// voorwaartse rigting L2 = 0; L1 = abs (PWM); R2 = 0; R1 = abs (PWM); as (L1> = 255) { L1 = R1 = 255;}} anders {// agteruit rigting L1 = 0; L2 = abs (PWM); R1 = 0; R2 = abs (PWM); as (L2> = 255) {L2 = R2 = 255; }} // motor drive ledcWrite (0, L1); ledcWrite (1, L2); ledcWrite (2, R1*0.97); // 0.97 is spoedfeit of omdat die regtermotor 'n hoë snelheid het as die linkermotor, verminder ons dit totdat die motorsnelheid gelyk is aan ledcWrite (3, R2*0.97);

}

Aanbeveel: