4.14. Základy CSI¶
Modul csi je způsob, jakým Python kód řídí senzor kamery. Každý skript, který zachytává snímek, má stejnou třídílnou strukturu: importy nahoře, jednorázová konfigurace uprostřed a smyčka while True dole, která vytahuje snímky z kamery jeden po druhém.
4.14.1. Typická smyčka¶
import csi, image, time
csi0 = csi.CSI()
csi0.reset()
csi0.pixformat(csi.RGB565)
csi0.framesize(csi.QVGA)
clock = time.clock()
while True:
clock.tick()
img = csi0.snapshot()
# process img here
print(clock.fps())
4.14.2. Co dělá každé volání¶
import csi, image, timeNačte tři moduly.
csiovládá senzor,imagedefinuje tříduImage, kterou vracísnapshot(), atimeposkytuje pomocníkatime.clock()používaného k měření počtu snímků za sekundu.csi.CSI()Vytvoří instanci
CSI, která obaluje jeden fyzický senzor kamery. Konstruktor zabere periferii kamery a zaznamená konfiguraci specifickou pro daný senzor. Kamery s jediným senzorem mají jednu instanciCSI; kamery se dvěma senzory (barevný plus termální, barevný plus událostní) mají dvě, každou vybranou argumentemcidkonstruktoru.csi0.reset()Napájí a konfiguruje senzor. Ve výchozím nastavení vyšle puls na resetovací pin senzoru a poté zapíše I2C registry senzoru do známého počátečního stavu. Následná konfigurační volání –
pixformat,framesize, ovládací prvky automatiky – posílají další zápisy do registrů přes stejnou řídicí sběrnici I2C.csi0.pixformat(csi.RGB565)Zapíše registry senzoru, které vyberou výstupní formát pixelů. Dostupné volby jsou formáty představené na stránce formáty pixelů:
RGB565,GRAYSCALE,BAYER,YUV422aJPEGna senzorech, které jej podporují.csi0.framesize(csi.QVGA)Zapíše registry, které vyberou výstupní rozlišení.
QVGAje 320 × 240; pojmenované velikosti sahají až poWQXGA2(2592 × 1944, přibližně 5 MP) na senzorech, které je podporují. Funguje také vlastní n-tice(width, height), pokud odpovídá výstupním možnostem senzoru.clock = time.clock()Vytvoří pomocníka clock. Každé volání
clock.tick()uvnitř smyčky zaznamená čas začátku iterace;time.clock.fps()hlásí nedávnou rychlost smyčky v počtu snímků za sekundu.img = csi0.snapshot()Zachytí jeden snímek ze senzoru a vrátí jej jako
Image. Mechanika toho, jak se tento snímek dostane do paměti, stojí za bližší pohled.
4.14.3. Jak snapshot plní paměť¶
Senzor dodává pixely na datové sběrnici pixelů popsané v sběrnice senzoru rychlostí stovek megabajtů za sekundu – příliš rychle na to, aby je CPU kopíroval pixel po pixelu v softwaru.
Místo toho MCU přenechá přenos přímému přístupu do paměti (DMA) – hardwarovému stroji odděleného od CPU, který kopíruje bajty z jednoho místa na druhé uvnitř MCU bez jakéhokoli zapojení CPU. Vstupní periferie kamery zachytává každý příchozí bajt pixelu do malé čipové fronty FIFO; libovolné stupně ISP, které běží na straně MCU, data cestou zpracují; a stroj DMA zapisuje hotové pixely do framebufferu v RAM na odpovídající offset pixelu. Nic v tomto řetězci nepotřebuje CPU, jakmile je kanál DMA naprogramován.
Když je zavoláno snapshot():
Ovladač CSI naprogramuje stroj DMA s adresou framebufferu, délkou přenosu (pixely jednoho snímku) a callbackem pro přerušení dokončení DMA.
Ovladač povolí vstupní periferii kamery a čeká, až senzor signalizuje začátek dalšího snímku.
Jak senzor vysílá snímek ven, periferie předává každý bajt pixelu skrz ISP a dále stroji DMA, který zapisuje výsledek do RAM na další offset framebufferu. CPU je během přenosu volný a může vykonávat jiný kód.
Když dorazí poslední pixel snímku, DMA vyvolá své přerušení dokončení, ovladač obalí framebuffer do
Imageasnapshot()jej vrátí uživatelskému kódu.
Vrácený Image nevlastní kopii dat pixelů – ukazuje na jeden z framebufferů kamery v RAM. Kolik framebufferů kamera udržuje a jak se předávají mezi DMA a uživatelským kódem při každém volání snapshot(), závisí na režimu bufferování, který aplikace vybrala prostřednictvím framebuffers().