13.1.9. De Channels-weergave#
De framebuffer toont wat de camera ziet; de Channels-weergave toont wat het script meet en beslist. Een script publiceert benoemde waarden over het debugprotocol – een temperatuur, een detectietelling, een microfoongolfvorm, een time-of-flight-dieptekaart, of een bedieningselement dat de gebruiker moet kunnen wijzigen – en de IDE geeft elk ervan live weer als een widget, een grafiek of een kaart in het paneel onder de framebuffer. Er hoeft niets op de afbeelding getekend of uit de terminal geparseerd te worden. Aan de camerakant is het een paar regels met protocol.CBORChannel; aan de IDE-kant is het het item Channels van de paneelkeuzelijst.

De bedieningselementen van een thermische-camerascript: twee temperatuuruitlezingen, schakelaars voor de meetmodi en schuifregelaars voor het temperatuurbereik. Het wijzigen van een ervan stuurt de nieuwe waarde naar het script.#
De weergave is per kanaal georganiseerd. Elk kanaal dat het script registreert wordt een sectie met de naam van het kanaal als kop, en elk record in het kanaal wordt een rij eronder, in de volgorde waarin het script ze heeft toegevoegd. Wanneer het script een kanaal registreert of de vorm ervan wijzigt, bouwt de weergave zichzelf opnieuw op; wanneer het script stopt, blijven de laatste waarden op het scherm, met de bedieningselementen uitgeschakeld, totdat het volgende script start.
13.1.9.1. Widgets#
Uitlezingen en bedieningselementen nemen de voor de hand liggende vormen aan. Een label is een alleen-lezen waarde met zijn eenheid; een text-record is een blok statische opgemaakte tekst voor koppen en uitleg. De schrijfbare soorten sturen hun nieuwe waarde terug naar het script op het moment dat je ze wijzigt, waar de on_write-callback van het script de recordnaam en waarde ontvangt: een toggle is een schakelaar, een slider en een spinbox stellen een getal in binnen het bereik en de stap van het script (de spinbox voor nauwkeurige invoer), radio-knoppen en een select kiezen een van de opties van het script, een lineedit is een vrij tekstveld, en een pushbutton voert een kortstondige actie uit. De weergave houdt je bewerking op het scherm in plaats van deze terug te zetten naar de laatst gepubliceerde waarde van de camera terwijl de schrijfbewerking onderweg is.
Aan de scriptkant is de hele set een protocol.CBORChannel met één add per widget en een callback voor de schrijfbewerkingen:
import time
import protocol
from protocol import CBORChannel
def on_write(ch, name, value):
print(name, "=", value) # every change lands here
ch = CBORChannel(on_write=on_write)
ch.add("Status", type="label", value="starting")
ch.add("Enable", type="toggle", value=True)
ch.add("Threshold", type="slider", min=0, max=100,
step=1, value=50, unit="%")
ch.add("Mode", type="select",
options=["Idle", "Track", "Record"], value="Idle")
ch.add("Calibrate", type="pushbutton")
protocol.register(name="controls", backend=ch)
while True:
if ch["Enable"]: # read a control back
ch["Status"] = "threshold %d%%" % ch["Threshold"]
time.sleep_ms(100)
Voer het uit en schakel het paneel naar Channels: er verschijnt een sectie met de naam controls met de vijf widgets, en het bewegen van de schuifregelaar print in de terminal. De andere widgettypen – spinbox, radio, lineedit, text – zijn elk één add extra; het hoofdstuk over het hostprotocol loopt ze allemaal langs.
13.1.9.2. Golfvormgrafieken#
Een waveform-record is een blok verweven samples met een samplefrequentie – audio, accelerometerassen, een ADC-spoor – en de weergave plot het als een scrollende grafiek, één reeks per as, benoemd door het script. De grafiekbediening zit in de werkbalk en op de plot zelf:
Sleep om te pannen en scroll om te zoomen; dubbelklik om terug te keren naar het volgen van de live rand. History bepaalt hoeveel eerdere gegevens worden bewaard, zodat je erdoorheen terug kunt pannen.
Auto Scale past de verticale as aan de gegevens aan; uitgeschakeld is de as het bereik dat het script heeft gedeclareerd.
Klik met de rechtermuisknop op de plot om een marker te plaatsen en de exacte tijd en waarde van een sample af te lezen, of om een triggerniveau in te stellen. Met een geactiveerde Trigger houdt de grafiek stil totdat het signaal het niveau op een stijgende of dalende flank kruist – de oscilloscoopmanier om een transiënt te vangen – en Re-arm wacht op de volgende.
Spectrum schakelt de grafiek om naar een frequentieplot van dezelfde gegevens, met een keuze uit venster (Hann, Hamming, Blackman, rechthoekig), Averaging en Peak Hold over frames heen, en een Log Frequency-as. De uitlezing onder de plot noemt de piekfrequentie en het niveau ervan.
Pause bevriest de grafiek zonder een opname te beïnvloeden; Stats voegt een regel met min / max / RMS toe; en het rechtermuisknopmenu slaat de plot op als afbeelding.

Twee golfvormrecords die live scrollen: een microfoonspoor en een IMU-spoor met drie reeksen.#
Een waveform-veld neemt de samplefrequentie en, voor meerdere signalen tegelijk, het aantal verweven series en hun namen; elke update is de ruwe bytes van een array van samples in de typecode van het veld:
import math
import time
import protocol
from array import array
from protocol import CBORChannel
RATE, CHUNK = 1000, 100 # 1 kHz, 100 ms per update
ch = CBORChannel()
ch.add("IMU", type="waveform", sample_rate=RATE, series=3,
typecode="f", min=-2.0, max=2.0,
options=["X", "Y", "Z"], unit="g")
protocol.register(name="signals", backend=ch)
t = 0
while True:
block = array("f")
for i in range(CHUNK):
phase = 2 * math.pi * 2 * (t + i) / RATE
block.extend((math.sin(phase), math.cos(phase), 1.0))
ch["IMU"] = bytes(block) # interleaved X, Y, Z
t += CHUNK
time.sleep_ms(100)
13.1.9.3. Dieptekaarten#
Een depth-record is een raster van afstanden – de frames die een time-of-flight-sensor produceert – en de weergave tekent het als een valse-kleurenkaart, opgeschaald naar de grafiekhoogte. De werkbalk kiest de weergave: het palet (de eigen paletten Depth, Rainbow en Ironbow van de camera, plus lichte en donkere paletten voor eventcamera’s), het schaalfilter dat het kleine sensorraster vergroot (bicubisch voor een glad oppervlak, bilineair, of nearest voor één blok per sensorpixel), en de tone mapping die afstand in kleur omzet: Script Range gebruikt het bereik dat het script heeft gedeclareerd, Auto Range rekt de kleuren uit over de afstanden die daadwerkelijk in elk frame voorkomen (met weglating van de paar procent uitschieters), en Equalize verdeelt ze over de verdeling van het frame, zodat een vlakke scène toch zijn details toont. De kop meldt de grootte van de kaart, het gedeclareerde bereik en het minimum, maximum en gemiddelde van het frame; wanneer je de muis over de kaart beweegt, wordt de afstand onder de cursor uitgelezen, en Save Image schrijft de gerenderde kaart naar een PNG.

Een time-of-flight-dieptekaart van een hand voor de sensor, met de keuzelijsten voor palet, schaling en tone mapping in de werkbalk.#
Een depth-veld declareert zijn rastergrootte en bereik; elke update is het raster als gepakte 32-bits floats, wat de lezer van de tof-module produceert:
import struct
import time
import tof
import protocol
from protocol import CBORChannel
tof.init()
ch = CBORChannel()
ch.add("depth", type="depth", width=tof.width(),
height=tof.height(), min=0, max=1000)
protocol.register(name="ToF", backend=ch)
while True:
try:
d, dmin, dmax = tof.read_depth(vflip=True, hmirror=True)
except RuntimeError:
continue
ch["depth"] = struct.pack("<%df" % len(d), *d)
time.sleep_ms(50)
13.1.9.4. Opnemen#
Elke grafiek en kaart heeft een knop Record, en een kanaal met meer dan één ervan heeft een balk Record All die ze samen start. Opnemen schrijft de gegevens zoals ze binnenkomen – niet de weergave – naar een bestand waarvan het formaat de extensie volgt die je in het opslagvenster kiest: CSV voor spreadsheets en plotgereedschappen, WAV voor eenkanaals audiogolfvormen, NumPy .npy-arrays voor Python, en Edge Impulse JSON of CBOR om rechtstreeks als trainingsdata in een Edge Impulse-project te uploaden, met een optioneel label dat de bestanden benoemt. Alleen de formaten die de gegevens van een record kunnen bevatten worden aangeboden; een dieptekaart kan bijvoorbeeld geen WAV-bestand zijn. Een lange opname wordt opgesplitst in genummerde delen, zodat geen enkel bestand onhandelbaar groot wordt, en een opname overleeft het opnieuw registreren van zijn kanalen door het script. De uitlezing naast de knop houdt bij hoeveel samples er zijn geschreven en hoe groot het bestand is.
Het interval Channel Polling van het paneel, in de protocolsectie van de voorkeuren, bepaalt hoe vaak de IDE de camera om nieuwe kanaalgegevens vraagt; de standaardwaarde past bij scripts die een paar keer per seconde publiceren, en een script dat audio streamt heeft baat bij een korter interval.
Zie ook
protocol.CBORChannel voor de scriptkant – de recordtypen, hun argumenten en de on_write-callback – en de 12-Protocol-voorbeelden onder File → Examples voor werkende scripts die uitlezingen, bedieningselementen en een dieptekaart publiceren.