13.1.9. La vista Canales#
El búfer de fotogramas muestra lo que la cámara ve; la vista Canales muestra lo que el script mide y decide. Un script publica valores con nombre a través del protocolo de depuración – una temperatura, un recuento de detecciones, la forma de onda de un micrófono, un mapa de profundidad por tiempo de vuelo, o un control que quiere que el usuario pueda cambiar – y el IDE representa cada uno en vivo como un widget, una gráfica o un mapa en el panel bajo el búfer de fotogramas. No hay que dibujar nada sobre la imagen ni extraer nada de la terminal. En el lado de la cámara son unas pocas líneas con protocol.CBORChannel; en el lado del IDE es la entrada Canales del selector del panel.

Los controles del script de una cámara térmica: dos lecturas de temperatura, interruptores para los modos de medición y deslizadores para el rango de temperatura. Cambiar cualquiera de ellos envía el nuevo valor al script.#
La vista está organizada por canal. Cada canal que registra el script se convierte en una sección con el nombre del canal como título, y cada registro del canal se convierte en una fila debajo, en el orden en que el script los añadió. Cuando el script registra un canal o cambia la forma de uno, la vista se reconstruye; cuando el script se detiene, los últimos valores permanecen en pantalla, con los controles desactivados, hasta que arranca el siguiente script.
13.1.9.1. Widgets#
Las lecturas y los controles adoptan las formas evidentes. Una label (etiqueta) es un valor de solo lectura con su unidad; un registro text es un bloque de texto enriquecido estático para títulos y explicaciones. Los tipos escribibles envían su nuevo valor de vuelta al script en el momento en que los cambias, donde el callback on_write del script recibe el nombre del registro y el valor: un toggle es un interruptor, un slider y un spinbox fijan un número dentro del rango y el paso del script (el cuadro numérico para una entrada precisa), los botones radio y un select eligen una de las opciones del script, un lineedit es un campo de texto libre, y un pushbutton dispara una acción momentánea. La vista mantiene tu edición en pantalla en lugar de devolverla al último valor publicado por la cámara mientras la escritura está en curso.
En el lado del script todo el conjunto es un protocol.CBORChannel con un add por widget y un callback para las escrituras:
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)
Ejecútalo y cambia el panel a Canales: aparece una sección llamada controls con los cinco widgets, y mover el deslizador imprime en la terminal. Los otros tipos de widget – spinbox, radio, lineedit, text – son un add más cada uno; el capítulo del protocolo de host los recorre todos.
13.1.9.2. Gráficas de forma de onda#
Un registro waveform (forma de onda) es un bloque de muestras intercaladas con una frecuencia de muestreo – audio, los ejes de un acelerómetro, una traza de ADC – y la vista lo representa como una gráfica con desplazamiento, una serie por eje, con los nombres que les da el script. Los controles de la gráfica están en su barra de herramientas y en la propia gráfica:
Arrastra para desplazarte y usa la rueda para hacer zoom; haz doble clic para volver a seguir el borde en vivo. Historial establece cuántos datos pasados se conservan para que puedas retroceder por ellos.
Escala automática ajusta el eje vertical a los datos; desactivada, el eje es el rango que declaró el script.
Haz clic derecho en la gráfica para colocar un marcador y leer el tiempo y el valor exactos de una muestra, o para fijar un nivel de disparo. Con un Disparo armado, la gráfica se mantiene quieta hasta que la señal cruza el nivel en un flanco ascendente o descendente – la manera del osciloscopio de capturar un transitorio – y Rearmar espera al siguiente.
Espectro cambia la gráfica a una representación en frecuencia de los mismos datos, con elección de ventana (Hann, Hamming, Blackman, rectangular), Promediado y Retención de picos entre fotogramas, y un eje de Frecuencia logarítmica. La lectura bajo la gráfica indica la frecuencia del pico y su nivel.
Pausar congela la gráfica sin afectar a una grabación; Estadísticas añade una línea de mín. / máx. / RMS; y el menú contextual guarda la gráfica como imagen.

Dos registros de forma de onda desplazándose en vivo: una traza de micrófono y una traza de IMU de tres series.#
Un campo de forma de onda toma la frecuencia de muestreo y, para varias señales a la vez, el número de series intercaladas y sus nombres; cada actualización son los bytes en bruto de un array de muestras en el typecode del campo:
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. Mapas de profundidad#
Un registro depth (profundidad) es una cuadrícula de distancias – los fotogramas que produce un sensor de tiempo de vuelo – y la vista lo dibuja como un mapa de falso color ampliado hasta la altura de la gráfica. La barra de herramientas elige la representación: la paleta (las paletas Profundidad, Arcoíris e Ironbow propias de la cámara, más las paletas clara y oscura para cámaras de eventos), el filtro de escalado que amplía la pequeña cuadrícula del sensor (bicúbico para una superficie suave, bilineal, o más cercano para un bloque por píxel del sensor), y el mapeo tonal que convierte la distancia en color: Rango del script usa el rango que declaró el script, Rango auto estira los colores sobre las distancias realmente presentes en cada fotograma (ignorando el pequeño porcentaje de valores extremos), y Ecualizar los reparte sobre la distribución del fotograma para que una escena plana siga mostrando su detalle. La cabecera informa del tamaño del mapa, del rango declarado y del mínimo, el máximo y la media del fotograma; al pasar el cursor sobre el mapa se lee la distancia bajo el cursor, y Guardar imagen escribe el mapa representado en un PNG.

Un mapa de profundidad por tiempo de vuelo de una mano frente al sensor, con los selectores de paleta, escalado y mapeo tonal en la barra de herramientas.#
Un campo de profundidad declara el tamaño de su cuadrícula y su rango; cada actualización es la cuadrícula como flotantes de 32 bits empaquetados, que es lo que produce el lector del módulo tof:
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. Grabación#
Cada gráfica y mapa tiene un botón Grabar, y un canal con más de uno tiene una barra Grabar todo que los inicia a la vez. La grabación escribe los datos a medida que llegan – no la representación – en un archivo cuyo formato sigue la extensión que elijas en el diálogo de guardado: CSV para hojas de cálculo y herramientas de representación gráfica, WAV para formas de onda de audio de un solo canal, matrices .npy de NumPy para Python, y JSON o CBOR de Edge Impulse para subirlos directamente a un proyecto de Edge Impulse como datos de entrenamiento, con una etiqueta opcional que da nombre a los archivos. Solo se ofrecen los formatos que pueden contener los datos de un registro; un mapa de profundidad, por ejemplo, no puede ser un archivo WAV. Una captura larga se divide en partes numeradas para que ningún archivo crezca hasta volverse inmanejable, y una grabación sobrevive a que el script vuelva a registrar sus canales. La lectura junto al botón indica cuántas muestras se han escrito y el tamaño del archivo.
El intervalo de Sondeo de canales del panel, en la sección del protocolo de las preferencias, establece con qué frecuencia el IDE pide a la cámara nuevos datos de canal; el valor predeterminado conviene a los scripts que publican unas pocas veces por segundo, y un script que transmite audio se beneficia de un intervalo más corto.
Ver también
protocol.CBORChannel para el lado del script – los tipos de registro, sus argumentos y el callback on_write – y los ejemplos de 12-Protocol bajo File → Examples para scripts funcionales que publican lecturas, controles y un mapa de profundidad.