BAĞLAN

Arduino İle Kendini Dengeleyen Robot Yapımı

  • Görüntülenme 13494
  • PAYLAŞ
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  

    Kendi Robotunu Yap projelerimizin bu bölümünde arduino ile dengede duran robot yapımını anlatacağım.Önceki projelerimizde android kontrollü olan versiyonu anlatmıştık.Bu projemizde ise bizim kontrolümüzle hareket etmeyecek.Kendini Dengeleyen Robot projemize geçelim ve yapımına başlayalım.

    Malzemeler:

    • Arduino Uno veya Mega
    • L298N Motor Sürücü Kartı
    • Mpu 6050 6 eksen Gyro-İvmeölçer
    • 3 Adet potansiyometre
    • Mekanik için pleksi levha veya sert plastik kaplardan kesebilirsiniz.
    • 4 Adet yaklaşık 20 cm uzunluğunda vida çubuklar
    • 24 Adet Somun
    • 2 Adet 6v 250 rpm dc motor (tekerlekleri ile birlikte olanlardan alın)
    • Lipo pil

    Mekanik Kısım:

    20×8 cm ebatında üç adet pleksi levha keselim.Farklı ebatlarda da kesebilirsiniz.Kestikten sonra her levhanın köşelerine çubuk vidanın çapı kadar delik açalım.Her levha iki somun arasında kalacak şekilde çubuk vidaları ve somunları monte edelim.Levhaların birbirleri arasındaki boşluğun eşit olmasına dikkat edelim.Ardından motorlarımızı en altta bulunan levhanın sağ ve sol kenarına tam merkezde olacak şekilde demir telle bağlayıp silikonlayalım.Mekanik kısım bu kadar.

    Elektronik Kısım:

    Devre şeması:

    Kullandığımız motor sürücü kendi kütüphanesi ile motorları senkronize bir şekilde çalıştırıyor.Bu sayede de tam verimle motorların çalışıp sistemde hata olmamasını en aza indirgemiş oluyor.

    Motor sürücü üzerinde 12v enerji girişine lipo pilin artı kısmını takıyoruz.Gnd girişine de eksi ucunu takıyoruz.

    Devreye ek olarak 3 tane potansiyometreyi analog 0,1 ve 2 numaralı pinlere bağlıyoruz.Potansiyometrelerin burdaki görevi kp, kd ve ki değerlerini manual olarak ayarlayarak robotun en uygun denge noktasını bulmamızı sağlayacaktır.Mpu6050 gyro sensörü yatay şekilde en alt levhaya sabitleyelim.

    Yazılım Kısmı:

    Kütüphaneleri buradan indirelim >> Denge Robot Kütüphaneler

    Arduino Yazılımı:

    #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 //MANUAL_TUNING must be 1
    #define MOVE_BACK_FORTH 0
    
    #define MIN_ABS_SPEED 30
    
    //MPU
    
    
    MPU6050 mpu;
    
    // MPU control/status vars
    bool dmpReady = false; // set true if DMP init was successful
    uint8_t mpuIntStatus; // holds actual interrupt status byte from MPU
    uint8_t devStatus; // return status after each device operation (0 = success, !0 = error)
    uint16_t packetSize; // expected DMP packet size (default is 42 bytes)
    uint16_t fifoCount; // count of all bytes currently in FIFO
    uint8_t fifoBuffer[64]; // FIFO storage buffer
    
    // orientation/motion vars
    Quaternion q; // [w, x, y, z] quaternion container
    VectorFloat gravity; // [x, y, z] gravity vector
    float ypr[3]; // [yaw, pitch, roll] yaw/pitch/roll container and gravity vector
    
    
    //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 = balance; 1 = back; 2 = forth
    
    #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 CONTROLLER
    
    
    int ENA = 9;
    int IN1 = 11;
    int IN2 = 10;
    int IN3 = 5;
    int IN4 = 4;
    int ENB = 3;
    
    
    LMotorController motorController(ENA, IN1, IN2, ENB, IN3, IN4, 0.6, 1);
    
    
    //timers
    
    
    long time1Hz = 0;
    long time5Hz = 0;
    
    
    volatile bool mpuInterrupt = false; // indicates whether MPU interrupt pin has gone high
    void dmpDataReady()
    {
     mpuInterrupt = true;
    }
    
    
    void setup()
    {
     // join I2C bus (I2Cdev library doesn't do this automatically)
     #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)
     Serial.begin(115200);
     while (!Serial); // wait for Leonardo enumeration, others continue immediately
    
     // initialize device
     Serial.println(F("Initializing I2C devices..."));
     mpu.initialize();
    
     // verify connection
     Serial.println(F("Testing device connections..."));
     Serial.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed"));
    
     // load and configure the DMP
     Serial.println(F("Initializing DMP..."));
     devStatus = mpu.dmpInitialize();
    
     // supply your own gyro offsets here, scaled for min sensitivity
     mpu.setXGyroOffset(220);
     mpu.setYGyroOffset(76);
     mpu.setZGyroOffset(-85);
     mpu.setZAccelOffset(1788); // 1688 factory default for my test chip
    
     // make sure it worked (returns 0 if so)
     if (devStatus == 0)
     {
     // turn on the DMP, now that it's ready
     Serial.println(F("Enabling DMP..."));
     mpu.setDMPEnabled(true);
    
     // enable Arduino interrupt detection
     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
     Serial.println(F("DMP ready! Waiting for first interrupt..."));
     dmpReady = true;
    
     // get expected DMP packet size for later comparison
     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)
     Serial.print(F("DMP Initialization failed (code "));
     Serial.print(devStatus);
     Serial.println(F(")"));
     }
    }
    
    
    void loop()
    {
     // if programming failed, don't try to do anything
     if (!dmpReady) return;
    
     // wait for MPU interrupt or extra packet(s) available
     while (!mpuInterrupt && fifoCount < packetSize)
     {
     //no mpu data - performing PID calculations and output to motors
     
     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(", ");Serial.print(ki);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
    

    Yazılımı yükleyip gerekli bağlantıları tamamlıyoruz. Robotumuzu çalıştırdıktan sonra dik konumda serbest bırakalım.Robotun dengede durmasında sıkıntı varsa potansiyometrelerle kp, ki ve kd değerlerini değiştiriyoruz.

    Yukarıdaki kodu kopyalıp almışsanız muhtemelen derlemede hata alacaksınız. Bundan dolayı Arduino Yazılım dosyasını buradan indirebilirsiniz.>> kendini dengeleyen Robot

    Kendi Robotunu Yap projelerimizin bu bölümünde arduino ile dengede duran robotumuzu tamamladık.Bir sonraki kendi robotunu yap projemizde görüşmek üzere.. iyi çalışmalar…


    PAYLAŞ
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    Sezgin GÜL

    Sezgin GÜL

    Makine Mühendisi, Girişimci, Maker

    Kimler Neler Demiş?

    145 Yorum - "Arduino İle Kendini Dengeleyen Robot Yapımı"

    avatar
    Sıralama:   En Yeniler | Eskiler | Beğenilenler
    Kazım
    Ziyaretçi

    Hocam şekildeki gibi herşeyi yaptım ama tekerler sürekli aynı yönde dönüyor aorun nerdedir acaba yardımcı olabilirmisiniz

    Ali
    Ziyaretçi

    Merhaba burda gösterilenlerin hepsini yapyık ama çalışmıyor güc verince motor kartından ses geliyor ama tekerler dönmüyor

    Taner
    Ziyaretçi

    Potansiyometreler icin tek 5v ve tek gnd girisi var ucunu birden nasil beslicem?

    cem koç
    Ziyaretçi

    merhaba yukarıda anlatılanları yaptım ama motorlarda hiç çalışmadı ve seri pport ekranına balınca böyle bir hata veriyor Initializing I2C devices…
    Testing devicInitializing I2C devices…
    Testing device connections…
    MPU6050 connection failed
    Initializing DMP…
    DMP Initialization failed (code 1)

    sebebi nedir acaba

    efe
    Ziyaretçi

    merhaba sezgin bey ben aynı işlemleri yaptım tek motor surekli aynı yöne dönüyor ve ivme sensörünün de bi etkisi yok

    Muammer
    Ziyaretçi

    Merhaba hocam benim aklima takilan sey potansetre ile yapilmak istenen ne yani potansetre nicin kullanildida jiroskop neden kullanilmadi

    Seyfi
    Ziyaretçi

    Hocam kolay gelsin l293d motor sürü kartı ile bu proje gerçekleşir mi bunu soracaktım saygılar

    efe
    Ziyaretçi

    sezgin bey merhaba atmış olduğunuz devre şemasının daha detaylısı var mı acaba

    ahmet
    Ziyaretçi

    merhaba hocam yüklerken hata oluştu verdiğiniz dosyayı indirdim yine aynı sorunla karşılaştım

    Robotikçi
    Ziyaretçi

    Merhabalar. Acaba İTÜRO’ya uygun yani 2. level’i de tamamlayan yani A noktasından B noktasına, sonra da B noktasından A noktasına gidebilen bir kod da var mı bunun içinde? Eğer yoksa yazabilir misiniz/verebilir misiniz/bulabilir misiniz lütfen?

    wpDiscuz

    Yeni Projeler More

    • 16 Şubat 2017
      1 hafta ÖNCE 2 Yorum

      Öğrenme Fonksiyonuna Sahip Hareket Kopyalayan Robot Kol Yapımı

      Bu projede öğrenme yoluyla hareket kopyalayan robot kol yapımından bahsedeceğim. Endüstride kullanılan robot kollar, her zaman aynı hareketleri yapmaya odaklıdır. Örneğin ürün bandından bir nesneyi alıp başka bir banda aktarımını yapan robot kollar sürekli aynı hareketi yapmaktadır. Bu hareketler önceden öğretilerek robot kola aktarılır. Burada da aynı mantıkla robot ...

    • 11 Şubat 2017
      2 hafta ÖNCE 10 Yorum

      Arduino İle Labirent Çözen Robot Yapımı

      Kendi robotunu yap projelerimizin bu bölümünde arduino ile labirent çözen robot yapacağız. Labirent çözen robot özellikle robot yarışmalarında yer almaktadır. Bir labirentin çözüm yolunu bulmak aslında tek bir etkene bağlıdır. Bu etken sağ veya sol taraftaki herhangi bir duvarı takip ettirmektir. Bu etkenden yola çıkarak robot sol veya sağ ...

    • 07 Şubat 2017
      3 hafta ÖNCE Yorum Yok

      Arduino ile MLX90614 Kızılötesi Sıcaklık Sensörü Kullanımı

      Cisme temas etmeden, cismin sıcaklığını ölçen MLX90614 kızılötesi sıcaklık sensöründen bahsedeceğim. Dahili bir 17-bit ADC ve güçlü bir DSP, MLX90614'ün ölçümlerinde yüksek doğruluk ve çözünürlük verir. Vücut sıcaklığı ölçmek için uygundur. Ayrıca hareket algılamada da kullanabilirsiniz. MLX90614 Özellikler: Ortam sıcaklığı ölçme aralığı -40 ile + 125 ° C Nesne ...

    • 05 Şubat 2017
      3 hafta ÖNCE Yorum Yok

      Arduino ile Yazıyı Sese Dönüştüren Emic 2 Modülü Kullanımı

      Robotunuzu konuşturmak ve neler olup bittiğini söyletmek ister misiniz ? Emic 2 yazıyı sese çeviren modülle kolaylıkla projeleriniz konuşabilir. Emic-2, Parallax tarafından, ses sentezini tamamen zahmetsiz kılmak için Grand Idea Studio ile birlikte tasarlanmıştır.

    • 31 Ocak 2017
      4 hafta ÖNCE 7 Yorum

      Arduino ile DHT22 Sıcaklık Nem Sensörü Kullanımı

      DHT sensörleri, kapasitif nem sensörü ve bir termistör olmak üzere iki parçadan oluşur. DHT11 ve DHT22 olan iki DHT modelini ele alalım. Görünüm ve pin yapısı olarak benzer görünmelerine rağmen farklı ölçüm hassasiyetlerine sahiptirler. Aşağıda iki modelin karşılaştırmasına bakalım.

    Bizi Takip Et

    Son Yorumlar

    Sezgin GÜL
    Sezgin GÜL 2017-02-25 23:01:46
    merhaba batuhan, hatanın sebebi AFMotor.h kütüphanesini yüklemediğinden kaynaklanmış. Kütüphaneyi buradan indirebilirsin http://www.robimek.com/wp-content/uploads/AFMOTOR-master.rar
    batuhan 2017-02-25 21:52:21
    sezgin bey öncelikle çok teşekkür ediyorum proje için ; Arduino ya kodu derlediğimde şöyle bir sorun ile karşılaşıyorum Arduino:1.8.1 (Windows.....
    Emin ERKMEN 2017-02-25 19:55:34
    Bu robotun üstüne ekleme yapabilir misiniz? 1 hafta içinde? Bu bizim için çok önemli.
    Sezgin GÜL
    Sezgin GÜL 2017-02-25 19:48:46
    Çizgili olan labirenti çözen robotlarda o özellik mevcut. İlerleyen günlerde o tarz proje paylaşacağım.
    Emin ERKMEN 2017-02-25 19:34:28
    Peki bu robot. En kısa yolu nasıl bulabilir. İkinci kez aynı labirentten geçtiği zaman en kısa yoldan gitmesi için ne.....
    Sezgin GÜL
    Sezgin GÜL 2017-02-25 18:10:10
    Kodlarda sorun yok videodaki robotta kullanılan kodlardır. Motor yönlerini doğru taktınız mı. Yön komutlarında doğru yönde dönüyorlar mı bunları da.....
    Emin ERKMEN 2017-02-25 18:03:27
    kodlarda sıkıntı yok yani?
    Sezgin GÜL
    Sezgin GÜL 2017-02-25 17:17:46
    Bağlantılarınız doğru ve sensörlerin konumları uygun ise enerji yetersizliğinden kaynaklanabilir