Bolu Beyi tarafından yazıldı Şubat - 18 - 2014 12 Yorum

Bu yazımda bitirme projemde uğraştığımız bir konuya değineceğim. MPU 6050 IMU sensörünü Arduino cihazınıza bağladığınızda karşınıza -2000, 15000, 4000 gibi ham veriler okunduğunu görebilirsiniz. Bu değerleri -180 ile +180 aralığına çekmek için ham verilerin filtreden geçirilmesi gerekmektedir. Filtre olarak Arduino‘da kullanılmasına imkan sağlayan Kalman Filtresi’ni kullandık. Ben sizlerle internetten bulduğumuz ve hatalı çalışan bir kodun düzeltilmiş halini paylaşacağım.

Kodlamaya geçmeden önce bağlantıları doğru bir şekilde yapmak gerekiyor. Biz projemizde Arduino Mega kullanmıştık, bağlantıları aşağıdaki tablodan ve şekilden rahatlıkla görebilirsiniz:

Arduino Mega pinleri MPU6050 pinleri
GND GND
3.3V VCC
20(communication) SDA
21(communication) SCL

arduino mpu6050

Öncelikle bazı kütüphaneleri eklememiz gerekiyor:

#include <I2Cdev.h>
#include <MPU6050_6Axis_MotionApps20.h>
#include <Kalman.h>

Kütüphaneleri ekledikten sonra bazı değişkenler tanımlamamız gerekiyor, isimlerinden ne için kullanıldığını anlayabilirsiniz:

Kalman KalmanX, KalmanY;const uint8_t IMUAddress = 0x68;
//Ham veriler
int16_t HamIvmeX, HamIvmeY, HamIvmeZ, HamGyroX, HamGyroY;double IvmeXaci, IvmeYaci, IvmeZaci;double IvmeX, IvmeY, IvmeZ;double GyroXaci = 0, GyroYaci = 0;// Kalman filtresinden gelen değer
double GyroX, GyroY;double OncekiGyroX = 0, OncekiGyroY = 0;uint32_t timer;
MPU6050 mpu;uint8_t mpuDurum;
uint8_t devStatus;
uint16_t PaketBoyutu;
uint16_t Sayac;
uint8_t Bellek[64];

Quaternion q;
VectorFloat YerCekimi;
volatile bool mpuKesme = false;

OncekiGyroX ve OncekiGyroY değişkenleri dikkatinizi çekmiş olabilir. Denemelerimiz sırasında sensörden bazı sapan veriler okunduğunu gördük. Mesela 2-3 derece civarında açı bilgisi geldiğinde birden 50 derece açı bilgisi okunduğunu gördük. Bunun üzerinde okuduğumuz her bir değeri “OncekiGyro” değişkenlerine atadık ve aradaki fark 15 derece ise önemseme dedik. Sonrasında aşağıdaki fonksiyonları kullanarak açı bilgilerini okuduk:

void IMU()
{
uint8_t* veri = i2cRead(0x3B,14);
HamIvmeX = ((veri[0] << 8) | veri[1]);
HamIvmeY = ((veri[2] << 8) | veri[3]);
HamIvmeZ = ((veri[4] << 8) | veri[5]);
HamSicaklik = ((veri[6] << 8) | veri[7]);
HamGyroX = ((veri[8] << 8) | veri[9]);
HamGyroY = ((veri[10] << 8) | veri[11]);IvmeYaci = (atan2(HamIvmeX,HamIvmeZ)+PI)*RAD_TO_DEG;
IvmeXaci = (atan2(HamIvmeY,HamIvmeZ)+PI)*RAD_TO_DEG;
IvmeZaci = (atan2(HamIvmeZ,HamIvmeZ)+PI)*RAD_TO_DEG;double GyroHassasiyetX =   (double)HamGyroX/131.0;
double GyroHassasiyetY = -((double)HamGyroY/131.0);GyroX = KalmanX.getAngle(IvmeXaci, GyroHassasiyetX, (double)(micros()-timer)/1000000);
GyroY = KalmanY.getAngle(IvmeYaci, GyroHassasiyetY, (double)(micros()-timer)/1000000);
timer = micros();
GyroX -= 180;
GyroY -= 180;if(abs(GyroX – OncekiGyroX) > 15)
GyroX = OncekiGyroX;
if(abs(GyroY – OncekiGyroY) > 15)
GyroY = OncekiGyroY;OncekiGyroX = GyroX;
OncekiGyroY = GyroY;Sicaklik = ((double)HamSicaklik + 12412.0) / 340.0;//veri madenciliği
IvmeX = (double)((double)(HamIvmeX – 630)/16384.0);
IvmeY = (double)((double)(HamIvmeY – 340)/16384.0);
IvmeZ = (double)((double)(HamIvmeZ – 1720)/16384.0);mpuKesme = false;
mpuDurum = mpu.getIntStatus();
Sayac = mpu.getFIFOCount();

if((mpuDurum & 0x10) || Sayac >= 1024)
{
mpu.resetFIFO();
}
else if(mpuDurum & 0x02)
{
while (Sayac < PaketBoyutu)
Sayac = mpu.getFIFOCount();

mpu.getFIFOBytes(Bellek, PaketBoyutu);

Sayac -= PaketBoyutu;
mpu.dmpGetQuaternion(&q, Bellek);
mpu.dmpGetGravity(&YerCekimi, &q);
mpu.dmpGetYawPitchRoll(ypr, &q, &YerCekimi);
ypr[0] = (double)(ypr[0]*1000.0);
GyroZ = map(ypr[0], -3000,3000,-180,180);
}
}
void dmpAktif()
{
mpuKesme = true;
}

void MPUbaslat()
{

Wire.begin();
mpu.initialize();
devStatus = mpu.dmpInitialize();
if(devStatus == 0)
{

mpu.setDMPEnabled(true);
attachInterrupt(0, dmpAktif, RISING);
mpuDurum = mpu.getIntStatus();
PaketBoyutu = mpu.dmpGetFIFOPacketSize();
}
}
void i2cWrite(uint8_t registerAddress, uint8_t data){
Wire.beginTransmission(IMUAddress);
Wire.write(registerAddress);
Wire.write(data);
Wire.endTransmission(); // Send stop
}
uint8_t* i2cRead(uint8_t registerAddress, uint8_t nbytes) {
uint8_t data[nbytes];
Wire.beginTransmission(IMUAddress);
Wire.write(registerAddress);
Wire.endTransmission(false);
Wire.requestFrom(IMUAddress, nbytes);
for(uint8_t i = 0; i < nbytes; i++)
data[i] = Wire.read();
return data;
}

Bu kod sonucunda Arduino’dan okuduğumuz örnek açı ve ivme bilgilerinin ekran görüntüsü:

mpu 6050

 

 

 

 

 

How to read data from mpu6050, arduino, read angle data from mpu 6050, code example

Bugüne kadar 12 yorum yapıldı

  1. eren dedi ki:

    merhaba kütüphaneler için link verebilir misiniz lütfen

  2. eren dedi ki:

    bu kütüphanelerin hepsini yüklemiş olmama rağmen hata alıyorum:

    stray ‘\’ in program

    diye

  3. eren dedi ki:

    hata sebebi olarak da şu satırı gösteriyor

    const uint8_t IMUAddress = 0×68;

    • Bolu Beyi dedi ki:

      Aldığınız hatanın kütüphanelerle ilgili olduğunu sanmıyorum. Şu anda arduino yüklü olmadığından ve malzemelerim yanımda olmadığı için maalesef kontrol edemiyorum. Fakat bu kodların doğru çalıştığından eminim 🙂

  4. Onur dedi ki:

    kodda “ypr” değişkeni girilmemiş.

  5. eren dedi ki:

    biz bu hataları nasıl düzeltebiliriz peki. ya da doğru kodu paylaşabilir misiniz rica etsek

    • Bolu Beyi dedi ki:

      Dediğim gibi bunlar çalışıyordu zaten, kendim bizzat denedim. Şu anda elimde malzemeler olmadığından tekrar kontrol etme şansım yok maalesef, arkadaşın dediği gibi ypr değişkenini dizi olarak tanımlayın kendiniz, öyle deneyin bir de

  6. boyacı dedi ki:

    bir türlü yapamadım arkadaş neden hep hata veriyor sorun bendemi anlamadım gitti

  7. eko dedi ki:

    Merhaba,

    Bu mükemmel paylaşım için teşekkür ederim.Bu tarz yazılarınızı daha sıklıkla bekliyoruz.


Time limit is exhausted. Please reload CAPTCHA.