12.6. Adlandırılmış kanallar¶
Her paketin başlığındaki kanal kimliği, en fazla 32 bağımsız akışın aynı fiziksel aktarımı paylaşmasına olanak tanır. Kanal katmanı, bu sayısal kimlikleri ana makine kodunun bir dize ile başvurabileceği adlandırılmış, uygulama tarafından görülebilir uç noktalara dönüştürür.
12.6.1. Dört yerleşik kanal¶
Kamera, herhangi bir uygulama kodu çalışmadan önce, açılışta dört kanal kaydeder:
stdin– ana makinenin çalıştırılmak üzere kameraya gönderdiği betik baytları. IDE, düzenlenen betiği göndermek için bu kanalı kullanır; ana makine SDK’sındakiexec(), bir Python programından eşdeğer çağrıdır.stdout– kameranınprint()çağrılarından ve yakalanmamış istisna geri izlemelerinden gelen baytlar. IDE’nin seri konsolu bu kanalı okur.stream– canlı önizleme kanalı. IDE bundan JPEG çerçeveleri çeker; herhangi bir ana makine betiği aynısınıread_frame()ile yapabilir.profile– profilleyici olayları, yalnızca kamera profilleme etkin olarak derlendiğinde mevcuttur. Çoğu sürüm derlemesi bunu içermez.
Uygulama kodunun yerleşiklerden herhangi birine dokunması nadiren gerekir; ilginç iş, uygulamanın kendisinin kaydettiği kanallarda gerçekleşir.
12.6.2. Bir kanal kaydetme¶
Kamera tarafındaki bir betik, protocol.register() işlevini bir ad ve bir Python backend nesnesiyle çağırarak yeni bir kanal kaydeder:
import json
import protocol
import time
trigger_count = 0
class StatusChannel:
def size(self):
# Refresh the snapshot on every host query.
self._buf = json.dumps({
'uptime_s': time.ticks_ms() // 1000,
'triggers': trigger_count,
}).encode()
return len(self._buf)
def read(self, offset, size):
return self._buf[offset:offset + size]
protocol.register(name='status', backend=StatusChannel())
Backend nesnesinin metotları, kanalın ne yapabileceğine karar verir. Yalnızca size ve read içeren bir backend salt okunur bir veri kanalıdır; write ekleyin, çift yönlü olur; poll ekleyin, ana makine bir okuma için maliyet ödemeden önce yeni verinin hazır olup olmadığını sorabilir. Yük tek bir parçaya sığacak kadar küçük olduğunda, veriyi size içinde örneklemek en basit yaklaşımdır – arabellek istek üzerine oluşturulur, asla önbelleğe alınmaz, asla yarış durumuna girmez. Daha büyük yükler – görüntü çerçeveleri, sensör izleri – ana makine çok parçalı okumasını bitirene kadar arabelleği tutan bir mandallama yaklaşımına ihtiyaç duyar; bu, çerçeve kanalıyla ele alınmaktadır.
Az miktarda kayıt tutma işlemi otomatik olarak gerçekleşir:
Kütüphane bir sonraki boş kanal kimliğini (0 ile 31 arasında) atar.
Yetenek bayrakları, mevcut metotlardan türetilir:
readtanımlıysaCHANNEL_FLAG_READ,writetanımlıysaCHANNEL_FLAG_WRITE,lock/unlocktanımlıysaCHANNEL_FLAG_LOCK.Bağlı her ana makineye, kanal listesini güncellemesi için bir
CHANNEL_REGISTEREDolay paketi gönderilir.
Dönüş değeri, uygulamanın elinde tutabileceği bir protocol.ProtocolChannel tutamacıdır. Tutamacın send_event() metodu, ana makineye “bu kanalda okunabilir veriyi değiştirmeden bir şey oldu” demek için kamera tarafındaki kancadır – bir tetikleyici devreye girdi, bir düğmeye basıldı, bir örnek sayısı kilometre taşı geçildi.
12.6.3. Ana makineden kanalları okuma¶
Ana makine SDK’sı, aktarım için pyserial üzerine kurulu, PyPI üzerinde openmv paketi (pip install openmv) olarak gönderilir. openmv.camera.Camera sınıfı, kameranın adlandırılmış kanallarını üst düzey metotlar aracılığıyla sunar:
from openmv.camera import Camera
with Camera('/dev/ttyACM0', baudrate=921600) as cam:
cam.update_channels()
if cam.has_channel('status'):
size = cam.channel_size('status')
data = cam.channel_read('status', size)
Uyarı
openmv paketi CPython 3.12 veya daha yenisini gerektirir. Daha eski yorumlayıcılarda SDK’nın bağlı olduğu özellikler bulunmaz; pip install openmv öncesinde 3.12+ bir derleme kurun.
Kurulum hakkında dikkat edilmesi gereken birkaç şey:
Seri port dizesi – burada
/dev/ttyACM0– Windows’taCOM3tarzıdır, macOS’ta/dev/cu.usbmodemXXXXve Linux’ta/dev/ttyACM*şeklindedir. Gerçek numara, kameranın hangi port olarak numaralandırıldığına bağlıdır.Baud hızı, protokolün sihirli değeri olan
921600‘dür; kameranın USB-CDC yığını bunu “bu istemci REPL’i değil protokolü konuşuyor” olarak tanır. Başka herhangi bir hız, düz bir seri hatta geri döner.with Camera(...) as cam:bağlam yöneticisi aktarımı açar,PROTO_SYNCçalıştırır, yetenekleri değiş tokuş eder ve çıkışta portu temiz bir şekilde kapatır. Girişten sonra yapılan açıkupdate_channels()çağrısı, yerel kanal listesini uygulamanın açılıştan sonra kaydettiği kanallarla tazeler.
channel_size() ve channel_read(), asıl işi yapan metotlardır; channel_write(), backend’in bir write metodu varsa bir arabelleği kameraya gidip getirir; has_channel(), bir adı kullanmadan önce kayıtlı olduğunu kontrol etmenin güvenli yoludur. Kanal adı, kameranın register sırasında atadığı kanal kimliğine bir kez bakılarak çözülür ve bundan sonra her pakette kullanılır.
Her channel_size() / channel_read() çifti iki gidiş-dönüşe mal olur: biri boyutu sormak için bir paket, diğeri baytları sormak için. USB-CDC üzerinden ikisi birlikte yaklaşık bir milisaniyede biter; UART üzerinden aynı değiş tokuş, seri hattın baud hızıyla orantılı olarak daha uzun sürer. Sıkı bir döngüde okuyan uygulama kodu, channel_size() işlevini yalnızca boyutun gerçekten değişebileceği zaman çağırmalıdır – sabit boyutlu veriler için ilk çağrıdan gelen boyut önbelleğe alınabilir.
12.6.4. Kanallar arası bağımsızlık¶
Kanalların nasıl etkileşime girdiği konusunda bilinmeye değer üç şey vardır:
Bağımsız akış kontrolü. Her kanalın kendi bekleyen okuma durumu, kendi verisi ve kendi
size/read/writegeri çağırmaları vardır.streamkanalında uzun süren bir okuma, uygulamanınconfigkanalındaki okumaları engellemez.Kanal başına sıralı. Tek bir kanal içinde, paketler sırayla teslim edilir. Güvenilirlik katmanı, yeniden iletimler söz konusu olsa bile bunu garanti eder.
Paylaşılan aktarım, paylaşılan yeniden iletim bütçesi. Tüm kanallar tek fiziksel bağlantıyı paylaşır, bu nedenle bir kanaldaki trafik seli, hattı tek başına işgal ederek diğerlerini yavaşlatır.
CHANNEL_LOCKmekanizması, bir kanalın atomik çok paketli bir okuma için hattı rezerve etmesine olanak tanır; backend,lock/unlockgeri çağırmalarını uygulayarak bunu etkinleştirir.
Bir kanal, bir ana makine programı ile bir kamera programının iş birliği yapmak için anlaştığı en küçük yüzey alanıdır. Ad, yönlülük (okuma veya yazma ya da her ikisi), kamera tarafındaki geri çağırma metotları ve ana makine tarafındaki eşleşen metot çağrıları, sözleşmenin tamamını oluşturur.