BAĞLAN

Android Kontrollü Dengede Duran Robot Yapımı

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

    Kendi Robotunu Yap projelerimizin bu bölümünde arduino ile kendini dengeleyen robot yapacağız.Yapacağımız denge robotunu android cihazdan da kontrol edebileceğiz.Robotumuzun kontrol sisteminden bahsedecek olursak dengede durması için gyro sensörden gelen açı analiz edilir ve PID kontrol sistemiyle açıya göre motorlara ivmelenme vererek dengeyi sağlar.Kullanacağımız motorların enkoderli olması avantaj sağlayacaktır.

    Malzemeler:

    1. Arduino Uno
    2. Hc-05 Bluetooth Modül
    3. MPU6050 6 Eksen İvme ve Gyro Sensörü
    4. L293D Motor Sürücü
    5. IC7805 Voltaj Regülatörü
    6. Lipo Pil
    7. 2Adet  500 Rpm Motor
    8. 2 Adet Motor Vidalama Kıskacı

    Mekanik Kısım:

    Mekanik malzemesi için pleksi kullanabilirsiniz.

    Elektronik Devre Şeması:

    MPU6050 Gyro Sensör Bağlantı Pinleri:

    SDA => Analog 4

    SCL => Analog 5

    INT => Dijital 2

    Bluetooth Bağlantı Pinleri:

    rxpin = > D4
    txpin = > D11
    VCC = > 5V
    GND = > GND

    L293D Motor Sürücü Bağlantı Pinleri:

    1.Motor İleri => Dijital 5.Pin
    1.Motor Geri => Dijital 8.Pin
    2.Motor İleri => Dijital 6.Pin
    2.Motor Geri => Dijital 12.Pin
    1.Motor Hız Kontrol => Dijital 9.Pin
    2.Motor Hız Kontrol => Dijital 10.Pin

    Yazılım Kısmı:

    Arduino Yazılımı:

    #define version_0.67
     
    //#define DEBUGING 
    #define BLUE 
     
    #include <EEPROMex.h> 
    #include <I2Cdev.h>
    #include <Wire.h>
    #include <MPU6050_6Axis_MotionApps20.h>
    #include <helper_3dmath.h>
    #include <PID_v1.h> 
    #include <digitalIOPerformance.h> 
    #define DIGITALIO_NO_INTERRUPT_SAFETY
    #define DIGITALIO_NO_MIX_ANALOGWRITE
     
    //Bluetooth Stuff
    #include<SoftwareSerial.h>
     
    const int rxpin = 11; 
    const int txpin = 4; 
     
    SoftwareSerial blue(rxpin, txpin); 
     
    #define RESTRICT_PITCH
     
    MPU6050 mpu;
     
    // MPU control/status vars
    bool dmpReady = false; 
    uint8_t mpuIntStatus; 
    uint8_t devStatus; 
    uint16_t packetSize; 
    uint16_t fifoCount; 
    uint8_t fifoBuffer[64]; 
    // orientation/motion vars
    Quaternion q; 
    VectorFloat gravity; 
    float ypr[3]; 
     
    volatile bool mpuInterrupt = false; 
    void dmpDataReady() {
     mpuInterrupt = true;
    }
    // Balance PID controller Definitions
    #define BALANCE_KP 15 
    #define BALANCE_KI 90
    #define BALANCE_KD 0.8
    #define BALANCE_PID_MIN -255 
    #define BALANCE_PID_MAX 255
     
    #define ROTATION_KP 50
    #define ROTATION_KI 300
    #define ROTATION_KD 4
     
    #define MOTOR_A_DIR 5 
    #define MOTOR_A_BRAKE 8 
    #define MOTOR_B_DIR 6 
    #define MOTOR_B_BRAKE 12 
    #define MOTOR_A_PWM 9 
    #define MOTOR_B_PWM 10 
     
    // Motor Misc
    #define PWM_MIN 0
    #define PWM_MAX 255
    float MOTORSLACK_A=32; 
    float MOTORSLACK_B=39; 
    #define MOTOR_A_PWM_MAX 255 
    #define MOTOR_B_PWM_MAX 255 
     
    int MotorAspeed, MotorBspeed, MotorSlack,moveState=0,d_speed,d_dir;
     
    double yaw,input,out,setpoint,originalSetpoint,Buffer[3];
    double yinput,yout,ysetpoint,yoriginalSetpoint;
    //uint32_t timer,timer1;
     
    double bal_kp,bal_ki,bal_kd,rot_kp,rot_ki,rot_kd;
    int addressFloat=0;
     
    PID pid(&input,&out,&setpoint,BALANCE_KP,BALANCE_KI,BALANCE_KD,DIRECT);
    PID rot(&yinput,&yout,&ysetpoint,ROTATION_KP,ROTATION_KI,ROTATION_KD,DIRECT);
     
    String content = "";
     char character;
    //String d;
     
    void setup()
    {
     #ifdef DEBUGING
     Serial.begin(9600);
     #endif
     
     #ifdef BLUE
     blue.begin(9600);
     blue.setTimeout(10);
     #endif
     
     init_imu();
     initmot();
     
    pid.SetMode(AUTOMATIC); 
    pid.SetOutputLimits(-210, 210);
    pid.SetSampleTime(10);
    rot.SetMode(AUTOMATIC);
    rot.SetOutputLimits(-20, 20);
    rot.SetSampleTime(10);
     
    setpoint = 0;
    originalSetpoint = setpoint;
    ysetpoint = 0;
    yoriginalSetpoint = ysetpoint;
     
    addressFloat = EEPROM.getAddress(sizeof(float)); 
    bal_kp=EEPROM.readFloat(addressFloat);
    bal_ki=EEPROM.readFloat((addressFloat+=sizeof(float)));
    bal_kd=EEPROM.readFloat((addressFloat+=sizeof(float)));
    rot_kp=EEPROM.readFloat((addressFloat+=sizeof(float)));
    rot_ki=EEPROM.readFloat((addressFloat+=sizeof(float)));
    rot_kd=EEPROM.readFloat((addressFloat+=sizeof(float)));
     
    pid.SetTunings(bal_kp,bal_ki,bal_kd); 
    rot.SetTunings(rot_kp,rot_ki,rot_kd);
    }
     
    void loop() 
    {
     getvalues(); 
     new_pid(); 
     
    #ifdef BLUE
    Bt_control(); 
    #endif
     
    #ifdef DEBUGING
     printval();
    #endif
     
    }
     
    void init_imu()
    {
     Wire.begin();
     mpu.initialize();
     devStatus = mpu.dmpInitialize();
     
     mpu.setXGyroOffset(-9);
     mpu.setYGyroOffset(-3);
     mpu.setZGyroOffset(61);
     mpu.setXAccelOffset(-449);
     mpu.setYAccelOffset(2580);
     mpu.setZAccelOffset(1259);
     // make sure it worked (returns 0 if so)
     if (devStatus == 0) {
     
     mpu.setDMPEnabled(true);
     
     attachInterrupt(0, dmpDataReady, RISING);
     mpuIntStatus = mpu.getIntStatus();
     dmpReady = true;
     // get expected DMP packet size for later comparison
     packetSize = mpu.dmpGetFIFOPacketSize();
     }
    }
     
    void getvalues()
    {
     
     if (!dmpReady) return;
     while (!mpuInterrupt && fifoCount < packetSize) {
     }
     mpuInterrupt = false;
     mpuIntStatus = mpu.getIntStatus();
     
     fifoCount = mpu.getFIFOCount();
     
     if ((mpuIntStatus & 0x10) || fifoCount == 1024) {
     
     mpu.resetFIFO();
     } else if (mpuIntStatus & 0x02) {
     
     while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount();
     
     mpu.getFIFOBytes(fifoBuffer, packetSize);
     
     fifoCount -= packetSize;
     mpu.dmpGetQuaternion(&q, fifoBuffer);
     mpu.dmpGetGravity(&gravity, &q);
     mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);
     
     } 
     yinput = ypr[0]* 180/M_PI;
     input = -ypr[1] * 180/M_PI; //change sign if negative
    }
     
    void printval()
    {
     Serial.print(yinput);Serial.print("\t"); 
     Serial.print(yoriginalSetpoint); Serial.print("\t");
     Serial.print(ysetpoint); Serial.print("\t");
     Serial.print(yout); Serial.print("\t");Serial.print("\t"); 
     Serial.print(input);Serial.print("\t");
     Serial.print(originalSetpoint); Serial.print("\t");
     Serial.print(setpoint); Serial.print("\t");
     Serial.print(out); Serial.print("\t");Serial.print("\t");
     Serial.print(MotorAspeed); Serial.print("\t");
     Serial.print(MotorBspeed); Serial.println("\t");
     
    }
     
    void Bt_control()
    {
    if(blue.available())
     {
     content=blue.readString();
     if(content[0]=='F')
     setpoint = originalSetpoint - d_speed;//Serial.println(setpoint);} 
     else if(content[0]=='B')
     setpoint = originalSetpoint + d_speed;//Serial.println(setpoint);} 
     else if(content[0]=='L')
     ysetpoint = constrain((ysetpoint + yoriginalSetpoint - d_dir),-180,180);//Serial.println(ysetpoint);} 
     else if(content[0]=='R')
     ysetpoint = constrain(ysetpoint + yoriginalSetpoint + d_dir,-180,180);//Serial.println(ysetpoint);} 
     else if(content[0]=='S')
     d_speed = (content.substring(2)).toInt();//Serial.println(d_speed);} 
     else if(content[0]=='D')
     d_dir = content.substring(2).toInt();//Serial.println(d_dir);} 
     else if(content[0]=='P')
     {
     if(content[1]=='S')
     {
     if(content[2]=='B')
     save_pid(1); 
     else
     save_pid(0); 
     } else if(content[1]=='C')
     {
     if(content[2]=='B')
     {
     change_pid(1); 
     }
     else
     change_pid(0); 
     }
     }
     if(content=="updateb") 
     return_pid(1); 
     else if(content=="updater")
     return_pid(0); 
     
     }
    }
     
    void return_pid(bool b) 
    {
     char charVal[10];
     String sent = "";
     if(b)
     {
     sent.concat("OP");dtostrf(bal_kp, 5, 3, charVal);sent.concat(charVal);
     sent.concat("OI");dtostrf(bal_ki, 5, 3, charVal);sent.concat(charVal);
     sent.concat("OD");dtostrf(bal_kd, 5, 3, charVal);sent.concat(charVal);
     sent.concat("e");
     // Serial.println(sent);
     }
     else
     {
     sent.concat("OP");dtostrf(rot_kp, 5, 3, charVal);sent.concat(charVal);
     sent.concat("OI");dtostrf(rot_ki, 5, 3, charVal);sent.concat(charVal);
     sent.concat("OD");dtostrf(rot_kd, 5, 3, charVal);sent.concat(charVal);
     sent.concat("e");Serial.println(sent);
     }
     blue.print(sent);
    }
     
    void change_pid(bool b) 
    {
     blue.print("O");
     while(!blue.available());
     for(int i=0;i<3;i++) { Buffer[i]=blue.parseFloat(); } if(b) { bal_kp=Buffer[0];bal_ki=Buffer[1],bal_kd=Buffer[2]; } else { rot_kp=Buffer[0];rot_ki=Buffer[1],rot_kd=Buffer[2]; } } void save_pid(bool pid) { addressFloat = 0; if(pid) { EEPROM.updateFloat(addressFloat,bal_kp); EEPROM.updateFloat((addressFloat+=sizeof(float)),bal_ki); EEPROM.updateFloat((addressFloat+=sizeof(float)),bal_kd); } else { EEPROM.updateFloat(addressFloat,rot_kp); EEPROM.updateFloat((addressFloat+=sizeof(float)),rot_ki); EEPROM.updateFloat((addressFloat+=sizeof(float)),rot_kd); } } double compensate_slack(double yOutput,double Output,bool A) { if(A) { if (Output >= 0) 
     Output = Output + MOTORSLACK_A - yOutput;
     if (Output < 0) Output = Output - MOTORSLACK_A - yOutput; } else { if (Output >= 0) 
     Output = Output + MOTORSLACK_B + yOutput;
     if (Output < 0) Output = Output - MOTORSLACK_B + yOutput; } Output = constrain(Output, BALANCE_PID_MIN, BALANCE_PID_MAX); return Output; } void new_pid() { //Compute error pid.Compute(); rot.Compute(); MotorAspeed = compensate_slack(yout,out,1); MotorBspeed = compensate_slack(yout,out,0); motorspeed(MotorAspeed, MotorBspeed); } void initmot() { pinMode(MOTOR_A_DIR, OUTPUT); pinMode(MOTOR_A_BRAKE, OUTPUT); pinMode(MOTOR_B_DIR, OUTPUT); pinMode(MOTOR_B_BRAKE, OUTPUT); analogWrite(MOTOR_A_PWM, 0); analogWrite(MOTOR_B_PWM, 0); } void motorspeed(int MotorAspeed, int MotorBspeed) { if (MotorAspeed >= 0) 
     {
     digitalWrite(MOTOR_A_DIR,HIGH);
     digitalWrite(MOTOR_A_BRAKE,LOW);
     }
     else
    {
     digitalWrite(MOTOR_A_DIR,LOW);
     digitalWrite(MOTOR_A_BRAKE,HIGH);
    }
     
     analogWrite(MOTOR_A_PWM,abs(MotorAspeed));
     
     if (MotorBspeed >= 0) 
     {
     digitalWrite(MOTOR_B_DIR,HIGH);
     digitalWrite(MOTOR_B_BRAKE,LOW);
     }
     else
     {
     digitalWrite(MOTOR_B_DIR,LOW);
     digitalWrite(MOTOR_B_BRAKE,HIGH);
     }
     analogWrite(MOTOR_B_PWM, abs(MotorBspeed));
    }

    Gerekli Kütüphaneler:

    Denge robotu kütüphaneleri

    Android Uygulaması ve Arduino Kodu:

    Android arayüz programımızda pid değerlerini değiştirerek yaptığınız mekanik tasarıma göre robotun denge konumunu ayarlayabilirsiniz.Android kontrol programını indirelim.

    Android Denge robot kontrolü

    Arduino Kodu: denge robotu

    Kendi Robotunu Yap projelerimizin bu bölümünde de android kontrolllü dengede duran robotumuzu tamamladık.

     


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

    Sezgin GÜL

    Makine Mühendisi, Girişimci, Maker

    Kimler Neler Demiş?

    129 Yorum - "Android Kontrollü Dengede Duran Robot Yapımı"

    avatar
    Sıralama:   En Yeniler | Eskiler | Beğenilenler
    mustafa coşkun soyluoğlu
    Ziyaretçi
    mustafa coşkun soyluoğlu

    l293dd motor sürücü kartı kullanıyorum bağlantı şeması nasıl olmalı? m1a,m1b,m2a ve m2b gibi pin isimleri var

    mustafa coşkun soyluoğlu
    Ziyaretçi
    mustafa coşkun soyluoğlu

    hata veritor kod
    Arduino:1.8.0 (Windows 7), Kart:”Arduino/Genuino Uno”

    C:\Users\ogretmen1\Desktop\Yeni klasör (3)\cizgi-izleyen-robot\cizgi-izleyen-robot\Line_Follower_01012015pda\Line_Follower_01012015pda.ino:11:21: fatal error: PID_v1.h: No such file or directory

    compilation terminated.

    exit status 1
    Arduino:1.8.0 (Windows 7), Kart:”Arduino/Genuino Uno”

    C:\Users\ogretmen1\Documents\Arduino\sketch_jan17c\sketch_jan17c.ino:11:20: fatal error: PID_v1.h: No such file or directory

    #include

    ^

    compilation terminated.

    exit status 1
    Error compiling for board Arduino/Genuino Uno.

    This report would have more information with
    “Show verbose output during compilation”
    option enabled in File -> Preferences.

    Volkan
    Ziyaretçi

    Hocam malzeme list ile semanın alakası yok.ayrıca motorlarda enkoder de yok.

    Ali Can ÇEVRİM
    Ziyaretçi

    Hocam iyi günler. Biz robot için parçaları sipariş ettik lakin resimdeki voltaj regülatörü stokta kalmamış. Devre şemamızı IC 7805 voltaj regülatörü olmadan kursak herhangi bir sorunla karşılaşır mıyız?

    ERCAN
    Ziyaretçi

    Merhaba projelerinizi takip ediyorum. Denge robotunda bir problem ile karşlaştım,
    digitalIOPerformance.h:6:5: operator’%’ has no left operand
    Kodu değiştirsem bile aynı hata mesajı ile karşılaşıyorum.
    Nasıl düzeltebilirim

    Erdoğan
    Ziyaretçi

    Merhaba Sezgin Bey. Ben mekatronik mühendisliği son sınıf öğrencisiyim. Bitime projem sizin yaptığınız gibi iki tekerlekli denge robotu. Proje şu an bitmiş durumda. Ancak iki tekerlekli dengede durabilen robotlarda kontrol metodları üzerine bitirme tezi yazıyorum. Bu konuda yardımcı olabilir misiniz ?

    Sedat
    Ziyaretçi

    Merhaba. Ben de mekatronik 4. sınıf öğrencisiyim ve iki tekerlekli denge robotu yapacağım bitirme ödevi için. Yapmış olduğun ödevin notlarını bana gönderebilir misin ?

    Ahmet
    Ziyaretçi

    Robotu modellemek için free body diagram ya da Lagrange method kullanabilirsin Lagrange öneririm. Kontrol etmek için PID kullanabilirsin ama çok hassas olmaz. PID ve LQR kullanırsan çok iyi sonuçlar çıkar ama gyro verileri durum geri beslemesi için fazla gürültülü. Bu yüzden Kalman filtresi eklemen gerekecek. Alternatif olarak olarak fuzzy pid ya da sliding mode control da kullanabilirsin

    hasan
    Ziyaretçi

    s.a sezgin bey aynı projeyi bende yaptım ancak [sketch_may23a.ino: In function ‘void setup()’:
    sketch_may23a:98: error: ‘initmot’ was not declared in this scope
    sketch_may23a.ino: In function ‘void new_pid()’:
    sketch_may23a:287: error: ‘else’ without a previous ‘if’] böyle bir hata veriyo gerekli kütüpaneleri yükledim ama yinede olmuyor yardımcı olursanız sevinirim. iyi günler iyi çalışmalar

    Yusuf AKGÜL
    Üye

    tüm bağlantılar tamam kodları da yükledim ancak hiç bir hareket yok

    Yusuf AKGÜL
    Üye

    kodlar bir türlü derlenmiyor..tüm kütüphaneler tam olmasına rağmen initmot hata veriyor…

    Yusuf AKGÜL
    Üye

    ‘initmot’ was not declared in this scope

    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 3 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
      2 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
      3 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-23 19:53:34
    I2Cdev.h MPU6050 kütüphanesinin içinde bulunuyor ayrı indirmenize gerek yok.
    mahmut 2017-02-23 18:25:28
    iyi günler ı2cdev.h kutuphanesını nerden bulabılırım
    Sezgin GÜL
    Sezgin GÜL 2017-02-23 15:27:37
    Arduino Uno
    mustafa 2017-02-23 15:02:27
    abi yukarida paylaştıgın videodaki arduino çeşidini yazarmisin aynısından alacağimda
    Sezgin GÜL
    Sezgin GÜL 2017-02-23 13:23:12
    İndirdiğin eklentiyi aç.Klasör içine gir. 3 dosya bir klasör olacak. Onların hepsini yukarıda belirtiğim konuma ekle. Önceki eklediğini sil. Programı.....
    mustafa 2017-02-23 13:06:37
    abi bütün yazilimi 1 sekmeyemi ekliyoruz
    Sezgin GÜL
    Sezgin GÜL 2017-02-22 13:37:41
    Eklentiyi yanlış yere kurmuş olduğunuz için görünmüyor.Attığınız konumu tekrar kontrol edin.
    enver 2017-02-22 13:17:45
    iyi günler ben inkspace 0.48,5 kurdum anacak içine linkini verdiğiniz gcode dosyasını belirrttiğiniz adrese atmama rağmen gcode dosyası olarak kaydedemiyorum......