https://www.youtube.com/watch?v=EMkmC6QPMf4
Kalman filtresinin ne olduğu ve ne işe yaradığı hakkında yüzeysel olarak bahsetmek gerekirse: Sensör tahminin belli bir modele (formüle) göre işlendiği bir tahmin yöntemidir. Rudolf Kalman tarafından tasarlanan bu sistemin ilk kullanım alanı NASA'nın Apollo projesidir. konum hız ve yörünge gibi tahminlerin yapılmasında kullanılmaktadır.
MPU6050 Hobi seviyesinde çalışmalar ve öğrenim amaçlı yaygın olarak kullanılan düşük maliyetli bir sensör modülüdür. X, Y ve Z ekseninde Jiroskop ve İvmeölçer bulunduran bu sensör toplamda 6 eksenlidir. jiroskop tarafında ±250, ±500, ±1000, ±2000 °/s (derece/saniye) ve ivmeölçer tarafında ±2g, ±4g, ±8g, ±16g (1g ≈ 9.81 m/s²) hassasiyet konfigürasyonları vardır. kendi içinde DMP (Dijital Hareket İşlemcisi) bulunur.
Bu konuda açıklama yazıya giriş yapmaya başlamadan önce referansı sizinle paylaşmamda fayda olacaktır.
Arduino ve ESP32 kullananlar için Kristian Sloth Lauszus'un C++ dili ile yayınladığı Kalman Filtresi kütüphanesi, ve Arduino Uno ile MPU6050 ile kullanım örneğinin gösterilmesi:
https://github.com/TKJElectronics/KalmanFilter
(bu başlıkta paylaşılan kodun referans kaynağı) STM32 için leech001 kullanıcı adıyla Konstantin Bulanov'un C dili ile yayınladığı MPU6050 kalman Filtresi kütüphanesi:
https://github.com/leech001/MPU6050
MPU6050 Datasheet:
https://www.alldatasheet.com/datasheet-pdf/view/1132809/TDK/MPU6050.html
dileyenler olursa DMP örneği için en kapsamlı kütüphane jrowberg'in i2cdevlib kütüphanesini inceleyebilir.
https://github.com/jrowberg/i2cdevlib/tree/master/STM32HAL
https://github.com/spacemonochrome/STM32_KalmanFilter_MPU6050
eğer kopyaladığınız halde dosyalar gözükmüyorsa refresh etmenizde fayda olacaktır. proje klasörüne gelip sağ tık yaparak refresh edebilirsiniz. ve eğer ki dosya klasörünü bulmak istiyorsanız yine aynı yerden system explorer üzerinden bakabilirsiniz.
istenirse parametre ayarları;
mpu6050.c dosyasında X ve Y eksenleri için ayrı ayrı düzeltme parametreleri bulunuyor. Z ekseni için ise bir düzeltme uygulamıyor (bunu yapmak istediğiniz takdirde bir manyetometre kullanmanızda fayda olacaktır.). buradaki değerleri kendi ihtiyacınıza göre değiştirmeniz gerekmektedir.
.Q_angle (0.001f): MPU-6050'nin jiroskop verisindeki açısal tahmin hatalarını temsil eder. Değer düşükse, jiroskop verisine daha çok güvenilir. Artırmak, ivmeölçer verilerine daha çok ağırlık verilmesini sağlar (örneğin, titreşimli ortamlarda faydalı olabilir). Azaltmak, jiroskopun uzun vadeli driftini önler.
.Q_bias (0.003f): Jiroskop bias (drift) tahminindeki belirsizlik. MPU-6050'de jiroskopun zamanla birikebilen hatasını düzeltir. Artırmak, bias güncellemesini hızlandırır ama gürültüyü artırabilir. Azaltmak, daha stabil ama yavaş bir düzeltme sağlar.
.R_measure (2.0f): İvmeölçer verilerindeki gürültüyü yansıtır. MPU-6050'nin ivmeölçeri kısa vadede açı tahmini için kullanılır, ancak gürültülü olabilir. Artırmak, ivmeölçere güveni azaltır ve jiroskopa kayar. Azaltmak, ivmeölçer verilerine daha çok güvenerek hızlı tepki verir.
Bu kod daha önceden yayınlanan STM32 MPU6050 Kalman filtresinden farklı olarak jiroskop ve ivmeölçer verilerini ayrı ayrı alma fonksiyonları kaldırılmış onun yerine tek kod satırı ile tek seferde 14 baytlık ivme sıcaklık jiroskop verileri olarak almıştır. bunun yapılmasındaki amaç kodun aynı zamanda DMA metoduna uygun olmasıdır. her I2C_Read_DMA fonksiyonuna karşılık I2C_CallBack kesmesi gerçekleştiği için jiroskop ivme sıcaklık değerlerini ayrı ayrı çağırmak yerine tek seferde çağırmak işlemciyi daha az meşgul edecektir. fakat bu örneğimizde bu kullanılmamıştır, polling metod kullanılmıştır. istenirse DMA kullanılabilir.
bununla beraber milisaniye mertebesinde çalışan HalGetTick fonksiyonu yerine mikrosaniye mertebesinde çalışan DWT kullanılmıştır. 72 Mhz'lik STM32F103C8T6 işlemcisi I2C hattından 400 Khz ile haberleştiği takdirde aşağıdaki kod döngüsünü 750 - 850 küsür mikrosaniye civarında gerçekleştirmektedir. dolayısıyla zaman hassasiyeti olarak HalGetTick bu noktada yetersiz kalmaktadır. bu da sensörden sağlıklı veri okunmasını engeller. time elapsed değeri ile sensörden veri okunması ve daha sonra gelen veri ile belirli hesaplamalar yapılması durumunda bir tam turda ne kadar süre geçtiğini mikrosaniye cinsinden verir. 1000 mikrosaniye = 1 milisaniye. DWT kullanımı ile ilgili yazı aşağıdaki linktedir.
https://teslaninsovalyesi.blogspot.com/2025/07/milisaniye-mikrosaniye-zaman-olcumu-ve.html
yayınlanan MPU6050_t struct veri yapısında offset hatası için değişkenler kayıtlı değildir ve bunun için bir fonksiyon yazılmamıştır. bu kodda istenirse offset hata kalibrasyonu yapılabilir, istenmezse de yapılmaz. fakat sağlıklı bir ölçüm için yapılması doğru olacaktır.
/* USER CODE BEGIN Includes */
#include "mpu6050.h"
/* USER CODE END Includes */
/* USER CODE BEGIN 0 */
MPU6050_t MPU6500;
uint32_t time_elapsed;
/* USER CODE END 0 */
/* USER CODE BEGIN 2 */
MPU6050_Init(&hi2c1);
MPU6050_Calibration_offset(&hi2c1, &MPU6500);
DWT_Init();
/* USER CODE END 2 */
/* USER CODE BEGIN WHILE */
while (1)
{
uint32_t time_start = DWT_GetMicros();
MPU6050_Read_WithKalman(&hi2c1, &MPU6500, time_start);
time_elapsed = DWT_GetDeltaMicros(time_start);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
Yorumlar
Yorum Gönder