Isi kandungan:

Robot Mengimbangkan Diri Dari Magicbit: 6 Langkah
Robot Mengimbangkan Diri Dari Magicbit: 6 Langkah

Video: Robot Mengimbangkan Diri Dari Magicbit: 6 Langkah

Video: Robot Mengimbangkan Diri Dari Magicbit: 6 Langkah
Video: MULTISUB《万古剑尊》第1-60集🔥剑之巅、傲世间!白袍少帅叶无道觉醒古帝印记,以剑入道,只手横推三千界,万剑镇压百万师,笑傲神佛仙,谁敢一战? #穿越 #逆袭 #爽文 2024, Julai
Anonim

Tutorial ini menunjukkan cara membuat robot pengimbang diri menggunakan papan pemikir Magicbit. Kami menggunakan magicbit sebagai papan pengembangan dalam projek ini yang berdasarkan ESP32. Oleh itu, papan pengembangan ESP32 boleh digunakan dalam projek ini.

Bekalan:

  • magicbit
  • Pemandu motor D-H-bridge L298
  • Pengatur Linear (7805)
  • Bateri Lipo 7.4V 700mah
  • Unit Pengukuran Inersia (IMU) (6 darjah kebebasan)
  • motor gear 3V-6V DC

Langkah 1: Cerita

Cerita
Cerita
Cerita
Cerita

Hai kawan-kawan, hari ini dalam tutorial ini kita akan belajar mengenai perkara yang sedikit rumit. Iaitu mengenai robot mengimbangkan diri menggunakan Magicbit dengan Arduino IDE. Oleh itu, mari kita mulakan.

Pertama sekali, mari kita lihat apa itu robot pengimbangan diri. Robot pengimbang diri adalah robot roda dua. Ciri khasnya ialah robot dapat mengimbangkan dirinya tanpa menggunakan sokongan luaran. Apabila kuasa dihidupkan robot akan berdiri dan kemudian diimbangi secara berterusan dengan menggunakan pergerakan ayunan. Jadi sekarang anda semua mempunyai idea kasar mengenai robot pengimbang diri.

Langkah 2: Teori dan Metodologi

Teori dan Metodologi
Teori dan Metodologi

Untuk mengimbangi robot, pertama kita mendapatkan data dari beberapa sensor untuk mengukur sudut robot ke satah menegak. Untuk tujuan itu kami menggunakan MPU6050. Setelah mendapatkan data dari sensor kami mengira kecondongan ke satah menegak. Sekiranya robot pada kedudukan lurus dan seimbang, maka sudut kecondongan adalah sifar. Sekiranya tidak, maka sudut kecondongan adalah nilai positif atau negatif. Sekiranya robot condong ke arah depan, maka robot harus bergerak ke arah depan. Juga jika robot condong ke arah belakang maka robot harus bergerak ke arah terbalik. Sekiranya sudut kecondongan ini tinggi maka kelajuan tindak balas mestilah tinggi. Sebaliknya sudut kecondongan rendah maka kelajuan tindak balas mestilah rendah. Untuk mengawal proses ini, kami menggunakan teorema khusus yang disebut PID. PID adalah sistem kawalan yang digunakan untuk mengendalikan banyak proses. PID bermaksud 3 proses.

  • P- berkadar
  • I- integral
  • D- terbitan

Setiap sistem mempunyai input dan output. Dengan cara yang sama sistem kawalan ini juga mempunyai beberapa input. Dalam sistem kawalan ini adalah penyimpangan dari keadaan stabil. Kami menyebutnya sebagai kesalahan. Dalam robot kami, kesalahan adalah sudut kecondongan dari satah menegak. Sekiranya robot seimbang maka sudut kecondongan adalah sifar. Jadi nilai ralat akan menjadi sifar. Oleh itu output sistem PID adalah sifar. Sistem ini merangkumi tiga proses matematik yang berasingan.

Yang pertama adalah darab ralat dari keuntungan berangka. Keuntungan ini biasanya disebut sebagai Kp

P = ralat * Kp

Yang kedua adalah menghasilkan kamiran kesalahan dalam domain masa dan mengalikannya dari beberapa keuntungan. Keuntungan ini disebut sebagai Ki

I = Integral (ralat) * Ki

Yang ketiga adalah turunan dari ralat dalam domain waktu dan kalikannya dengan sejumlah keuntungan. Keuntungan ini disebut sebagai Kd

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

Setelah menambah operasi di atas, kami mendapat hasil akhir kami

OUTPUT = P + I + D

Kerana robot bahagian P dapat memperoleh kedudukan stabil yang sebanding dengan penyimpangan. Saya mengira bahagian ralat vs graf masa. Oleh itu, ia berusaha menjadikan robot ke kedudukan stabil dengan tepat. Bahagian D mengukur cerun dalam masa vs graf ralat. Sekiranya kesalahan meningkat, nilai ini adalah positif. Sekiranya ralat menurun nilai ini adalah negatif. Oleh kerana itu, apabila robot bergerak ke posisi stabil maka kecepatan tindak balas akan berkurang dan ini akan membantu menghilangkan kelebihan yang tidak perlu. Anda boleh mengetahui lebih lanjut mengenai teori PID dari pautan ini seperti di bawah.

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

Output fungsi PID adalah had 0-255 (resolusi PWM 8 bit) dan akan memberi makan kepada motor sebagai isyarat PWM.

Langkah 3: Persediaan Perkakasan

Persediaan Perkakasan
Persediaan Perkakasan

Sekarang ini adalah bahagian persediaan perkakasan. Reka bentuk robot bergantung pada anda. Semasa anda merancang badan robot, anda harus mempertimbangkannya secara simetri mengenai paksi menegak yang terletak pada paksi motor. Pek bateri terletak di bawah. Oleh itu robot itu mudah diimbangkan. Dalam reka bentuk kami membetulkan papan Magicbit secara menegak ke badan. Kami menggunakan dua motor gear 12V. Tetapi anda boleh menggunakan apa-apa jenis motor gear. itu bergantung pada dimensi robot anda.

Apabila kita membincangkan mengenai litar, ia dikuasakan oleh bateri 7.4V Lipo. Magicbit menggunakan 5V untuk memberi kuasa. Oleh itu, kami menggunakan pengatur 7805 untuk mengatur voltan bateri hingga 5V. Dalam versi Magicbit kemudian, pengatur itu tidak diperlukan. Kerana ia berkuasa sehingga 12V. Kami membekalkan secara langsung 7.4V untuk pemandu motor.

Sambungkan semua komponen mengikut rajah di bawah.

Langkah 4: Persediaan Perisian

Dalam kod kami menggunakan perpustakaan PID untuk mengira output PID.

Pergi ke pautan berikut untuk memuat turunnya.

www.arduinolibraries.info/libraries/pid

Muat turun versi terkini daripadanya.

Untuk mendapatkan bacaan sensor yang lebih baik, kami menggunakan pustaka DMP. DMP bermaksud proses gerakan digital. Ini adalah ciri dalaman MPU6050. Cip ini mempunyai unit proses gerakan bersepadu. Oleh itu, ia memerlukan pembacaan dan analisis. Setelah menghasilkan output tepat yang tidak bersuara ke mikrokontroler (dalam kes ini Magicbit (ESP32)). Tetapi terdapat banyak kerja di sisi mikrokontroler untuk mengambil bacaan dan mengira sudut. Oleh itu, kami menggunakan pustaka DMP MPU6050. Muat turun melalui pautan berikut.

github.com/ElectronicCats/mpu6050

Untuk memasang perpustakaan, dalam menu Arduino pergi ke alat-> sertakan perpustakaan-> perpustakaan add.zip dan pilih fail perpustakaan yang anda muat turun.

Dalam kod anda mesti menukar sudut setpoint dengan betul. Nilai pemalar PID berbeza dari robot ke robot. Oleh itu, tetapkan dulu nilai Ki dan Kd sifar dan kemudian tingkatkan Kp sehingga anda mendapat kelajuan reaksi yang lebih baik. Lebih banyak penyebab Kp untuk lebih banyak kelebihan. Kemudian tingkatkan nilai Kd. Tingkatkan dengan selalu dalam jumlah yang sangat sedikit. Nilai ini pada amnya rendah daripada nilai lain. Sekarang tingkatkan Ki sehingga anda mempunyai kestabilan yang sangat baik.

Pilih port COM dan papan jenis yang betul. muat naik kod. Sekarang anda boleh bermain dengan robot DIY anda.

Langkah 5: Skematik

Skematik
Skematik

Langkah 6: Kod

#sertakan

#include "I2Cdev.h" #include "MPU6050_6Axis_MotionApps20.h" #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE #include "Wire.h" #endif MPU6050 mpu; bool dmpReady = salah; // tetapkan benar sekiranya DMP init berjaya uint8_t mpuIntStatus; // memegang byte status gangguan sebenar dari MPU uint8_t devStatus; // kembali status selepas setiap operasi peranti (0 = berjaya,! 0 = ralat) uint16_t packetSize; // ukuran paket DMP yang dijangkakan (lalai adalah 42 bait) uint16_t fifoCount; // kiraan semua bait yang ada di FIFO uint8_t fifoBuffer [64]; // Penyangga simpanan FIFO Quaternion q; // [w, x, y, z] bekas kuarter VectorVloat graviti; // [x, y, z] pelampung vektor graviti ypr [3]; // [yaw, pitch, roll] yaw / pitch / roll container and gravity vector double originalSetpoint = 172.5; setpoint berganda = originalSetpoint; double movingAngleOffset = 0.1; input berganda, output; int moveState = 0; double Kp = 23; // tetapkan P double pertama Kd = 0.8; // nilai ini umumnya ganda ganda Ki = 300; // nilai ini harus tinggi untuk kestabilan yang lebih baik PID pid (& input, & output, & setpoint, Kp, Ki, Kd, LANGSUNG); // pid inisialisasi int motL1 = 26; // 4 pin untuk pemacu motor int motL2 = 2; int motR1 = 27; int motR2 = 4; bool tidak menentu mpuInterrupt = false; // menunjukkan sama ada pin interupsi MPU telah hilang tinggi dmpDataReady () {mpuInterrupt = true; } sia-sia persediaan () {ledcSetup (0, 20000, 8); // pwm setup ledcSetup (1, 20000, 8); ledcSetup (2, 20000, 8); ledcSetup (3, 20000, 8); ledcAttachPin (motL1, 0); // pinmode motor ledcAttachPin (motL2, 1); ledcAttachPin (motR1, 2); ledcAttachPin (motR2, 3); // sertai bas I2C (perpustakaan I2Cdev tidak melakukan ini secara automatik) #jika I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE Wire.begin (); Wire.setClock (400000); // Jam 400kHz I2C. Komen baris ini jika menghadapi kesukaran penyusunan #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE Fastwire:: setup (400, true); #endif Serial.println (F ("Memulakan peranti I2C …")); pinMode (14, INPUT); // memulakan komunikasi bersiri // (115200 dipilih kerana diperlukan untuk output Demo Teapot, tetapi // benar-benar terserah kepada anda bergantung pada projek anda) Serial.begin (9600); sementara (! bersiri); // tunggu penghitungan Leonardo, yang lain terus segera // memulakan peranti Serial.println (F ("Memulakan peranti I2C …")); mpu.initialize (); // sahkan sambungan Serial.println (F ("Menguji sambungan peranti …")); Serial.println (mpu.testConnection ()? F ("Sambungan MPU6050 berjaya"): F ("Sambungan MPU6050 gagal")); // muat dan konfigurasikan DMP Serial.println (F ("Memulakan DMP …")); devStatus = mpu.dmpInitialize (); // sediakan offset gyro anda sendiri di sini, disesuaikan dengan kepekaan min mpu.setXGyroOffset (220); mpu.setYGyroOffset (76); mpu.setZGyroOffset (-85); mpu.setZAccelOffset (1788); // 1688 lalai kilang untuk cip ujian saya // pastikan ia berfungsi (mengembalikan 0 jika ya) jika (devStatus == 0) {// hidupkan DMP, sekarang sudah siap Serial.println (F ("Mengaktifkan DMP… ")); mpu.setDMPEnabled (benar); // aktifkan pengesanan gangguan Arduino Serial.println (F ("Mengaktifkan pengesanan gangguan (gangguan luaran Arduino 0) …")); attachInterrupt (14, dmpDataReady, RISING); mpuIntStatus = mpu.getIntStatus (); // tetapkan bendera DMP Sedia kami supaya fungsi gelung utama () tahu tidak mengapa menggunakannya Serial.println (F ("DMP siap! Menunggu gangguan pertama …")); dmpReady = benar; // dapatkan ukuran paket DMP yang diharapkan untuk perbandingan paket kemudianSize = mpu.dmpGetFIFOPacketSize (); // persediaan PID pid. SetMode (AUTOMATIK); pid. SetSampleTime (10); pid. SetOutputLimits (-255, 255); } lain {// KESALAHAN! // 1 = muatan memori awal gagal // 2 = Kemas kini konfigurasi DMP gagal // (jika akan rosak, biasanya kodnya akan menjadi 1) Serial.print (F ("Permulaan DMP gagal (kod")); Serial. cetak (devStatus); Serial.println (F (")")); }} gelung void () {// jika pengaturcaraan gagal, jangan cuba melakukan apa-apa sekiranya (! dmpReady) kembali; // tunggu MPU terganggu atau paket tambahan tersedia semasa (! mpuInterrupt && fifoCount <packetSize) {pid. Compute (); // jangka masa ini digunakan untuk memuatkan data, jadi anda boleh menggunakannya untuk pengiraan lain motorSpeed (pengeluaran); } // tetapkan semula bendera gangguan dan dapatkan INT_STATUS bait mpuInterrupt = false; mpuIntStatus = mpu.getIntStatus (); // dapatkan jumlah FIFO saat ini fifoCount = mpu.getFIFOCount (); // periksa limpahan (ini tidak akan pernah berlaku kecuali kod kami terlalu tidak cekap) jika ((mpuIntStatus & 0x10) || fifoCount == 1024) {// tetapkan semula supaya kami dapat meneruskan mpu.resetFIFO (); Serial.println (F ("Limpahan FIFO!")); // jika tidak, periksa apakah data DMP siap terganggu (ini mesti kerap berlaku)} jika tidak (mpuIntStatus & 0x02) {// tunggu panjang data yang betul, harus menunggu SANGAT pendek sementara (paket fifoCount 1 tersedia // (ini mari kita segera membaca lebih lanjut tanpa menunggu gangguan) fifoCount - = packetSize; mpu.dmpGetQuaternion (& q, fifoBuffer); mpu.dmpGetGravity (& gravity, & q); mpu.dmpGetYawPitchRoll (ypr, & q, & gravity); #if LOG_INPUT Serial cetak ("ypr / t"); Serial.print (ypr [0] * 180 / M_PI); // euler sudut 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;}} batal motor Speed (int PWM) {float L1, L2, R1, R2; if (PWM> = 0) {// arah hadapan L2 = 0; L1 = abs (PWM); R2 = 0; R1 = abs (PWM); jika (L1> = 255) { L1 = R1 = 255;}} lain {// arah belakang L1 = 0; L2 = abs (PWM); R1 = 0; R2 = abs (PWM); jika (L2> = 255) {L2 = R2 = 255; }} // pemacu motor ledcWrite (0, L1); ledcWrite (1, L2); ledcWrite (2, R1 * 0.97); // 0.97 adalah fakta kelajuan atau, kerana motor kanan mempunyai kelajuan tinggi daripada motor kiri, jadi kami mengurangkannya sehingga kelajuan motor sama dengan ledcWrite (3, R2 * 0.97);

}

Disyorkan: