Sisällysluettelo:

Itsetasapainottava robotti Magicbitista: 6 vaihetta
Itsetasapainottava robotti Magicbitista: 6 vaihetta

Video: Itsetasapainottava robotti Magicbitista: 6 vaihetta

Video: Itsetasapainottava robotti Magicbitista: 6 vaihetta
Video: Makeblock Untimate Robot Kit Part 1 : Step by Step Assembly Robot of Aram Tank 2024, Heinäkuu
Anonim

Tämä opetusohjelma näyttää kuinka tehdä itsetasapainottava robotti Magicbit -kehityskortin avulla. Käytämme magicbitia kehityskorttina tässä projektissa, joka perustuu ESP32: een. Siksi mitä tahansa ESP32 -kehityskorttia voidaan käyttää tässä projektissa.

Tarvikkeet:

  • magicbit
  • Kahden H-sillan L298-moottorin kuljettaja
  • Lineaarinen säädin (7805)
  • Lipo 7.4V 700mah akku
  • Inertiaalinen mittausyksikkö (IMU) (6 astetta vapautta)
  • vaihdemoottorit 3V-6V DC

Vaihe 1: Tarina

Tarina
Tarina
Tarina
Tarina

Hei kaverit, tänään tässä opetusohjelmassa opimme vähän monimutkaisesta asiasta. Kyse on itsetasapainottavasta robotista, joka käyttää Magicbitia Arduino IDE: n kanssa. Aloitetaan siis.

Ensin katsotaan, mikä on itsetasapainottava robotti. Itsetasapainottava robotti on kaksipyöräinen robotti. Erityispiirre on, että robotti voi tasapainottaa itsensä ilman ulkoista tukea. Kun virta on päällä, robotti nousee seisomaan ja tasapainottuu jatkuvasti värähtelyliikkeillä. Joten sinulla on nyt karkea käsitys itsetasapainottavasta robotista.

Vaihe 2: Teoria ja metodologia

Teoria ja metodologia
Teoria ja metodologia

Robotin tasapainottamiseksi saamme ensin tietoja jostakin anturista mittaamaan robotin kulman pystytasoon. Tätä tarkoitusta varten käytimme MPU6050. Kun olemme saaneet tiedot anturista, laskemme kallistuksen pystytasoon. Jos robotti on suorassa ja tasapainossa, kallistuskulma on nolla. Jos ei, kallistuskulma on positiivinen tai negatiivinen arvo. Jos robotti on kallistettu etupuolelle, sen on siirryttävä etusuuntaan. Myös jos robotti on kallistettu peruutuspuolelle, robotin on siirryttävä vastakkaiseen suuntaan. Jos tämä kallistuskulma on suuri, vasteen tulee olla suuri. Päinvastoin, kallistuskulma on pieni, reaktionopeuden on oltava alhainen. Tämän prosessin hallitsemiseksi käytimme erityistä teoriaa nimeltä PID. PID on ohjausjärjestelmä, jota käytettiin monien prosessien ohjaamiseen. PID tarkoittaa 3 prosessia.

  • P- suhteellinen
  • I- kiinteä
  • D- johdannainen

Jokaisessa järjestelmässä on tulo ja lähtö. Samalla tavalla tässä ohjausjärjestelmässä on myös jonkin verran tuloa. Tässä ohjausjärjestelmässä se on poikkeama vakaasta tilasta. Kutsuimme sitä virheeksi. Robotissamme virhe on kallistuskulma pystytasosta. Jos robotti on tasapainossa, kallistuskulma on nolla. Virhearvo on siis nolla. PID -järjestelmän lähtö on siis nolla. Tämä järjestelmä sisältää kolme erillistä matemaattista prosessia.

Ensimmäinen on kertovirhe numerovahvistuksesta. Tätä voittoa kutsutaan yleensä nimellä Kp

P = virhe*Kp

Toinen on generoida virheen integraali aika -alueella ja kertoa se osasta vahvistusta. Tätä voittoa kutsutaan nimellä Ki

I = integraali (virhe)*Ki

Kolmas on johdannainen aika -alueen virheestä ja kerrotaan se jollakin voitolla. Tätä voittoa kutsutaan Kd: ksi

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

Edellä olevien toimintojen lisäämisen jälkeen saamme lopullisen tuloksen

LÄHTÖ = P+I+D

P -osan ansiosta robotti voi saada vakaan asennon, joka on verrannollinen poikkeamaan. I osa laskee virhealueen ja aikakaavion. Joten se yrittää saada robotin vakaaseen asentoon aina tarkasti. D -osa mittaa kaltevuuden ajassa vs. virhekaavio. Jos virhe kasvaa, tämä arvo on positiivinen. Jos virhe pienenee, tämä arvo on negatiivinen. Tämän vuoksi, kun robotti siirretään vakaaseen asentoon, reaktionopeus laskee ja tämä auttaa poistamaan tarpeettomat ylitykset. Voit oppia lisää PID -teoriasta tästä alla olevasta linkistä.

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

PID-toiminnon lähtö on rajoitettu alueelle 0-255 (8-bittinen PWM-tarkkuus) ja se syöttää moottoreille PWM-signaalia.

Vaihe 3: Laitteiston asennus

Laitteiston asennus
Laitteiston asennus

Tämä on nyt laitteiston asennusosa. Robotin suunnittelu riippuu sinusta. Kun suunnittelet robotin runkoa, sinun on otettava huomioon sen symmetrisyys moottorin akselilla olevan pystysuoran akselin suhteen. Akku sijaitsee alla. Siksi robotti on helppo tasapainottaa. Suunnittelussamme kiinnitämme Magicbit -levyn pystysuoraan runkoon. Käytimme kahta 12 V: n vaihteistomoottoria. Mutta voit käyttää mitä tahansa vaihteistomoottoreita. se riippuu robotin mitoista.

Kun keskustelemme piiristä, se saa virtaa 7,4 V: n Lipo -akusta. Magicbit käytti virtalähteenä 5V. Siksi käytimme 7805 -säädintä akun jännitteen säätämiseen 5 V. Magicbitin myöhemmissä versioissa tätä säädintä ei tarvita. Koska se saa virtaa jopa 12V. Toimitamme suoraan 7.4V moottorin kuljettajalle.

Liitä kaikki komponentit alla olevan kaavion mukaisesti.

Vaihe 4: Ohjelmiston asennus

Koodissa käytimme PID -kirjastoa PID -lähdön laskemiseen.

Siirry seuraavaan linkkiin ladataksesi sen.

www.arduinolibraries.info/libraries/pid

Lataa sen uusin versio.

Parantaaksemme anturilukemia käytimme DMP -kirjastoa. DMP tarkoittaa digitaalista liikeprosessia. Tämä on MPU6050: n sisäänrakennettu ominaisuus. Tässä sirussa on integroitu liikeprosessiyksikkö. Se vaatii siis lukemista ja analysointia. Sen jälkeen se tuottaa äänettömiä tarkkoja lähtöä mikro -ohjaimeen (tässä tapauksessa Magicbit (ESP32)). Mutta mikrokontrollerin puolella on paljon töitä lukemien ottamiseksi ja kulman laskemiseksi. Joten yksinkertaisesti käytimme MPU6050 DMP -kirjastoa. Lataa se goint -linkistä.

github.com/ElectronicCats/mpu6050

Asenna kirjastot valitsemalla Arduino-valikosta työkalut-> sisälly kirjasto-> add.zip-kirjasto ja valitsemalla lataamasi kirjastotiedosto.

Koodissa sinun on muutettava asetuspisteen kulma oikein. PID -vakioarvot vaihtelevat robotista toiseen. Joten virittäessäsi, aseta ensin Ki- ja Kd -arvot nollaksi ja lisää sitten Kp, kunnes saat paremman reaktionopeuden. Lisää Kp aiheuttaa enemmän ylityksiä. Lisää sitten Kd -arvoa. Lisää sitä aina hyvin pienellä määrällä. Tämä arvo on yleensä alhainen kuin muut arvot. Lisää nyt Ki -arvoa, kunnes vakaus on erittäin hyvä.

Valitse oikea COM -portti ja kortin tyyppi. lataa koodi. Nyt voit pelata DIY -robotillasi.

Vaihe 5: Kaaviot

Kaaviot
Kaaviot

Vaihe 6: Koodi

#sisältää

#include "I2Cdev.h" #include "MPU6050_6Axis_MotionApps20.h" #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE #include "Wire.h" #endif MPU6050 mpu; bool dmpReady = epätosi; // aseta tosi, jos DMP -aloitus onnistui uint8_t mpuIntStatus; // omistaa todellisen keskeytystilan tavun MPU: sta uint8_t devStatus; // palautustila jokaisen laitteen käytön jälkeen (0 = onnistunut,! 0 = virhe) uint16_t packetSize; // odotettu DMP -paketin koko (oletus on 42 tavua) uint16_t fifoCount; // kaikkien tällä hetkellä FIFO: ssa olevien tavujen määrä uint8_t fifoBuffer [64]; // FIFO -tallennuspuskuri Quaternion q; // [w, x, y, z] kvaternionisäiliö VectorFloat gravity; // [x, y, z] painovoimavektori float ypr [3]; // [kääntö, nousu, rulla] kääntö/nousu/rullaussäiliö ja painovoimavektori double originalSetpoint = 172,5; kaksinkertainen asetuspiste = originalSetpoint; kaksinkertainen liikkuminenAngleOffset = 0,1; kaksinkertainen tulo, lähtö; int moveState = 0; double Kp = 23; // aseta P ensimmäinen kaksinkertainen Kd = 0,8; // tämän arvon yleensä pieni kaksinkertainen Ki = 300; // tämän arvon pitäisi olla korkea paremman vakauden saavuttamiseksi PID pid (& input, & output, & setpoint, Kp, Ki, Kd, DIRECT); // pid alustaminen int motL1 = 26; // 4 nastaa moottorikäytölle int motL2 = 2; int motR1 = 27; int motR2 = 4; haihtuva bool mpuInterrupt = false; // osoittaa, onko MPU -keskeytysnasta mennyt korkeaksi 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); // moottorien pinmode ledcAttachPin (motL2, 1); ledcAttachPin (motR1, 2); ledcAttachPin (motR2, 3); // liittyä I2C -väylään (I2Cdev -kirjasto ei tee tätä automaattisesti) #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE Wire.begin (); Wire.setClock (400000); // 400 kHz I2C -kello. Kommentoi tätä riviä, jos sinulla on kokoamisvaikeuksia #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE Fastwire:: setup (400, true); #endif Serial.println (F ("I2C -laitteiden alustaminen…")); pinMode (14, TULO); // sarjakommunikoinnin alustaminen // (115200 valittu, koska se vaaditaan Teekannu -demoulostulolle, mutta se // riippuu todella projektistasi riippuen) Serial.begin (9600); while (! Sarja); // odota Leonardo -luetteloa, muut jatkavat heti // alustavat laitteen Serial.println (F ("I2C -laitteiden alustaminen…")); mpu.initialize (); // Tarkista yhteys Serial.println (F ("Laitteen yhteyksien testaus …")); Serial.println (mpu.testConnection ()? F ("MPU6050 -yhteys onnistui"): F ("MPU6050 -yhteys epäonnistui")); // lataa ja konfiguroi DMP Serial.println (F ("DMP: n alustaminen …")); devStatus = mpu.dmpInitialize (); // syötä tänne omat gyroskooppisiirrot, skaalattuna min. herkkyyden mukaan mpu.setXGyroOffset (220); mpu.setYGyroOffset (76); mpu.setZGyroOffset (-85); mpu.setZAccelOffset (1788); // testisirun tehdasasetus 1688 // varmista, että se toimi (palauttaa 0, jos näin on), jos (devStatus == 0) {// kytke DMP päälle, kun se on valmis Serial.println (F ("DMP: n käyttöönotto… ")); mpu.setDMPEnabled (tosi); // ota käyttöön Arduinon keskeytyksen tunnistus Serial.println (F ("Keskeytyksen havaitsemisen salliminen (Arduinon ulkoinen keskeytys 0)…")); attachInterrupt (14, dmpDataReady, RISING); mpuIntStatus = mpu.getIntStatus (); // aseta DMP Ready -lippumme niin, että pääsilmukka () -funktio tietää, että sen käyttö on okei Serial.println (F ("DMP valmis! Odotetaan ensimmäistä keskeytystä …")); dmpReady = totta; // saat odotetun DMP -paketin koon myöhempää vertailua varten packetSize = mpu.dmpGetFIFOPacketSize (); // setup PID pid. SetMode (AUTOMATIC); pid. SetSampleTime (10); pid. SetOutputLimits (-255, 255); } muu {// VIRHE! // 1 = alustava muistin lataus epäonnistui // 2 = DMP -kokoonpanopäivitykset epäonnistui // (jos se katkeaa, koodi on yleensä 1) Serial.print (F ("DMP -alustus epäonnistui (koodi")); Sarja. print (devStatus); Serial.println (F (")")); }} void loop () {// jos ohjelmointi epäonnistui, älä yritä tehdä mitään, jos (! dmpReady) palaa; // odota MPU -keskeytystä tai lisäpaketteja, kun (! mpuInterrupt && fifoCount <packetSize) {pid. Compute (); // tätä ajanjaksoa käytetään tietojen lataamiseen, joten voit käyttää tätä muihin laskelmiin motorSpeed (lähtö); } // nollaa keskeytyslippu ja hanki INT_STATUS -tavu mpuInterrupt = false; mpuIntStatus = mpu.getIntStatus (); // hanki nykyinen FIFO -lukumäärä fifoCount = mpu.getFIFOCount (); // tarkista ylivuoto (tämän ei pitäisi koskaan tapahtua, ellei koodimme ole liian tehoton) if ((mpuIntStatus & 0x10) || fifoCount == 1024) {// nollaa, jotta voimme jatkaa puhtaasti mpu.resetFIFO (); Serial.println (F ("FIFO -ylivuoto!")); // muussa tapauksessa tarkista, onko DMP -tiedot valmiina keskeytykseen (tämän pitäisi tapahtua usein)} else if (mpuIntStatus & 0x02) {// odota oikeaa käytettävissä olevaa datapituutta, odotetaan ERITTÄIN lyhyesti, kun (fifoCount 1 -paketti saatavilla // (tämä voimme lukea heti lisää odottamatta keskeytystä) fifoCount -= packetSize; mpu.dmpGetQuaternion (& q, fifoBuffer); mpu.dmpGetGravity (& gravity, & q); mpu.dmpGetYawPitchRoll (ypr, & q, & gravity); #if Lial_ print ("ypr / t"); Serial.print (ypr [0] * 180/M_PI); // euler -kulmat 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; jos (PWM> = 0) {// eteenpäin suunta L2 = 0; L1 = abs (PWM); R2 = 0; R1 = abs (PWM); jos (L1> = 255) { L1 = R1 = 255;}} else {// taaksepäin suunta L1 = 0; L2 = abs (PWM); R1 = 0; R2 = abs (PWM); jos (L2> = 255) {L2 = R2 = 255; }} // moottorikäyttö ledcWrite (0, L1); ledcWrite (1, L2); ledcWrite (2, R1*0,97); // 0,97 on nopeustieto tai koska oikean moottorin nopeus on suurempi kuin vasemman moottorin, niin pienennämme sitä, kunnes moottorin nopeudet ovat samat ledcWrite (3, R2*0,97);

}

Suositeltava: