13.1.9. Channels-vyn#

Bildbufferten visar vad kameran ser; Channels-vyn visar vad skriptet mäter och beslutar. Ett skript publicerar namngivna värden över felsökningsprotokollet – en temperatur, ett detekteringsantal, en mikrofonvågform, en time-of-flight-djupkarta, eller en kontroll det vill att användaren ska kunna ändra – och IDE:n renderar var och en live som en widget, en graf eller en karta i rutan under bildbufferten. Inget behöver ritas på bilden eller tolkas ur terminalen. På kamerasidan är det några rader med protocol.CBORChannel; på IDE-sidan är det posten Channels i rutväljaren.

The Channels view showing a thermal camera script's controls channel: FPA and AUX temperature readouts with their unit, Measurement and High Temp toggles, Temp Min and Temp Max sliders, and H-Mirror and V-Flip toggles

Ett värmekameraskripts kontroller: två temperaturavläsningar, växlare för mätlägena och skjutreglage för temperaturintervallet. Att ändra någon av dem skickar det nya värdet till skriptet.#

Vyn är ordnad efter kanal. Varje kanal skriptet registrerar blir en sektion med kanalens namn som rubrik, och varje post i kanalen blir en rad under den, i den ordning skriptet lade till dem. När skriptet registrerar en kanal eller ändrar formen på en bygger vyn om sig själv; när skriptet stoppas stannar de senaste värdena kvar på skärmen, med kontrollerna inaktiverade, tills nästa skript startar.

13.1.9.1. Widgetar#

Avläsningar och kontroller tar de självklara formerna. En label är ett skrivskyddat värde med sin enhet; en text-post är ett block med statisk formaterad text för rubriker och förklaringar. De skrivbara slagen skickar sitt nya värde tillbaka till skriptet i samma ögonblick som du ändrar dem, där skriptets on_write-återanrop tar emot postens namn och värde: en toggle är en brytare, en slider och en spinbox sätter ett tal inom skriptets intervall och steg (spinnrutan för exakt inmatning), radio-knappar och en select väljer ett av skriptets alternativ, en lineedit är ett fritextfält, och en pushbutton utlöser en tillfällig åtgärd. Vyn behåller din redigering på skärmen i stället för att låta den hoppa tillbaka till kamerans senast publicerade värde medan skrivningen är på väg.

På skriptsidan är hela uppsättningen en protocol.CBORChannel med ett add per widget och ett återanrop för skrivningarna:

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)

Kör det och växla rutan till Channels: en sektion med namnet controls visas med de fem widgetarna, och att flytta skjutreglaget skriver ut i terminalen. De andra widgettyperna – spinbox, radio, lineedit, text – är ett add till vardera; kapitlet om värdprotokollet går igenom dem alla.

13.1.9.2. Vågformsgrafer#

En waveform-post är ett block av sammanflätade sampel med en samplingsfrekvens – ljud, accelerometeraxlar, ett ADC-spår – och vyn ritar den som en rullande graf, en serie per axel, namngiven av skriptet. Grafens kontroller finns i dess verktygsfält och på själva grafen:

  • Dra för att panorera och rulla för att zooma; dubbelklicka för att återgå till att följa livekanten. History anger hur mycket tidigare data som behålls så att du kan panorera tillbaka genom den.

  • Auto Scale anpassar den lodräta axeln till datan; avstängd är axeln det intervall skriptet deklarerade.

  • Högerklicka på grafen för att placera en markör och läsa av exakt tid och värde för ett sampel, eller för att sätta en triggernivå. Med en Trigger aktiverad står grafen stilla tills signalen korsar nivån på en stigande eller fallande flank – oscilloskopets sätt att fånga en transient – och Re-arm väntar på nästa.

  • Spectrum växlar grafen till en frekvensgraf över samma data, med val av fönster (Hann, Hamming, Blackman, rektangulärt), Averaging och Peak Hold över bildrutor, och en Log Frequency-axel. Avläsningen under grafen anger toppfrekvensen och dess nivå.

  • Pause fryser grafen utan att påverka en inspelning; Stats lägger till en rad med min / max / RMS; och högerklicksmenyn sparar grafen som en bild.

The Channels view with two waveform records scrolling live: a 16 kHz microphone trace and a three-series accelerometer trace with its X, Y, and Z legend, each with its Record, Spectrum, Pause, and Stats buttons

Två vågformsposter som rullar live: ett mikrofonspår och ett IMU-spår med tre serier.#

Ett waveform-fält tar samplingsfrekvensen och, för flera signaler samtidigt, antalet sammanflätade series och deras namn; varje uppdatering är de råa byten i en array av sampel med fältets typecode:

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. Djupkartor#

En depth-post är ett rutnät av avstånd – de bildrutor en time-of-flight-sensor producerar – och vyn ritar den som en falskfärgskarta uppskalad till grafhöjden. Verktygsfältet väljer renderingen: paletten (kamerans egna paletter Depth, Rainbow och Ironbow, plus ljusa och mörka paletter för händelsekameror), skalningsfiltret som förstorar det lilla sensorrutnätet (bikubiskt för en slät yta, bilinjärt, eller närmaste för ett block per sensorpixel), och tonmappningen som omvandlar avstånd till färg: Script Range använder intervallet skriptet deklarerade, Auto Range sträcker ut färgerna över de avstånd som faktiskt finns i varje bildruta (och ignorerar de få avvikande procenten), och Equalize fördelar dem över bildrutans fördelning så att en platt scen ändå visar sina detaljer. Rubriken rapporterar kartans storlek, det deklarerade intervallet och bildrutans minimum, maximum och medelvärde; att hovra över kartan läser av avståndet under markören, och Save Image skriver den renderade kartan till en PNG.

The Channels view showing an 8 x 8 time-of-flight depth map scaled up smoothly with the Depth palette, the palette, scaling, and tone-mapping selectors in its toolbar, and the header reporting the size, declared range, and the frame's minimum, maximum, and mean

En time-of-flight-djupkarta av en hand framför sensorn, med väljarna för palett, skalning och tonmappning i verktygsfältet.#

Ett depth-fält deklarerar sin rutnätsstorlek och sitt intervall; varje uppdatering är rutnätet som packade 32-bitars flyttal, vilket är vad tof-modulens läsare producerar:

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. Inspelning#

Varje graf och karta har en Record-knapp, och en kanal med mer än en av dem har en Record All-rad som startar dem tillsammans. Inspelningen skriver datan allteftersom den anländer – inte renderingen – till en fil vars format följer filändelsen du väljer i spara-dialogen: CSV för kalkylblad och plottningsverktyg, WAV för enkanaliga ljudvågformer, NumPy .npy-arrayer för Python, och Edge Impulse JSON eller CBOR för uppladdning direkt till ett Edge Impulse-projekt som träningsdata, med en valfri etikett som namnger filerna. Bara de format som kan rymma en posts data erbjuds; en djupkarta kan till exempel inte bli en WAV-fil. En lång inspelning delas upp i numrerade delar så att ingen enskild fil blir ohanterlig, och en inspelning överlever att skriptet registrerar om sina kanaler. Avläsningen bredvid knappen följer hur många sampel som skrivits och filstorleken.

Rutans Channel Polling-intervall, i protokollavsnittet i inställningarna, anger hur ofta IDE:n ber kameran om nya kanaldata; standardvärdet passar skript som publicerar några gånger i sekunden, och ett skript som strömmar ljud har nytta av ett kortare intervall.

Se även

protocol.CBORChannel för skriptsidan – posttyperna, deras argument och on_write-återanropet – och 12-Protocol-exemplen under File → Examples för fungerande skript som publicerar avläsningar, kontroller och en djupkarta.