Sensör füzyonu, birden fazla sensörün okumalarını birleştirerek tek bir sensörün sağlayabileceğinden daha doğru, daha kararlı veya daha eksiksiz bir sonuç elde etme tekniğidir. IoT geliştiricileri için bu, çoğu zaman titreyen ve kayan bir sinyal ile bir dashboard'da ya da modelde güvenebileceğiniz bir sinyal arasındaki farktır. Bu makale, temel füzyon yaklaşımlarını sade bir dille açıklıyor, füzyonun ne zaman uçta ne zaman bulutta yapılması gerektiğini gösteriyor ve birleştirilmiş değerleri MQTT ile yayınlayan çalışan ESP32 ve Python kodu sunuyor.
Sensörleri Neden Birleştirmeli
Her sensörün zayıf yönleri vardır. Bir ivmeölçer, cihaz hareketsizken eğimi iyi ölçer ancak her titreşimde sapar. Bir jiroskop dönüşü pürüzsüz ölçer ancak integrali alınmış açısı zamanla kayar. GPS mutlak konum verir ama yavaş güncellenir ve ağaçların altında sıçramalar yapar; tekerlek odometrisi pürüzsüzdür ama hata biriktirir. Aynı tanktaki iki ucuz sıcaklık probu birbirinden biraz farklı değer okur ve her birinde ara sıra ani sıçramalar görülür.
Füzyon, bu zayıflıkların farklı olmasından yararlanır. Bir sensör yüksek frekanslarda gürültülüyse ve diğeri düşük frekanslarda kayıyorsa, ikisini birleştirmek her alanda iyi olan bir sinyal verir. İki sensör aynı büyüklüğü birbirinden bağımsız gürültüyle ölçüyorsa, ağırlıklı bir birleşim her birinden tek başına daha hassastır. Bir sensör arızalandığında ise birleştirilmiş bir tahmin, sessizce yanlış bir değer raporlamak yerine tutarsızlığı tespit edebilir.
Sensör Füzyonunun Üç Seviyesi
| Seviye | Neler birleştirilir | Örnek | Tipik yöntem |
|---|---|---|---|
| Düşük seviye (veri) | Aynı büyüklüğün ham ölçümleri | İki sıcaklık probu, ivmeölçer artı jiroskop | Ağırlıklı ortalama, tamamlayıcı filtre, Kalman filtresi |
| Özellik seviyesi | Farklı sensörlerden türetilen özellikler | Titreşim RMS'i artı motor akımı artı sıcaklık | Bir ML modeli için özellik vektörleri |
| Karar seviyesi | Ayrı dedektörlerin çıktıları | Kamera "kişi" der, PIR "hareket" der | Oylama, kurallar, Bayesçi birleştirme |
Bu makalenin odağı düşük seviye füzyondur, çünkü tamamlayıcı ve Kalman filtreleri gibi filtreler burada yer alır. Özellik seviyesi füzyon ise makine öğrenmesi modellerinin günlük girdisidir; örneğin kestirimci bakım için makine öğrenmesi yazısında olduğu gibi titreşim, sıcaklık ve akım birlikte, hiçbirinin tek başına net göstermediği bozulmayı ortaya çıkarır.
Tamamlayıcı Filtre
Tamamlayıcı filtre, işe yarayan en basit füzyon yöntemidir ve ataletsel sensörler için iyi bir başlangıç noktasıdır. Bir eğim açısını tahmin etmek için kısa vadeli değişimlerde jiroskop hızının integralini alır ve uzun vadeli kaymayı gidermek için sonucu yavaşça ivmeölçer açısına doğru çeker:
angle = alpha * (angle + gyro_rate * dt) + (1 - alpha) * accel_angle
alpha yaklaşık 0,98 ve örnekleme periyodu 10 ms olduğunda, saniyenin kesirlerinde jiroskop, birkaç saniyelik ölçekte ise ivmeölçer baskın olur. Filtre matris gerektirmez, bir mikrodenetleyicide mikrosaniyeler içinde çalışır ve ayarlaması kolaydır: çıktı gürültülüyse alpha değerini artırın, çıktı kayıyorsa azaltın.
Kalman Filtresi
Kalman filtresi aynı fikri genelleştirir. Durumun ve kendi belirsizliğinin bir tahminini tutar, durumun nasıl değişeceğini öngörür, ardından her ölçümle öngörüyü düzeltir; düzeltmeyi, ölçüme öngörüye kıyasla ne kadar güvendiğine göre ağırlıklandırır. Ölçüm gürültülü olduğunda filtre öngörüye dayanır; öngörü belirsiz olduğunda ölçüme dayanır.
İki sensörlü tek bir büyüklük için Kalman güncellemesi, tamamını okuyabileceğiniz kadar kısadır:
import json
import random
import time
import uuid
import paho.mqtt.client as mqtt
class Kalman1D:
def __init__(self, x0, p0=1.0, q=0.001):
self.x, self.p, self.q = x0, p0, q # tahmin, varyansı, süreç gürültüsü
def predict(self):
self.p += self.q
def update(self, z, r):
k = self.p / (self.p + r) # Kalman kazancı
self.x += k * (z - self.x)
self.p *= (1 - k)
return self.x
BASE = f"connectmq/demo/{uuid.uuid4().hex[:8]}/tank1"
client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id="fusion-" + uuid.uuid4().hex[:8])
client.connect("broker.connectmq.com", 1883, keepalive=60)
client.loop_start()
kf = Kalman1D(x0=20.0)
true_temp = 20.0
R_PT100, R_NTC = 0.05 ** 2, 0.4 ** 2 # veri sayfalarından veya testlerden ölçüm varyansları
for _ in range(300):
true_temp += random.gauss(0, 0.02)
pt100 = true_temp + random.gauss(0, 0.05)
ntc = true_temp + random.gauss(0, 0.4) + (5 if random.random() < 0.02 else 0) # ara sıra sıçrama
kf.predict()
if abs(ntc - kf.x) < 3 * (R_NTC + kf.p) ** 0.5: # makul olmayan okumaları ele
kf.update(ntc, R_NTC)
fused = kf.update(pt100, R_PT100)
payload = {"ts": int(time.time() * 1000), "value": round(fused, 3), "variance": round(kf.p, 6),
"raw": {"pt100": round(pt100, 3), "ntc": round(ntc, 3)}}
client.publish(f"{BASE}/temperature/fused", json.dumps(payload))
time.sleep(1)
client.loop_stop()
client.disconnect()
pip install paho-mqtt ile kurun ve birleştirilmiş değeri ham okumaların yanında görmek için mosquitto_sub -h broker.connectmq.com -p 1883 -i fusion-watch-$RANDOM -t "connectmq/demo/+/tank1/#" -v ile abone olun. Kapıya (gate) dikkat edin: mevcut tahminden üç standart sapmadan fazla ayrışan okumalar atlanır; filtre NTC sıçramalarını bu şekilde reddeder. Varyansı değerle birlikte yayınlamak, tüketicilerin tahminin ne kadar güvenilir olduğunu bilmesini sağlar.
GPS ve bir IMU'dan konum ve hız gibi çok boyutlu problemlerde aynı yapı matrislerle kullanılır; doğrusal olmayan sistemlerde ise genişletilmiş (extended) veya kokusuz (unscented) Kalman filtresi kullanılır. Python'daki FilterPy gibi kütüphaneler ya da yönelim için Madgwick ve Mahony filtreleri, bunları elle uygulama zahmetinden sizi kurtarır.
Uçta Füzyon: ESP32 Örneği
Ataletsel füzyon sensöre yakın çalışmalıdır, çünkü hızlı ve düzenli aralıklı örneklere, çoğu zaman 100 Hz veya daha fazlasına ihtiyaç duyar. Her ham örneği MQTT üzerinden yayınlamak bant genişliğini ve pili boşa harcar ve titreşim (jitter) ekler. Daha iyi kalıp, füzyonu cihazda yapmak ve sonucu makul bir hızla yayınlamaktır.
Bu sketch, bir ESP32 üzerinde I2C ile bir MPU6050'yi okur, 100 Hz'de tamamlayıcı filtre çalıştırır ve birleştirilmiş pitch açısını saniyede iki kez broker.connectmq.com adresine yayınlar. Adafruit MPU6050 ve PubSubClient kütüphanelerini kullanır.
#include <WiFi.h>
#include <PubSubClient.h>
#include <Adafruit_MPU6050.h>
#include <Adafruit_Sensor.h>
#include <Wire.h>
const char* WIFI_SSID = "YOUR_WIFI";
const char* WIFI_PASS = "YOUR_WIFI_PASSWORD";
const char* BROKER = "broker.connectmq.com";
const char* TOPIC = "connectmq/demo/imu-7f3a/arm1/pitch";
WiFiClient net;
PubSubClient mqtt(net);
Adafruit_MPU6050 mpu;
float pitch = 0.0f;
const float ALPHA = 0.98f;
unsigned long lastSample = 0, lastPublish = 0;
void connectMqtt() {
while (!mqtt.connected()) {
String id = "esp32-imu-" + String((uint32_t)ESP.getEfuseMac(), HEX);
if (!mqtt.connect(id.c_str())) delay(2000);
}
}
void setup() {
Serial.begin(115200);
WiFi.begin(WIFI_SSID, WIFI_PASS);
while (WiFi.status() != WL_CONNECTED) delay(500);
mqtt.setServer(BROKER, 1883);
if (!mpu.begin()) {
Serial.println("MPU6050 not found");
while (true) delay(1000);
}
mpu.setGyroRange(MPU6050_RANGE_250_DEG);
mpu.setFilterBandwidth(MPU6050_BAND_44_HZ);
lastSample = micros();
}
void loop() {
if (!mqtt.connected()) connectMqtt();
mqtt.loop();
if (micros() - lastSample >= 10000) { // 100 Hz
float dt = (micros() - lastSample) / 1e6f;
lastSample = micros();
sensors_event_t a, g, temp;
mpu.getEvent(&a, &g, &temp);
float accelPitch = atan2f(-a.acceleration.x,
sqrtf(a.acceleration.y * a.acceleration.y + a.acceleration.z * a.acceleration.z)) * 180.0f / PI;
float gyroRate = g.gyro.y * 180.0f / PI; // rad/s'den derece/s'ye
pitch = ALPHA * (pitch + gyroRate * dt) + (1.0f - ALPHA) * accelPitch;
}
if (millis() - lastPublish >= 500) { // saniyede 2 mesaj
lastPublish = millis();
char payload[64];
snprintf(payload, sizeof(payload), "{\"pitch\":%.2f,\"unit\":\"deg\"}", pitch);
mqtt.publish(TOPIC, payload);
}
}
imu-7f3a topic bölümünü benzersiz bir değerle değiştirin. Üretim cihazında, ConnectMQ kullanıcı adınız, parolanız ve client ID'nizle 8883 portunda WiFiClientSecure'a geçin; TLS kurulumu ESP32 MQTT eğitiminde ayrıntılı olarak anlatılıyor.
Uçta mı Bulutta mı Füzyon: Nasıl Karar Verilir
- Füzyonu uçta yapın: sensörler aynı cihazdaysa, örnekleme hızları yüksekse, gecikme önemliyse (dengeleme, stabilizasyon, güvenlik) ya da bant genişliği ve pil sınırlıysa.
- Füzyonu bulutta veya bir sunucuda yapın: sensörler farklı cihazlardaysa, hızlar düşükse, geçmiş bağlama ihtiyacınız varsa ya da algoritmayı firmware güncellemesi olmadan değiştirmek istiyorsanız.
- Geliştirme sırasında bir süre ikisini de yayınlayın: filtreyi gerçeğe karşı doğrulayabilmek için ham değerleri düşürülmüş bir hızda ve birleştirilmiş değerleri birlikte gönderin.
- Cihazlar arası füzyon yaparken zaman damgasını her zaman kaynakta ekleyin, çünkü broker'a varış sırası ölçüm sırası değildir.
Bu, uç yapay zeka nedir yazısında ele alınan dengenin aynısıdır: hesaplama, verinin ve gecikme gereksinimlerinin bulunduğu yere taşınır.
Sensör Füzyonunda Sık Yapılan Hatalar
- Yanlış gürültü parametreleri. Bir Kalman filtresi, varsayılan ölçüm ve süreç gürültüsü kadar iyidir. Gürültüyü tahmin etmek yerine hareketsiz bir kayıttan ölçün.
- Uyumsuz eksenler ve birimler. Jiroskoplar çoğu zaman rad/s raporlar; ivmeölçer eksenleri varsaydığınızdan farklı monte edilmiş olabilir. Kartı elle eğerek işaretleri kontrol edin.
- Düzensiz örnekleme zamanlaması. Filtreler bilinen bir
dtvarsayar. Sabit olduğunu varsaymak yerine zaman damgalarından hesaplayın. - Senkronize olmayan kaynaklar. Saatleri saniyelerce farklı olan iki cihazı birleştirmek yapay bozulmalar üretir. NTP ile senkronize edin ve kaynak zaman damgalarını taşıyın.
- Sensör arızalarını gizlemek. Füzyon, arızalanan bir sensörü maskeleyebilir. Arızaların görünür kalması için ham sağlık göstergelerini veya inovasyon değerlerini yayınlayın; bu, IoT anomali tespiti için de girdi sağlar.
Birleştirilmiş Veri Sonra Nereye Gider
Birleştirilmiş değerler dashboard'lar, uyarılar ve modeller için daha iyi girdilerdir. ConnectMQ, bunları cihazlardan tüketicilere taşıyan barındırılan MQTT broker görevi görür: canlı topic gezgini birleştirilmiş ve ham topic'leri yan yana gösterir; eşik tabanlı uyarı kuralları ise güvenli sınırın ötesindeki bir eğim açısı gibi birleştirilmiş bir değer üzerinde tetiklenebilir. Modellerin ve bağlantılı cihazların daha geniş ölçekte nasıl birlikte çalıştığını görmek için yapay zeka ve IoT rehberine bakın.
ConnectMQ ile Başlayın
Örnekleri önce genel MQTT test broker'ı üzerinde deneyin; ardından cihazlarınız için özel kimlik bilgileri ve TLS almak üzere app.connectmq.com adresinde kredi kartı gerektirmeden ücretsiz bir Serverless broker oluşturun.
Sık Sorulan Sorular
IoT'de sensör füzyonu nedir?
Sensör füzyonu, birden fazla sensörün ölçümlerini birleştirerek tek bir sensörden daha doğru, kararlı veya eksiksiz bir tahmin üretir; örneğin bir ivmeölçer ve bir jiroskoptan kaymasız bir eğim açısı elde etmek.
Tamamlayıcı filtre mi yoksa Kalman filtresi mi kullanmalıyım?
Mikrodenetleyicilerdeki basit yönelim problemleri için tamamlayıcı filtreyle başlayın. Gürültü karakteristikleri bilinen sensörleri birleştirmeniz, birbiriyle ilişkili birkaç durumu tahmin etmeniz veya belirsizliği raporlamanız gerektiğinde Kalman filtresi kullanın.
Sensör füzyonu cihazda mı yoksa bulutta mı çalışmalı?
Sensörler yerel ve hızlı olduğunda cihazda çalıştırın, çünkü her ham örneği göndermek maliyetlidir ve titreşim ekler. Sensörler farklı cihazlardaysa veya güncelleme hızı düşükse merkezi olarak çalıştırın.
Uçta füzyon yaparsam ham veriye yine de erişebilir miyim?
Evet. Yaygın bir kalıp, birleştirilmiş değerleri sürekli, ham değerleri ise ayrı topic'lerde daha düşük bir hızda veya talep üzerine yayınlamaktır; bu, doğrulamaya izin verirken bant genişliğini düşük tutar.



