Robotik sistemlerde, endüstriyel otomasyonda veya hobi projelerinde analog sensörler (örneğin potansiyometre, analog sıcaklık sensörleri, basınç transdüserleri veya mesafe sensörleri) ile çalışırken en sık karşılaşılan sorun sinyal gürültüsü (noise) ve anlık dalgalanmalardır. Arduino'nun ADC (Analog-to-Digital Converter) pininden okunan ham değer sabit bir fiziksel ortamda dahi titreşebilir.

Geliştiriciler bu gürültüyü engellemek için genellikle basit bir Hareketli Ortalama (Moving Average) algoritmasına başvurur. Ancak hareketli ortalama, sinyale ciddi bir gecikme (phase lag) ekler. Bu yazıda, havacılık ve uzay sanayisinde Apollo görevlerinden beri kullanılan efsanevi Kalman Filtresi algoritmasının tek boyutlu (1D) halini Arduino'ya uyarlayacağız.

1. Yöntem: Hareketli Ortalama (Moving Average) ve Sınırları

Hareketli ortalama, son $N$ adet okunan değerin aritmetik ortalamasını alarak çalışır:

// Klasik 10 Adımlı Hareketli Ortalama Mantığı
float runningAverage(float rawVal) {
    static float readings[10];
    static int readIndex = 0;
    static float total = 0;

    total -= readings[readIndex];
    readings[readIndex] = rawVal;
    total += readings[readIndex];
    readIndex = (readIndex + 1) % 10;

    return total / 10.0;
}

Dezavantajı: Eğer ortamda ani bir gerçek değişim olursa (örneğin bir robot nesneye aniden yaklaşırsa), hareketli ortalama bu ani değişimi hemen yansıtamaz; $N$ adım geriden gelir. Gecikme ile pürüzsüzlük arasında sürekli ödün vermek zorunda kalırsınız.

2. Yöntem: 1 Boyutlu (1D) Kalman Filtresi

Kalman filtresi, sistemin geçmiş durumunu ve yeni gelen ölçümün varyansını (güvenilirlik katsayısını) kullanarak en olası gerçek değeri matematiksel olarak tahmin eder. Bir tahmin (prediction) ve bir güncelleme (update) adımından oluşur.

1D Kalman filtresinde iki temel parametre ayarlanır:

  • $q$ (Süreç Gürültüsü - Process Noise): Sistemin kendi içinde ne kadar hızlı değiştiğine dair güven katsayısı (Genellikle 0.01 - 0.1 arası seçilir).
  • $r$ (Ölçüm Gürültüsü - Measurement Noise): Sensörün ürettiği elektriksel gürültü varyansı (Sensör çok gürültülüyse büyütülür, örn: 1.0 - 5.0).

Arduino C++ Kalman Filtresi Sınıfı ve Örnek Kod

Aşağıdaki kod hiçbir harici kütüphaneye ihtiyaç duymadan, doğrudan Arduino Uno, Mega veya ESP32 üzerinde koşan saf C++ Kalman filtresi implementasyonudur:

// Basit ve Hızlı 1 Boyutlu Kalman Filtresi Sınıfı
class SimpleKalmanFilter {
private:
    float err_measure; // r: Ölçüm hatası (Gürültü)
    float err_estimate;// e: Tahmin hatası
    float q;           // q: Süreç varyansı
    float current_estimate;
    float last_estimate;
    float kalman_gain;

public:
    SimpleKalmanFilter(float mea_e, float est_e, float q_val) {
        err_measure = mea_e;
        err_estimate = est_e;
        q = q_val;
        current_estimate = 0;
        last_estimate = 0;
        kalman_gain = 0;
    }

    float updateEstimate(float mea) {
        kalman_gain = err_estimate / (err_estimate + err_measure);
        current_estimate = last_estimate + kalman_gain * (mea - last_estimate);
        err_estimate = (1.0 - kalman_gain) * err_estimate + fabs(last_estimate - current_estimate) * q;
        last_estimate = current_estimate;

        return current_estimate;
    }

    void setParameters(float mea_e, float est_e, float q_val) {
        err_measure = mea_e;
        err_estimate = est_e;
        q = q_val;
    }
};

// Parametreler: Ölçüm hatası=2.0, Tahmin hatası=2.0, Süreç gürültüsü=0.05
SimpleKalmanFilter kalmanFilter(2.0, 2.0, 0.05);

void setup() {
    Serial.begin(115200);
}

void loop() {
    // A0 pininden analog sensör oku (0 - 1023)
    int rawValue = analogRead(A0);

    // Kalman filtresinden geçir
    float filteredValue = kalmanFilter.updateEstimate(rawValue);

    // Arduino Seri Çizici (Serial Plotter) Formatında Yazdır:
    Serial.print("Ham_Veri:");
    Serial.print(rawValue);
    Serial.print(",");
    Serial.print("Kalman_Filtreli:");
    Serial.println(filteredValue);

    delay(20); // 50 Hz örnekleme hızı
}

Karşılaştırma: Seri Çizici Analizi

Arduino IDE'nin Araçlar -> Seri Çizici (Serial Plotter) ekranını açtığınızda:

  • Mavi Çizgi (Ham Veri): Sürekli yukarı aşağı sıçrayan, testere dişli ve gürültülü bir grafik çizer.
  • Kırmızı Çizgi (Kalman Filtreli): Tüm gürültüyü pürüzsüzleştirir ancak hareketli ortalamanın aksine, sensörde ani bir basamak değişimi olduğunda gecikmeden yeni değere kilitlenir.
Mühendislik Tavsiyesi: Özellikle PID kontrol algoritmalarında (örneğin sıcaklık kontrolü veya drone motor dengelemesi) hareketli ortalama sistemde salınıma (oscillation) yol açabilirken, Kalman filtresi gerçek zamanlı dinamik tepki sunduğu için sistem kararlılığını maksimize eder.