Arduino Denge Robotu-Kaykay
Arduino denge robotum iki teker üzerinde mpu 6050 sensörü sayesinde dengede durur.Devrilmemek için ileri geri giderek kendini dengeye alır.
Bu projemde denge robotumu sizlere tanıtıp nasıl yapıldığını adım adım anlatmak istiyorum arkadaşlar.
- Arduino Uno
- L298N Motor Sürücü Kartı
- Mpu 6050 6 eksen Gyro-İvmeölçer
- 8X15 cm 2 adet Mekanik için pleksi levha
- 2 Adet motor ve tekerlekleri
- 9v pil
- 4 adet 1.5 voltluk pil
- iki anahtar
- 4 adet 4 cm boyunda vida
- 10 adet 1.5 cm boyunda vida
- somun ve pul
İlk olarak robotumuzun gövdesini oluşturarak işe başlayalım arkadaşlar.Şunu her zaman dikkate almalıyız ki oda tabikide gövdeyi yaparken malzemeleri gelişi güzel değilde orantılı ve elimizden geldiği kadar dengeli yerleştirmeliyiz ki robotumuz tam verimde çalışsın.
2 adet levhayı üst üste koyarak 4 köşesinden delik açıyoruz.Gövde 2 katlı olacağı için vidalar sayesinde birbirlerine bağlayacağız.Delik lerin genişliği alacağınız vidaya göre farklı olabilir bunu siz ayarlarsınız artık.
Delik açma işleminden sonra levhaların ortası bulunur.
Foto da göründüğü üzere 8X15 cm lik levhanın ortasından yani 4 cm den çizgi ile ayıralım.Motorları dik bir şekide levhaya takıyoruz sağlam olması için silikon ile birleştirmesini sağlıyoruz.
Üst kısma gelecek olan levhanın motor geleceği yerleri kesiyoruz.
Vidalarını da takarak gövdemizi aşağıdaki fotoğraftaki gibi yapıyoruz arkadaşlar.
Motorumuzun Gövdesi Bu şekilde son buluyor sıra geldi gövde üzerine kartları yerleştirmeye.
İlk önce uno ve MPU6020 ivme sensörünü alt bölüme takalı.Bunun için küçük vidaları kullanacağız.Kartı ve sensörü levha üzerine koyarak delik açacağımız yerleri işaretleyelim.Ve vidalarını pullarıda kullanarak takalım.
Yerlerini hazırladığımız arduino uno ve sensörü levhaya takalım.Arduino unonun gerilimi için soket kullanmak yerine direkt altından lehim yaparak kablo çektim.Arduino yu takmadan önce bu bağlantıyı yapalım.Siyah Soket girişi olan yerin alt kısmında + ve – kablosunu çekin.Ve malzemeleri yerlerine takın.
Sıra geldi üst kısma.Üst kısımda ise motor sürücü kartı ve piller olacak.En uygunu Bu Dizayndı arkadaşlar bi kaç deneme yaptım ama hiç tat almadım en uygunu bu şekilde oldu.Aynı şekilde motor sürücü için vida yerleri açalım.Ve ön tarafa 2 adet anahtar koyalım.
Pil yerlerimizde ortaya çıktı.4 adet pilin uçları anahtar yardımı ile motor sürücünün vcc pinine,9 voltluk pilin uçları diğer anahtar yardımı ile uno nun altından aldığımız uçlara gidecek.GÖvde ve Malzeme yerleştirmesi bitti şimdi sırada bağlantılarını yapma var.Devre şemasında göründüğü gibi bağlantılarınızı yapınız.
#include <PID_v1.h> #include <LMotorController.h> #include "I2Cdev.h" #include "MPU6050_6Axis_MotionApps20.h" #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE #include "Wire.h" #endif #define LOG_INPUT 0 #define MANUAL_TUNING 0 #define LOG_PID_CONSTANTS 0 #define MOVE_BACK_FORTH 0 #define MIN_ABS_SPEED 30 // Minumum Başlangıç Hızı //MPU MPU6050 mpu; // MPU control/status vars bool dmpReady = false; //DMP init başarılı olmuşsa doğru olarak ayarlayın. uint8_t mpuIntStatus; // MPU'dan gerçek kesme durumu baytı tutar uint8_t devStatus; // Her cihaz çalışmasından sonra dönüş durumu (0 = başarı,! 0 = hata) (0 = success, !0 = error) uint16_t packetSize; // Beklenen DMP paket boyutu (varsayılan 42 bayt) uint16_t fifoCount; // Şu anda FIFO'daki tüm baytların sayısı uint8_t fifoBuffer[128]; // FIFO depolama arabelleği // orientation/motion vars Quaternion q; // [w, x, y, z] Kuarterna konteyner VectorFloat gravity; // [x, y, z] Yerçekimi vektörü float ypr[3]; // [yaw, pitch, roll] Yaw / pitch Adım/ roll rulo container ve yerçekimi vektörü //PID #if MANUAL_TUNING double kp , ki, kd; double prevKp, prevKi, prevKd; #endif double originalSetpoint = 174.29; double setpoint = originalSetpoint; double movingAngleOffset = 0.3; double input, output; int moveState=0; //0 = denge ; 1 = geri ; 2 = ileri #if MANUAL_TUNING PID pid(&input, &output, &setpoint, 0, 0, 0, DIRECT); #else PID pid(&input, &output, &setpoint, 70, 240, 1.9, DIRECT); #endif //MOTOR SURUCU int ENA = 3; int IN1 = 4; int IN2 = 8; int IN3 = 5; int IN4 = 7; int ENB = 6; LMotorController motorController(ENA, IN1, IN2, ENB, IN3, IN4, 0.6, 1); //Zamanlama long time1Hz = 0; long time5Hz = 0; volatile bool mpuInterrupt = false; // indicates whether MPU interrupt pin has gone high MPU kesme iğnesinin yüksek mi kaldıysa void dmpDataReady() { mpuInterrupt = true; } void setup() { // join I2C bus (I2Cdev library doesn't do this automatically) I2C veriyoluna katıl (I2Cdev kütüphanesi bunu otomatik olarak yapmaz) #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE Wire.begin(); TWBR = 24; // 400kHz I2C clock (200kHz if CPU is 8MHz) #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE Fastwire::setup(400, true); #endif // initialize serial communication // (115200 chosen because it is required for Teapot Demo output, but it's // really up to you depending on your project) // seri haberleşmeyi başlatır // (115200, Teapot Demo çıktısı için gerekli olduğu için seçildi, ancak // gerçekten projenize bağlı kalabilirsiniz) Serial.begin(115200); while (!Serial); // wait for Leonardo enumeration, others continue immediately Leonardo numaralandırmasını bekle, diğerleri hemen devam et // initialize device Cihazı başlat Serial.println(F("I2C Kuruluyor...")); mpu.initialize(); // verify connection Bağlantıyı doğrulamak Serial.println(F("Suruculer test ediliyor...")); Serial.println(mpu.testConnection() ? F("MPU6050 baglanti basarili") : F("MPU6050 baglanti basarisiz")); // load and configure the DMP DMP'yi yükleyin ve yapılandırın Serial.println(F("DMP kuruluyor...")); devStatus = mpu.dmpInitialize(); // supply your own gyro offsets here, scaled for min sensitivity Minyatür hassasiyet için ölçeklendirilmiş, kendi cirosu uzaklıklarınızı burada sağlayın mpu.setXGyroOffset(220); mpu.setYGyroOffset(76); mpu.setZGyroOffset(-85); mpu.setZAccelOffset(1688); // 1688 factory default for my test chip Test yongama için 1688 fabrika varsayılanı // make sure it worked (returns 0 if so) Çalıştığından emin olun (eğer öyleyse 0 döndürür) if (devStatus == 0) { // turn on the DMP, now that it's ready Hazır olduğunda, DMP'yi aç Serial.println(F("Enabling DMP...")); mpu.setDMPEnabled(true); // enable Arduino interrupt detection Arduino kesme algılamasını etkinleştir Serial.println(F("Enabling interrupt detection (Arduino external interrupt 0)...")); attachInterrupt(0, dmpDataReady, RISING); mpuIntStatus = mpu.getIntStatus(); // set our DMP Ready flag so the main loop() function knows it's okay to use it Ana döngü () işlevi onu kullanmanın iyi olduğunu bilmesi için DMP Hazır bayrağını ayarlayın Serial.println(F("DMP ready! Waiting for first interrupt...")); dmpReady = true; // get expected DMP packet size for later comparison Daha sonra karşılaştırmak için beklenen DMP paket boyutunu elde edin packetSize = mpu.dmpGetFIFOPacketSize(); //setup PID pid.SetMode(AUTOMATIC); pid.SetSampleTime(10); pid.SetOutputLimits(-255, 255); } else { // ERROR! // 1 = initial memory load failed // 2 = DMP configuration updates failed // (if it's going to break, usually the code will be 1) // HATA! // 1 = başlangıç bellek yükü başarısız // 2 = DMP yapılandırma güncellemeleri başarısız oldu // (eğer kırılırsa, genellikle kod 1 olur) Serial.print(F("DMP Initialization failed (code ")); Serial.print(devStatus); Serial.println(F(")")); } } void loop() { // if programming failed, don't try to do anything Programlama başarısız olursa, hiçbir şey yapmaya kalkışmayın. // wait for MPU interrupt or extra packet(s) available MPU kesmesi veya mevcut ek paket (ler) i bekleyin while (!mpuInterrupt && fifoCount < packetSize) { //no mpu data - performing PID calculations and output to motors // no mpu data - PID hesaplamaları yapar ve motorlara çıktılar pid.Compute(); motorController.move(output, MIN_ABS_SPEED); unsigned long currentMillis = millis(); if (currentMillis - time1Hz >= 1000) { loopAt1Hz(); time1Hz = currentMillis; } if (currentMillis - time5Hz >= 5000) { loopAt5Hz(); time5Hz = currentMillis; } } // reset interrupt flag and get INT_STATUS byte mpuInterrupt = false; mpuIntStatus = mpu.getIntStatus(); // get current FIFO count fifoCount = mpu.getFIFOCount(); // check for overflow (this should never happen unless our code is too inefficient) if ((mpuIntStatus & 0x10) || fifoCount == 1024) { // reset so we can continue cleanly mpu.resetFIFO(); Serial.println(F("FIFO overflow!")); // otherwise, check for DMP data ready interrupt (this should happen frequently) } else if (mpuIntStatus & 0x02) { // wait for correct available data length, should be a VERY short wait while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount(); // read a packet from FIFO mpu.getFIFOBytes(fifoBuffer, packetSize); // track FIFO count here in case there is > 1 packet available // (this lets us immediately read more without waiting for an interrupt) fifoCount -= packetSize; mpu.dmpGetQuaternion(&q, fifoBuffer); mpu.dmpGetGravity(&gravity, &q); mpu.dmpGetYawPitchRoll(ypr, &q, &gravity); #if LOG_INPUT Serial.print("ypr\t"); Serial.print(ypr[0] * 180/M_PI); 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 loopAt1Hz() { #if MANUAL_TUNING setPIDTuningValues(); #endif } void loopAt5Hz() { #if MOVE_BACK_FORTH moveBackForth(); #endif } //move back and forth void moveBackForth() { moveState++; if (moveState > 2) moveState = 0; if (moveState == 0) setpoint = originalSetpoint; else if (moveState == 1) setpoint = originalSetpoint - movingAngleOffset; else setpoint = originalSetpoint + movingAngleOffset; } //PID Tuning (3 potentiometers) #if MANUAL_TUNING void setPIDTuningValues() { readPIDTuningValues(); if (kp != prevKp || ki != prevKi || kd != prevKd) { #if LOG_PID_CONSTANTS Serial.print("kp = ") Serial.print(kp);Serial.print(", ");Serial.print("ki = ");Serial.print(ki);Serial.print("kd = ");Serial.print(", ");Serial.println(kd); #endif pid.SetTunings(kp, ki, kd); prevKp = kp; prevKi = ki; prevKd = kd; } } void readPIDTuningValues() { int potKp = analogRead(A0); int potKi = analogRead(A1); int potKd = analogRead(A2); kp = map(potKp, 0, 1023, 0, 25000) / 100.0; //0 - 250 ki = map(potKi, 0, 1023, 0, 100000) / 100.0; //0 - 1000 kd = map(potKd, 0, 1023, 0, 500) / 100.0; //0 - 5 } #endif
DENGE ROBOT KÜTÜHANESİNİ TIklayarak indirin.
Etiketler: arduino denge robotu, denge robotu, denge robotu nasıl yapılır, kaykay
Eklenme Tarihi: 1 Ağustos 2016
Hocam motorlarım hiç dönmüyor. Sıkıntı nerede anlamadım. Sadece L298N ve motorları döndürmeye çalışıyorum yine olmuyor. ölçü aleti ile baktım motorlara ve L298N çıkışlarına baktım değerler görünüyor. Ama motorlarda hareket yok.
yardımcı olabilir misiniz?
Önce çıkışlara led bağlayın eğer ledlerde yanmıyor ise. L298 in 8. Bacağına gerilim geliyor mu kontrol edin.
robot yüksüzken tekerler yavaş dönüyor yada elimle destek vererek döndürebiliyorum.
yere koyduğumda ise hiç dönmüyor
Kaç volt veriyorsunuz. L298n in
8. Ve 16. Bacaklarda kaç volt var
9V pil kullanıyordum. 5.3V civarında değer gösteriyor. 8 ve 16. bacaklarda.büyük ihtimal sorun akım az geliyordu.
9V 600mA adaptör denedim. şimdi sorunsuz çalışıyor ama çok hızlı dönüyor. kontrol edemiyorum.
PID degerlerini nasıl belirlediniz bir referansıız var mı?
Robotun tepkisine göre Ayar yaptım. Referans sadece robotun tepkisiydi.
exit status 1
Error compiling for board Arduino/Genuino Uno.
YAZILIMDA BU HATAYI ALDIM BU İŞLERDENDE ANLAMIYORUM ÖDEVİM İÇİN YAPIYORUM YARDIMCI OLURSANIZ SEVİNİRİM
Port ve Arduino secimi yapmanız lazım
Hocam ben robotu l298n motor sürücü ile yaptım ENA ve ENB UÇLARI 2 adet bağlantıları yaptığımda çalışmıyor fakat enable uçlarından birini 2. Uca taktığımda sadece bir motor çalışıyor diğer enable ucu içinde bu geçerli sizce neden oluyor
Umarım yardımcı olabilmişimdir.Saygılarimla
öncelikle paylaasımınız icin tesekkurler.Proje odevım ıcın kullandım tum baglantıları yaptım kodu yukledım fakat robotta hıc bır hareket yok elemanların ısıkları yanıyıor fakat robotta hıc tepkı yok yardımcı olabılır mısınız
?
Motorlara enerji gidiyor mu? Motor voltajını semadaki gibi yaptınız mi ? Bağlantıları kontrol ediniz.
Avometre ile motoralrın ucundakı voltu olctum hıc bır deger gostermedı.BAGLANTILAR da sanırım doğru fakat bende kı motor surucu bıraz daha farklı ena enb ucları 2 ser tane sanırım ondan kaynaklı bır hata mı acaba maıl adresınızı verebılırsenız ordan sıze surucunun resmını atabılırım ıyı gunler
0553 404 81 14 whatsapp tan ulaşabilirsiniz.
HOCAM BÜTÜN BAGLANTILARI YAPDIM AMA ROBOTUM CALISMIYOR NEDEN ÖRENE BİLİRMİYİM ROBOTUMDA HİÇ BİR TEPKİ YOK BÜTÜN BAGLANTILAR DOGRU VE CALISMIYOR NEDEN ?
Merhaba;
Dün tesadüfen bende yaptım devreyi herhangi bir sorun olmadan çalıştı. Devrede ve kodlarda sorun yok defalarca aynı devreyi ve yazılımı kullandım. Devre elemanlarını test ederek devam edin. Mpu6050 yi tek kullanarak 3 eksende değerler görmeye çalışın. Sonra motor sürücüyü tek kullanarak motorlara yön vermeyi deneyin . Adım adım giderseniz hata ben burdayım diyecektir.
Hocam pil ve anahtarlar baglantılarını nası yapıcaz devre şemasında cok karışık yazarmısınız teşekkürler
9v kare pil Arduino yu besleyecek.
4 adet 1.5v pil . Motorsurucunun 8. Bacağına gidecek.
Anahtarlama ise bu iki güç kaynağının gnd uçlarına yapılacak.
In file included from C:\Users\Kadir\Documents\Arduino\denge0\denge0.ino:5:0:
C:\Program Files (x86)\Arduino\libraries\MPU6050/MPU6050_6Axis_MotionApps20.h: In member function ‘uint8_t MPU6050::dmpGetAccel(int32_t*, const uint8_t*)’:
C:\Program Files (x86)\Arduino\libraries\MPU6050/MPU6050_6Axis_MotionApps20.h:580:31: warning: left shift count >= width of type
data[0] = ((packet[28] << 24) + (packet[29] << 16) + (packet[30] <= width of type
data[0] = ((packet[28] << 24) + (packet[29] << 16) + (packet[30] <= width of type
data[1] = ((packet[32] << 24) + (packet[33] << 16) + (packet[34] <= width of type
data[1] = ((packet[32] << 24) + (packet[33] << 16) + (packet[34] <= width of type
data[2] = ((packet[36] << 24) + (packet[37] << 16) + (packet[38] <= width of type
data[2] = ((packet[36] << 24) + (packet[37] << 16) + (packet[38] <= width of type
data[0] = ((packet[0] << 24) + (packet[1] << 16) + (packet[2] <= width of type
data[0] = ((packet[0] << 24) + (packet[1] << 16) + (packet[2] <= width of type
data[1] = ((packet[4] << 24) + (packet[5] << 16) + (packet[6] <= width of type
data[1] = ((packet[4] << 24) + (packet[5] << 16) + (packet[6] <= width of type
data[2] = ((packet[8] << 24) + (packet[9] << 16) + (packet[10] <= width of type
data[2] = ((packet[8] << 24) + (packet[9] << 16) + (packet[10] <= width of type
data[3] = ((packet[12] << 24) + (packet[13] << 16) + (packet[14] <= width of type
data[3] = ((packet[12] << 24) + (packet[13] << 16) + (packet[14] <= width of type
data[0] = ((packet[16] << 24) + (packet[17] << 16) + (packet[18] <= width of type
data[0] = ((packet[16] << 24) + (packet[17] << 16) + (packet[18] <= width of type
data[1] = ((packet[20] << 24) + (packet[21] << 16) + (packet[22] <= width of type
data[1] = ((packet[20] << 24) + (packet[21] << 16) + (packet[22] <= width of type
data[2] = ((packet[24] << 24) + (packet[25] << 16) + (packet[26] <= width of type
data[2] = ((packet[24] << 24) + (packet[25] << 16) + (packet[26] << 8) + packet[27]);
^
Çalışmanız programın 16528 bayt (51 %) saklama alanını kullandı. Maksimum 32256 bayt.
Global değişkenler belleğin 706 byte kadarını (34%) kullanıyor. Yerel değişkenler için 1342 byte yer kalıyor. En fazla 2048 byte kullanılabilir.
Hocam bende derlerken böyle bir sorunla karsılasıyorum ne oldugunu anlayamadım kütüphaneden kaynaklı oldugunu düiündüm ivme sensörünün kütüphanesini sürekli degistirdim ama olmadı bi yardımcı olursanız cok sevinirim
nasıl çözdünüz hatayı?
PID pid(&input, &output, &setpoint, 70, 240, 1.9, DIRECT);
bu kısmı
PID pid(&input, &output, &setpoint, 15, 90, 0.8, DIRECT);
olarak değiştirdiğinizde titreme sorunu duzeltirseniz araç titreme falan yapmıyor çok dengeli çalışıyor.
Devreyi hazırladım dediğiniz gibi yaptım her şeyi ama eğim sensörü geriye gittiğinde iki tekerlek doğru çalışıyor , sensör öne doğru gittiğinde sadece bir tekerlek dönüyor bu yüzden robot çalıştığında ilk öne geriye hareket yapıp dengede duruyor sonra etrafında dönmeye başlıyor sizin kodunuzun aynısını yaptım ama neden böyle oldu ? kod ile alakalı bir şey diye düşünüyorum ama sizinle aynı kodu kullandım yardım ederseniz sevinirim.
Merhaba. Öncelikle gerçekten çok güzel anlatmışsınız teşekkürler :)) benim anlamadığım bir yer var . Gnd yerleri arduınonun harici güç yerine bağlanmış devrede onu nasıl yapacağım bilmiyorum. ve benim motorlarım 6v 500 rpm sorun olurmu ve tekerleklerim sizinikilerden ince ve biraz daha büyük. şimdiden teşekkürler 🙂
Arduino:1.8.2 (Windows 8.1), Kart:”Arduino/Genuino Uno”
sketch_apr19a:3: error: #include expects “FILENAME” or
#include “I2Cdev.h�
^
sketch_apr19a:4: error: #include expects “FILENAME” or
#include “MPU6050_6Axis_MotionApps20.h�
^
sketch_apr19a:6: error: #include expects “FILENAME” or
#include “Wire.h�
^
exit status 1
#include expects “FILENAME” or
This report would have more information with
“Show verbose output during compilation”
option enabled in File -> Preferences.
nasıl düzeltebilirim
” ve ‘ tirnaklari tekrar yaz klavyeden
ve derken
ile anlamında ve tırnakları tekrar yazın. Yada programı mail atayım.
mail atarsanız çok sevinirim
mail ne zaman atabilirsiniz
Kodları arduino uyumlu zip şeklinde verebilirmisiniz? Sıkıntı çıkıyor. Teşekkürler.
merhaba hocam kodu kopyala yapıştır yaptığımda hata veriyor kodu zip hainde verme şansınıoz var mı
hocam benimle iletişime geçer misiniz çok acil üniversite ödevim var yardımınız gerek.turhanbursa1@hotmail.com mail atarsanız çok iyi olur yada mail adresinizi verek
sketch_oct22f:9: error: #include expects “FILENAME” or
#include “MPU6050_6Axis_MotionApps20.h�
bu hatayı veriyor ne yaptıysam çözemedim durumu. arduino da çalışır vaziyetteki programı arduino dosyası olarak yükleseniz olmaz mı kopyala yapıştır yapınca bu tarz hatalar ile karşılaşıyoruz ve düzelmiyor
Selam , ben bu projeyi yapmak istiyorum.Programı arduino’nun programında denedim ama hata verdi.Programdaki kodlar doğru mu acaba?
Merhaba Emre.
Ben sürekli aynı kodlar ile çalışıyorum. Yanlış kod vermektense hiç vermemeyi tercih ederim.Kopyala yapıştır yapınca sorun çıkıyor bazen buna dikkat edin.