#64 Arduino MPU6050 İle 3D Model Teapot Uygulaması
Merhabalar, bu yazımızda Arduino MPU6050 İle 3D Model Teapot Uygulaması nı anlatacağım. Bu projede, MPU6050 ivmeölçer/jyroskop sensörü ile Arduino Nano kullanarak sensörden alınan hareket verilerinin 3D model (Teapot) üzerinde nasıl görselleştirileceğini öğreneceğiz. Bu tür uygulamalar özellikle robotik, hareket algılama, sanal gerçeklik gibi alanlarda sıkça kullanılmaktadır.
Devre bağlantı şeması, Arduino programı ayrıntılı kod kısmı, devre kurulumu detaylı anlatımı ve devre çalışma videosu şu şekildedir.
Arduino’ da kullanabileceğimiz üç eksenli ivmeölçer + üç eksenli jiroskop, toplamda 6 eksenli ivme ve gyro modülü özellikleri nelerdir? Hangi pinler kullanılır? Kullanıldığı alanlar nelerdir? Örnek Arduino çalıştırma kodu nedir? MPU6050 devreye nasıl bağlanır? gibi konularda bilgi almak için bir önceki yazımıza aşağıdaki linkten bakabilirsiniz.
https://egitim.ahmetcandemir.com.tr/mpu6050-ivme-ve-gyro-sensoru-nedir-nasil-calisir/
ARDUINO MPU6050 TEAPOT UYGULAMASI:
MPUTeapot, MPU6050 sensöründen alınan ivme (acceleration) ve jiroskop (gyro) verilerini kullanarak, gerçek zamanlı olarak 3 boyutlu (3D) bir modelin hareketlerini bilgisayar ekranında görselleştiren bir Processing uygulamasıdır.
Uygulamada genellikle bir çaydanlık (teapot) modeli yer alır, bu model MPU6050’nin hareketleriyle birebir olarak döner ve eğilir.
Sistem Nasıl Çalışır?
-
MPU6050 sensörü, 3 eksenli ivmeölçer ve 3 eksenli jiroskop içerir.
-
Bu sensör, Arduino aracılığıyla verileri okur.
-
Arduino, verileri seri port üzerinden bilgisayara gönderir.
-
Bilgisayarda çalışan Processing IDE ile yazılmış “MPUTeapot” programı bu verileri alır ve OpenGL ile 3D modelin dönüşünü ekranda gösterir.
DEVRE BAĞLANTI ŞEMASI:
DEVRE KURULUMU:
Malzemeler:
Arduino Nano (veya Uno)
Deney Tahtası (Breadboard)
1 adet ivme ve gyro modülü (MPU6050)
4 adet iki ucu erkek jumper kablo
MPU6050 modülü, deney tahtası (breadboard) üzerine yerleştirilir. Arduino Nano da deney tahtası üzerine yerleştirilir. Modülün VCC pini, Arduino +5V pinine bağlanır. Modülün GND pini, Arduino GND pinine bağlanır. Modülün SCL pini, Arduino’nun A5 pinine, modülün SDA pini, Arduino’nun A4 pinine bağlanır ve devre tamamlanır.
| MPU6050 Pin | Arduino Nano Pin |
|---|---|
| VCC | 3.3V veya 5V |
| GND | GND |
| SDA | A4 |
| SCL | A5 |
Öncelikli olarak MPU6050 sensöründen gelen verileri 3D bir model (örneğin uçak) üzerinde görselleştirmek için bir yazılıma ihtiyacımız var. Bu yazılımın adı Processing. Arduino, MPU6050 sensörüyle birlikte yaw, pitch, roll (yön, eğim, yuvarlanma) verilerini seri port üzerinden gönderir. Processing bu verileri gerçek zamanlı olarak okur. Processing bu açı verilerini kullanarak ekrandaki bir 3D modeli — örneğin bir uçak — sağa-sola döndürür, yukarı-aşağı eğdirir. Bu, sensörün hareketlerini doğrudan görsel olarak izlemeyi sağlar. Kısaca Processing, MPU6050’den gelen hareket verilerini görselleştirerek sensörün nasıl çalıştığını gerçek zamanlı olarak izlememizi sağlar. Şimdi aşağıdaki linkten Processing sayfasına gidip uygulamayı bilgisayarımıza indirip kuralım.
https://processing.org/download
Bilgisayarımızda Belgeler içerisinde Processing isimli bir klasör oluşacaktır. Bu klasör içerisinde libraries klasörü bulunmaktadır. Bu klasör içerisine kütüphane ekleyeceğiz.
Aşağıdaki linkten indirdiğiniz dosyayı zip içerisinden çıkartın. İçerisinde iki adet klasör olacak. toxiclibscore ve toxiclibs_p5 klasörleri. Bu klasörleri Processing – libraries klasörünün içerisine taşıyın.
https://drive.google.com/uc?id=1iN0plPB4i0TaYG9JtF2jSlss-W18AY-F
Arduino içerisine MPU6050 kütüphanesini de eklememiz gerekiyor. Bu sayfada üstteki menüden Dosyalar içerisinden Arduino kütüphaneleri içerisine geliniz. Ya da doğrudan aşağıdaki linke tıklayarak sayfa içeriğine ulaşabilirsiniz.
https://egitim.ahmetcandemir.com.tr/download-category/arduino-kutuphaneleri/
Bu sayfada MPU 6050 İvme ve Gyro Sensörü Kütüphanesi var. Bunu bilgisayarınıza indirin.
Arduino programını açın. Eskiz – Kütüphane Ekle – .ZIP Kütüphanesi Ekle seçeneğini seçerek bilgisayara indirdiğiniz MPU6050 kütüphanesini Arduino içerisine ekleyiniz.
Daha sonra Arduino içerisinde Dosya menüsünde Örnekler – MPU6050 – MPU6050_DMP6 örneğini açınız.
Teapot uygulamasının çalışması için açılan kod sayfasında bir değişiklik yapacağız. Kod satırında 58. satıra gelelim.
satırın baş tarafına // ekleyelim.
//#define OUTPUT_READABLE_YAWPITCHROLL (satır bu şekilde olacak.)
63. satıra gelelim. Satırın baş tarafında bulunan // işaretlerini de silelim.
Bu sayede Teapot uygulamasını çalıştırabileceğiz. Aşağıdaki resimde değişiklik yapılmış hali gözükmektedir.
Arduino kartınızı tasarlamış olduğunuz devrenizle birlikte bilgisayara bağlayınız. Port numarasını seçerek kodları Arduino kartınıza gönderiniz. Kodların gönderimi tamamlandıktan sonra ikinci adıma geçebiliriz.
Şimdi Belgeler – Arduino – libraries – MPU6050 – examples – MPU6050_DMP6 – Processing – MPUTeapot klasörüne gelelim. İçerisinde MPUTeapot.pde dosyası olduğunu göreceksiniz.
Şimdi bilgisayara yüklemiş olduğumuz Processing uygulamasını çalıştıralım. Windows ara çubuğuna Processing yazınca karşınıza gelecektir.) Program açıldığında Dosya menüsünden Aç seçeneğini seçiniz. Açılan pencereden Belgelerim – Arduino – libraries – MPU6050 – examples – MPU6050_DMP6 – Processing – MPUTeapot yolunu takip ederek klasör içerisindeki MPUTeapot.pde dosyasını seçerek Aç deyiniz.
Program bir kod dosyası açacaktır. Kod dosyasının 45. satırında Arduino’ nun bağlı olduğu port numarasını COMXX yazan satırda XX yerine yazmamız gerekecektir. Örneğin Arduino nuzu bilgisayar bağladığınızda kod gönderimi esnasında seçtiğiniz port numarası COM3 ise, buradaki COMXX satırını COM3 olarak değiştireceksiniz. Düzeltilmiş hali aşağıdaki şekildedir.
Daha sonra Ok işareti gösterilen Çalıştır butonuna bastığınızda karşınıza küçük bir pencere açılacaktır. Bu pencerede küçük bir uçak maketi göreceksiniz. Artık MPU6050 sensörünüzü öne arkaya, sağa sola hareke ettirdiğinizde ekrandaki uçak maketininde aynı doğrultuda hareket ettiğini görebilirsiniz.
ÖNEMLİ NOT: Processing programını çalıştırmadan önce MPU6050 sensörünü yatayda düz bir zemin üzerinde konumlandırınız. Uçak simülasyonu ekran açıldığı zaman MPU6050 nin ilk konumunu baz alarak ekranda uçağın konumunu düzgün gösterecektir.
Örnek kodları yine de alt kısma ekledim. İsterseniz buradan kopyala yaparak Arduino kartınız içerisine atabilirsiniz.
KOD BÖLÜMÜ:
NOT: Kod bölümü içerisinde yer alan ve // işareti ile başlayan satırlar açıklama satırlarıdır. O satırda, kod bloğunun ne anlama geldiği ve nasıl çalıştığı ile ilgili bilgi verir. Arduino // işaretli alanı çalıştırmaz. İsterseniz kod satırından // işaret ile başlayan açıklama satırlarını silebilirsiniz.
/*
MPU6050 DMP6
Digital Motion Processor or DMP performs complex motion processing tasks.
- Fuses the data from the accel, gyro, and external magnetometer if applied,
compensating individual sensor noise and errors.
- Detect specific types of motion without the need to continuously monitor
raw sensor data with a microcontroller.
- Reduce workload on the microprocessor.
- Output processed data such as quaternions, Euler angles, and gravity vectors.
The code includes an auto-calibration and offsets generator tasks. Different
output formats available.
This code is compatible with the teapot project by using the teapot output format.
Circuit: In addition to connection 3.3v, GND, SDA, and SCL, this sketch
depends on the MPU6050's INT pin being connected to the Arduino's
external interrupt #0 pin.
The teapot processing example may be broken due FIFO structure change if using DMP
6.12 firmware version.
Find the full MPU6050 library documentation here:
https://github.com/ElectronicCats/mpu6050/wiki
*/
#include "I2Cdev.h"
#include "MPU6050_6Axis_MotionApps20.h"
//#include "MPU6050_6Axis_MotionApps612.h" // Uncomment this library to work with DMP 6.12 and comment on the above library.
/* MPU6050 default I2C address is 0x68*/
MPU6050 mpu;
//MPU6050 mpu(0x69); //Use for AD0 high
//MPU6050 mpu(0x68, &Wire1); //Use for AD0 low, but 2nd Wire (TWI/I2C) object.
/* OUTPUT FORMAT DEFINITION-------------------------------------------------------------------------------------------
- Use "OUTPUT_READABLE_QUATERNION" for quaternion commponents in [w, x, y, z] format. Quaternion does not
suffer from gimbal lock problems but is harder to parse or process efficiently on a remote host or software
environment like Processing.
- Use "OUTPUT_READABLE_EULER" for Euler angles (in degrees) output, calculated from the quaternions coming
from the FIFO. EULER ANGLES SUFFER FROM GIMBAL LOCK PROBLEM.
- Use "OUTPUT_READABLE_YAWPITCHROLL" for yaw/pitch/roll angles (in degrees) calculated from the quaternions
coming from the FIFO. THIS REQUIRES GRAVITY VECTOR CALCULATION.
YAW/PITCH/ROLL ANGLES SUFFER FROM GIMBAL LOCK PROBLEM.
- Use "OUTPUT_READABLE_REALACCEL" for acceleration components with gravity removed. The accel reference frame
is not compensated for orientation. +X will always be +X according to the sensor.
- Use "OUTPUT_READABLE_WORLDACCEL" for acceleration components with gravity removed and adjusted for the world
reference frame. Yaw is relative if there is no magnetometer present.
- Use "OUTPUT_TEAPOT" for output that matches the InvenSense teapot demo.
-------------------------------------------------------------------------------------------------------------------------------*/
//#define OUTPUT_READABLE_YAWPITCHROLL
//#define OUTPUT_READABLE_QUATERNION
//#define OUTPUT_READABLE_EULER
//#define OUTPUT_READABLE_REALACCEL
//#define OUTPUT_READABLE_WORLDACCEL
#define OUTPUT_TEAPOT
int const INTERRUPT_PIN = 2; // Define the interruption #0 pin
bool blinkState;
/*---MPU6050 Control/Status Variables---*/
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)
uint8_t FIFOBuffer[64]; // FIFO storage buffer
/*---Orientation/Motion Variables---*/
Quaternion q; // [w, x, y, z] Quaternion container
VectorInt16 aa; // [x, y, z] Accel sensor measurements
VectorInt16 gy; // [x, y, z] Gyro sensor measurements
VectorInt16 aaReal; // [x, y, z] Gravity-free accel sensor measurements
VectorInt16 aaWorld; // [x, y, z] World-frame accel sensor measurements
VectorFloat gravity; // [x, y, z] Gravity vector
float euler[3]; // [psi, theta, phi] Euler angle container
float ypr[3]; // [yaw, pitch, roll] Yaw/Pitch/Roll container and gravity vector
/*-Packet structure for InvenSense teapot demo-*/
uint8_t teapotPacket[14] = { '$', 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0x00, 0x00, '\r', '\n' };
/*------Interrupt detection routine------*/
volatile bool MPUInterrupt = false; // Indicates whether MPU6050 interrupt pin has gone high
void DMPDataReady() {
MPUInterrupt = true;
}
void setup() {
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
Wire.begin();
Wire.setClock(400000); // 400kHz I2C clock. Comment on this line if having compilation difficulties
#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
Fastwire::setup(400, true);
#endif
Serial.begin(115200); //115200 is required for Teapot Demo output
while (!Serial);
/*Initialize device*/
Serial.println(F("Initializing I2C devices..."));
mpu.initialize();
pinMode(INTERRUPT_PIN, INPUT);
/*Verify connection*/
Serial.println(F("Testing MPU6050 connection..."));
if(mpu.testConnection() == false){
Serial.println("MPU6050 connection failed");
while(true);
}
else {
Serial.println("MPU6050 connection successful");
}
/*Wait for Serial input*/
Serial.println(F("\nSend any character to begin: "));
while (Serial.available() && Serial.read()); // Empty buffer
while (!Serial.available()); // Wait for data
while (Serial.available() && Serial.read()); // Empty buffer again
/* Initializate and configure the DMP*/
Serial.println(F("Initializing DMP..."));
devStatus = mpu.dmpInitialize();
/* Supply your gyro offsets here, scaled for min sensitivity */
mpu.setXGyroOffset(0);
mpu.setYGyroOffset(0);
mpu.setZGyroOffset(0);
mpu.setXAccelOffset(0);
mpu.setYAccelOffset(0);
mpu.setZAccelOffset(0);
/* Making sure it worked (returns 0 if so) */
if (devStatus == 0) {
mpu.CalibrateAccel(6); // Calibration Time: generate offsets and calibrate our MPU6050
mpu.CalibrateGyro(6);
Serial.println("These are the Active offsets: ");
mpu.PrintActiveOffsets();
Serial.println(F("Enabling DMP...")); //Turning ON DMP
mpu.setDMPEnabled(true);
/*Enable Arduino interrupt detection*/
Serial.print(F("Enabling interrupt detection (Arduino external interrupt "));
Serial.print(digitalPinToInterrupt(INTERRUPT_PIN));
Serial.println(F(")..."));
attachInterrupt(digitalPinToInterrupt(INTERRUPT_PIN), DMPDataReady, RISING);
MPUIntStatus = mpu.getIntStatus();
/* Set the DMP Ready flag so the main loop() function knows it is okay to use it */
Serial.println(F("DMP ready! Waiting for first interrupt..."));
DMPReady = true;
packetSize = mpu.dmpGetFIFOPacketSize(); //Get expected DMP packet size for later comparison
}
else {
Serial.print(F("DMP Initialization failed (code ")); //Print the error code
Serial.print(devStatus);
Serial.println(F(")"));
// 1 = initial memory load failed
// 2 = DMP configuration updates failed
}
pinMode(LED_BUILTIN, OUTPUT);
}
void loop() {
if (!DMPReady) return; // Stop the program if DMP programming fails.
/* Read a packet from FIFO */
if (mpu.dmpGetCurrentFIFOPacket(FIFOBuffer)) { // Get the Latest packet
#ifdef OUTPUT_READABLE_YAWPITCHROLL
/* Display Euler angles in degrees */
mpu.dmpGetQuaternion(&q, FIFOBuffer);
mpu.dmpGetGravity(&gravity, &q);
mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);
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
#ifdef OUTPUT_READABLE_QUATERNION
/* Display Quaternion values in easy matrix form: [w, x, y, z] */
mpu.dmpGetQuaternion(&q, FIFOBuffer);
Serial.print("quat\t");
Serial.print(q.w);
Serial.print("\t");
Serial.print(q.x);
Serial.print("\t");
Serial.print(q.y);
Serial.print("\t");
Serial.println(q.z);
#endif
#ifdef OUTPUT_READABLE_EULER
/* Display Euler angles in degrees */
mpu.dmpGetQuaternion(&q, FIFOBuffer);
mpu.dmpGetEuler(euler, &q);
Serial.print("euler\t");
Serial.print(euler[0] * 180/M_PI);
Serial.print("\t");
Serial.print(euler[1] * 180/M_PI);
Serial.print("\t");
Serial.println(euler[2] * 180/M_PI);
#endif
#ifdef OUTPUT_READABLE_REALACCEL
/* Display real acceleration, adjusted to remove gravity */
mpu.dmpGetQuaternion(&q, FIFOBuffer);
mpu.dmpGetAccel(&aa, FIFOBuffer);
mpu.dmpGetGravity(&gravity, &q);
mpu.dmpGetLinearAccel(&aaReal, &aa, &gravity);
Serial.print("areal\t");
Serial.print(aaReal.x);
Serial.print("\t");
Serial.print(aaReal.y);
Serial.print("\t");
Serial.println(aaReal.z);
#endif
#ifdef OUTPUT_READABLE_WORLDACCEL
/* Display initial world-frame acceleration, adjusted to remove gravity
and rotated based on known orientation from Quaternion */
mpu.dmpGetQuaternion(&q, FIFOBuffer);
mpu.dmpGetAccel(&aa, FIFOBuffer);
mpu.dmpGetGravity(&gravity, &q);
mpu.dmpGetLinearAccel(&aaReal, &aa, &gravity);
mpu.dmpGetLinearAccelInWorld(&aaWorld, &aaReal, &q);
Serial.print("aworld\t");
Serial.print(aaWorld.x);
Serial.print("\t");
Serial.print(aaWorld.y);
Serial.print("\t");
Serial.println(aaWorld.z);
#endif
#ifdef OUTPUT_TEAPOT
/* Display quaternion values in InvenSense Teapot demo format */
teapotPacket[2] = FIFOBuffer[0];
teapotPacket[3] = FIFOBuffer[1];
teapotPacket[4] = FIFOBuffer[4];
teapotPacket[5] = FIFOBuffer[5];
teapotPacket[6] = FIFOBuffer[8];
teapotPacket[7] = FIFOBuffer[9];
teapotPacket[8] = FIFOBuffer[12];
teapotPacket[9] = FIFOBuffer[13];
Serial.write(teapotPacket, 14);
teapotPacket[11]++; // PacketCount, loops at 0xFF on purpose
#endif
/* Blink LED to indicate activity */
blinkState = !blinkState;
digitalWrite(LED_BUILTIN, blinkState);
}
}
DEVRENİN ÇALIŞMASI:
MPU6050 sensörünüzü öne arkaya, sağa sola hareke ettirdiğinizde ekrandaki uçak maketininde aynı doğrultuda hareket ettiğini görebilirsiniz. Uygulama, bilgisayar ekranında MPU6050’nin gerçek zamanlı dönüşünü size görsel olarak sunar.
Bu Devre Ne Amaçla Tasarlanmıştır?
Eğitim: Sensör verilerini görselleştirerek ivme, açı ve dönüşü anlama.
Robotik Uygulamalar: Robotların veya drone’ların yönelim hesaplamaları.
Simülasyon Sistemleri: Hareketli kontrol sistemlerinin (joystick, head tracking, vs.) test edilmesi.
Gelişmiş Görselleştirme: 3D hareket takibi, sanal gerçeklik başlangıç uygulamaları.
Eğer devreyi Arduino Uno ile tasarlamak isterseniz aşağıdaki devreyi tasarlayabilirsiniz. Diğer işlemler aynıdır.
DEVRE BAĞLANTI ŞEMASI: (ARDUINO UNO İÇİN)
Arduino MPU6050 İle 3D Model Teapot Uygulaması
Youtube videosu yakında burada olacak. Takipte kalın.
Devre hakkında yorumlarınızı aşağıdaki yorum kısmına yazabilirsiniz. Youtube kanalımızda da mBlock ve Arduino ile ilgili ders videoları bulabileceksiniz. Youtube kanalıma abone olmayı da unutmayınız.









Yorum Yap