Okullar için Robotik ve Mühendislik · anaokulundan liseye

7. ünite / 10

Uzaktan eyleyiciler ve canlı pano

Röle, MOSFET ve servoyu MQTT ile güvenle sür: idempotent komut, komut kimliği, cihaz gölgesi; telemetriyi canlı panoda çiz.

Bu ünitenin sonunda

  • "Çevir" ile "ayarla" komutlarının yinelenen teslimde farkını göstermek
  • Komut kimliği ve kalıcı durum konusuyla istenen/bildirilen gölgeyi kurmak
  • Halka tampon ve min/max seyreltmeyle sabit bellekli canlı grafik çizmek
  • Histerezisli eşik uyarısının neden titreşmediğini açıklamak

Ders notları

Sensör okumak tek yönlüdür; bir fanı, pencereyi ya da pompayı uzaktan sürmek ise iki yönlü ve risklidir. Komut kaybolabilir, iki kez gelebilir, cihaz o anda kapalı olabilir. Bu ünitede komutları bu durumların hepsine dayanıklı yapacağız.

Eyleyici donanımı

  • MOSFET (IRF540): DC fan ya da LED şeridi için düşük taraf anahtar. IRF540 3,3 V kapı geriliminde tam açılmaz; mantık seviyeli bir MOSFET ya da sürücü transistör kullan, endüktif yükte flyback diyot koy.
  • Röle modülü: şebeke yükü için yalıtım sağlar ama mekaniktir; ömrü anahtarlama sayısıyla sınırlıdır.
  • Servo (SG90): 50 Hz PWM, 0,5–2,5 ms darbe; pencere açısı gibi mutlak konum komutları için doğaldır.

İdempotent komut

QoS 1 "en az bir kez" teslim eder: PUBACK kaybolursa mesaj ikinci kez gelir. {"cmd":"toggle"} iki kez uygulanınca fan istenen durumun tersinde kalır. {"on":true} ise kaç kez gelirse gelsin aynı sonucu verir: buna idempotent denir. Bir adım ileri: her komuta artan bir id ver, cihaz son uyguladığı kimliği saklasın ve küçük ya da eşit kimliği yok saysın.

gölge farkı = { alan : istenen ≠ bildirilen }

Cihaz gölgesi iki durum tutar: pano "istenen"i (sera/01/fan/set) yazar, cihaz gerçekten uyguladığını "bildirilen" olarak kalıcı (retained) bir konuya (sera/01/fan/state) yayımlar. Fark boş değilse komut henüz uygulanmamıştır; pano düğmeyi "bekliyor" gösterir, "açık" değil.

Canlı pano

Cihazda ya da tarayıcıda sınırsız dizi tutulamaz. Halka tampon sabit kapasitelidir, en eski değer ezilir. Ekran 300 piksel genişse 10 000 noktayı çizmek anlamsızdır; min/max seyreltme her kovadan en küçük ve en büyük değeri alır, böylece kısa bir tepe kaybolmaz (basit ortalama onu siler). Uyarı için histerezis kullan: 30 °C üstünde aç, 28 °C altında kapat; tek eşikte değer 30 civarında gezinirken uyarı saniyede birkaç kez açılıp kapanır. Gerçek projede bu panoyu Node-RED ya da Grafana ile de kurabilirsin; ilkeler aynıdır.

Simülasyonlar

Uzaktan eyleyici: idempotent komut ve cihaz gölgesi

Kayıplı bir bağlantıda röleye 20 komut gönder. "Çevir" (toggle) komutu yinelenen teslimde durumu bozar; "ayarla" (set) ve komut kimliği bozmaz. Altta istenen/bildirilen gölge farkını gör.

KomutSon röleBeklenenUygulananSonuç
toggle ("çevir")KAPALIKAPALI24doğru
set {"on": true/false}KAPALIKAPALI24doğru
set + komut kimliğiKAPALIKAPALI20doğru
Bağlantı: 20 komutta 4 yinelenen, 0 kayıp teslim.

Cihaz gölgesi

{ "desired": { "role": 1, "servo": 90 }, "reported": { "role": 0, "servo": 0 }, "delta": { "role": 1, "servo": 90 } }

Canlı pano: halka tampon, seyreltme, uyarı

Üç cihazdan gelen telemetriyi canlı çiz. Halka tampon boyutunu ve ekrana çizilecek nokta sayısını değiştir; min/max seyreltmenin tepeleri koruduğunu ve histerezisli eşik uyarısını izle.

sera-01: 17,1 °C17,1°Csera-01sera-02: 16,3 °C16,3°Csera-02sera-03: 15,9 °C15,9°Csera-03
Seyreltilmiş canlı sıcaklık, uyarı eşiği kesikli15.217.820.523.125.700.20.40.60.81açkapa°C
Tampon 1/360 örnek (her biri 2 dk) → seri başına 1 nokta çiziliyor sera-01 uyarısı: kapalı, tamponda 0 kez açıldı
Bellek: 3 × 360 × 4 B = 4,2 KB

Kod

Arduino C++: idempotent röle komutu, komut kimliği ve gölge bildirimi
#include <WiFi.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>

const int RELAY = 26;           // IRF540 kapısı ya da röle modülü girişi
WiFiClient net;
PubSubClient mqtt(net);
uint32_t lastCmdId = 0;         // aynı kimliği ikinci kez uygulama

void report(bool on) {
  // Bildirilen durum kalıcı (retained): yeni bağlanan pano hemen görür
  mqtt.publish("sera/01/fan/state", on ? "{\"on\":true}" : "{\"on\":false}", true);
}

void onMsg(char* topic, byte* data, unsigned int len) {
  JsonDocument doc;
  if (deserializeJson(doc, data, len)) return;    // bozuk JSON: yok say
  uint32_t id = doc["id"] | 0;
  if (id != 0 && id <= lastCmdId) return;         // yinelenen ya da eski komut
  lastCmdId = id;
  bool on = doc["on"] | false;                    // SET: mutlak değer, toggle değil
  digitalWrite(RELAY, on ? HIGH : LOW);
  report(on);                                     // gerçekten uygulanan durumu bildir
}

void setup() {
  pinMode(RELAY, OUTPUT);
  digitalWrite(RELAY, LOW);                       // güvenli varsayılan: kapalı
  mqtt.setCallback(onMsg);
}

void loop() {
  if (!mqtt.connected() && mqtt.connect("sera-01")) mqtt.subscribe("sera/01/fan/set", 1);
  mqtt.loop();
}
MicroPython: servo komutu ve OLED üzerinde halka tamponlu mini pano
import json
from machine import Pin, PWM, I2C
from umqtt.simple import MQTTClient
import ssd1306

servo = PWM(Pin(18), freq=50)                  # SG90: 50 Hz, 0,5 ile 2,5 ms darbe
oled = ssd1306.SSD1306_I2C(128, 64, I2C(0, scl=Pin(22), sda=Pin(21)))
buf, cap, head = [0.0] * 128, 128, 0           # halka tampon: sabit bellek

def on_msg(topic, msg):
    global head
    m = json.loads(msg)
    if topic == b"sera/01/pencere/set":
        aci = max(0, min(90, m["aci"]))        # sınırla: mekanik sonu zorlama
        servo.duty_ns(500_000 + aci * 2_000_000 // 180)
    elif topic == b"sera/01/telemetri":
        buf[head] = m["t"]; head = (head + 1) % cap   # en eski değer ezilir
        oled.fill(0)
        for x in range(cap):
            v = buf[(head + x) % cap]
            oled.pixel(x, 63 - int((v - 10) * 2), 1)  # 10..40 °C ekrana
        oled.show()

c = MQTTClient("pano-01", "broker.local")
c.set_callback(on_msg); c.connect()
c.subscribe(b"sera/01/#")
while True:
    c.wait_msg()

Kendin dene

Eyleyici simülasyonunda kayıp oranını %30 yap ve "çevir" komutuyla 20 komut gönder: son durum beklenenle aynı mı, kaç yinelenen teslim oldu? Aynısını "ayarla" ve "ayarla + kimlik" ile tekrarla. Pano simülasyonunda halka tamponu küçült ve çizilen nokta sayısını 30'a indir: tepe hâlâ görünüyor mu? Uyarı kapanma eşiğini açma eşiğine yaklaştır ve titreşimi izle. Wokwi'de ESP32 + LED + servo kur ve komutu MQTT ile gönder.

Sık yapılan hatalar

  • QoS 1 ile "toggle" komutu göndermek: tek bir yinelenen teslim durumu tersine çevirir.
  • Panoda düğmeyi komut gönderilir gönderilmez "açık" göstermek: cihaz uygulamadan durum değişmiş görünür.
  • Bildirilen durumu kalıcı (retained) yayımlamamak: sonradan açılan pano cihazın durumunu bilemez.
  • IRF540'ı doğrudan 3,3 V GPIO ile sürmek: tam açılmaz, ısınır.
  • Grafikte seyreltme için ortalama almak: kısa süreli tepeler ve arızalar görünmez olur.

Yazılım mühendisliği bağlantısı

Uzaktan komut, dağıtık sistemlerdeki "tam olarak bir kez" sorununun küçük bir örneğidir. Ağ bunu garanti etmez; uygulama idempotentlikle sağlar.

  • Komut işleyicisini saf bir fonksiyon olarak yaz: (durum, komut) → yeni durum. "Aynı komutu iki kez uygula = bir kez uygula" bir özellik testidir.
  • Pano ile cihaz arasındaki konu adları ve yük şeması bir README ya da AsyncAPI belgesinde yazılı olsun; iki taraf da ona göre test edilir.

Kendini sına

  1. QoS 1 ile gönderilen "toggle" komutunun PUBACK'i kayboldu. Ne olur?

  2. Cihaz gölgesinde "istenen" fan=1, "bildirilen" fan=0. Panoda ne gösterilmeli?

  3. Ekranda 10 000 noktayı 300 kovaya indirirken kısa bir sıcaklık tepesini korumak için hangisi?

  4. Uyarı 30 °C'de açılıyor. Kapanma eşiği neden 28 °C gibi daha düşük seçilir?

Bu üniteden sonra bitirme projesinde

  • Uçtan uca ilk sürüm: Sensör düğümü yayımlıyor, eyleyici düğümü idempotent komutla röle ve servoyu sürüyor, pano canlı çiziyor (Wokwi ya da gerçek kart).

Parçalar ve ilgili sayfalar

Esc
  • PanelAna sayfaSayfa
  • ModüllerTüm modüllerSayfa
  • ParçalarParça ansiklopedisiSayfa
  • Mühendislik yoluBüyükler için robotik: 128 parça, 7 seviyeSayfa
  • Robotik dersi (ESOF 323)Üniversite robotik dersi, 14 haftaSayfa
  • Drone dersiBüyükler için: parça, simülasyon, yazılım; 10 üniteSayfa
  • Blok atölyesiSerbest blok programlamaAraç
  • Devre laboratuvarıSanal Arduino ve devreAraç
  • Robot arenasıSanal robot sürüşüAraç
  • OyunlarBloklarla 8 öğretici oyunAraç
  • Mikro Kart atölyesiSanal LED kartı bloklarla programlaAraç
  • Robot atölyesiMikro Kart'ı robota tak, bloklarla görev yapAraç