EYDefterEmre Yakut
← tüm yazılar
Ses & ışık · Protokol · Hata avı · derin

Işıkları hızlandırmak için daha az komut gönder

Evdeki ampulleri müziğe bağladım. Her vuruşta renk komutu yolladım. Işıklar önce geride kaldı, sonra takıldı, sonra rastgele yanıp sönmeye başladı. Çözüm daha hızlı göndermek değildi.

her beat → her ampule komut · ~46 msg/snköprü kuyruğu doluyor, ışıklar geride kalıyor≤ 10 msg/sn · transitiontime ile aradaki geçişışığı hızlandırmak için daha çok komut göndermek, tam tersini yaparçözüm: komut sayısını düşür, ARADAKİ HAREKETİ AMPULE YAPTIRtransitiontime = 1 (100 ms) → donanım interpolasyonu, ağ trafiği yok

Evde ZigBee ampuller var. Bir akşam aklıma geldi: müziği dinleyip ışıkları ona göre sürsem?

Mantık basit görünüyordu. Mikrofondan ses al, frekans analizi yap, vuruşu bul, her vuruşta renk ve parlaklık gönder.

İlk sürüm çalıştı. Beş saniye.

Sonra ne oldu

Kademeli bir çöküş. Önce ışıklar müziğin biraz gerisinde kaldı. Sonra gecikme büyüdü — yarım saniye, bir saniye. Sonra bazı komutlar hiç ulaşmadı; bir ampul mavide kalakaldı. En son her şey rastgele yanıp sönmeye başladı.

Bu, ağ tıkanmasının klasik imzası: önce gecikme, sonra kayıp, sonra kaos.

Rakamlar ortada

ne göndermeye çalışıyordum
128 BPM ÷ 60 × 4 (onaltılık) × 6 ampul ≈ 51 komut/sn

Köprünün pratikte taşıyabildiği: ampul başına saniyede ~10 komut, grup komutlarında daha az. Kapasitenin beş katını gönderiyordum.

ZigBee düşük güçlü, düşük bant genişlikli bir ağ. Amacı bir sensörden saatte birkaç kez veri toplamak. Saniyede elli komut tasarım amacının tamamen dışında.

Köprü de bunu reddetmiyor — kabul ediyor ve kuyruğa alıyor. Asıl sorun bu. Hata dönseydi hemen anlardım. Bunun yerine her şey “başarılı” dönüyor, gerçekte kuyruk büyüyor ve sistem yavaşça ölüyor.

Bir arayüzün isteğini kabul etmesi, yapabileceği anlamına gelmiyor.

Doğru çözüm: işi ampule yaptır

İlk refleksim gönderim hızını düşürmek oldu. Ama saniyede on komutla akıcı geçiş olmuyor — ışık sıçrayarak değişiyor.

Sonra protokolün zaten sunduğu şeyi fark ettim: transitiontime. Bu alan ampule “hedef renge şu sürede geç” diyor. Aradaki bütün ara değerleri ampul üretiyor. Yani yumuşaklığı ağdan değil, donanımdan alıyorsun.

// önce: her ara adımı ben gönderiyordum
t=0ms   → parlaklık 40
t=30ms  → parlaklık 80    (ağda ek trafik)
t=60ms  → parlaklık 120   (ağda ek trafik)
t=90ms  → parlaklık 160   (ağda ek trafik)

// sonra: tek komut, geçişi ampul yapıyor
t=0ms   → { bri: 160, transitiontime: 1 }   // 100 ms'de geç

Dört komut bire indi. Görüntü daha akıcı oldu, çünkü ampulün kendi interpolasyonu ağ jitter’ından etkilenmiyor.

Bir de kuyruk disiplini

İkinci katman: gönderim tarafına kendi kuyruğumu koydum, iki kuralla.

  • Hız tavanı. Ampul başına saniyede en fazla 10 komut.
  • Eskiyi ez. Kuyrukta o ampul için bekleyen bir komut varsa, yenisi onun yerine geçiyor — arkasına eklenmiyor.

İkincisi kritik. Işık için en güncel durum önemli, ara durumlar değil. Kuyrukta bekleyen “kırmızı yap” komutunu göndermenin anlamı yok; artık mavi olması gerekiyor.

genel kural

Kuyruklar iki türlüdür: iş kuyruğu (her öğe yapılmalı — sipariş, e-posta, fatura) ve durum kuyruğu (yalnız sonuncusu önemli — ışık rengi, imleç konumu, sıcaklık göstergesi). İkisini aynı veri yapısıyla yönetmek, ikinci türde her zaman gecikme biriktirir.

Renk seçmek sandığımdan zor

Teknik sorun çözülünce estetik sorun çıktı. Frekansı doğrudan renge eşlemek (bas = kırmızı, tiz = mavi) mantıklı geliyor ve çirkin duruyor. Oda sürekli renk değiştiren bir disko topuna dönüşüyor.

İşe yarayan şey bir kısıt katmanı oldu: parça başına sınırlı bir palet seçiliyor, ses yalnız o palet içinde gezdiriyor. Beyaz özel bir durum — sadece strobe için. Aksi halde her şey gri-pembe bir ortalamaya kayıyor.

Kısıt çeşitliliği azaltmıyor; tutarlılık üretiyor. Bunu sonradan ışık şovu motorunda da aynen kullandım.

Ne öğrendim

Bir sistem yavaşladığında ilk refleks “daha çok, daha hızlı” oluyor. Çoğu zaman doğru hamle tam tersi: daha az gönder, işi yapabilecek olana yaptır.

Ve bir arayüzün sana sunduğu alanları okumak, kendi çözümünü yazmaktan önce gelir. transitiontime ilk günden oradaydı.

Ses & ışıkProtokolHata avı