13.1.9. A visualização Canais#
O frame buffer mostra o que a câmera vê; a visualização Canais mostra o que o script mede e decide. Um script publica valores nomeados pelo protocolo de depuração – uma temperatura, uma contagem de detecções, uma forma de onda de microfone, um mapa de profundidade time-of-flight, ou um controle que ele quer que o usuário possa alterar – e a IDE renderiza cada um ao vivo como um widget, um gráfico ou um mapa no painel abaixo do frame buffer. Nada precisa ser desenhado na imagem nem extraído do terminal. Do lado da câmera são algumas linhas com protocol.CBORChannel; do lado da IDE é a entrada Canais do seletor do painel.

Os controles de um script de câmera térmica: duas leituras de temperatura, chaves para os modos de medição e controles deslizantes para a faixa de temperatura. Alterar qualquer um deles envia o novo valor ao script.#
A visualização é organizada por canal. Cada canal que o script registra vira uma seção com o nome do canal como título, e cada registro no canal vira uma linha abaixo dela, na ordem em que o script os adicionou. Quando o script registra um canal ou muda a forma de um, a visualização se reconstrói; quando o script para, os últimos valores permanecem na tela, com os controles desabilitados, até o próximo script começar.
13.1.9.1. Widgets#
Leituras e controles assumem as formas óbvias. Um label é um valor somente leitura com sua unidade; um registro text é um bloco de rich text estático para títulos e explicações. Os tipos graváveis enviam seu novo valor de volta ao script no momento em que você os altera, onde o callback on_write do script recebe o nome e o valor do registro: um toggle é uma chave, um slider e um spinbox definem um número dentro da faixa e do passo do script (a caixa de incremento para entrada precisa), botões radio e um select escolhem uma das opções do script, um lineedit é um campo de texto livre, e um pushbutton dispara uma ação momentânea. A visualização mantém sua edição na tela em vez de voltá-la ao último valor publicado pela câmera enquanto a escrita está em andamento.
No lado do script o conjunto inteiro é um protocol.CBORChannel com um add por widget e um callback para as escritas:
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)
Execute-o e mude o painel para Canais: uma seção chamada controls aparece com os cinco widgets, e mover o controle deslizante imprime no terminal. Os outros tipos de widget – spinbox, radio, lineedit, text – são um add a mais cada; o capítulo do protocolo de host percorre todos eles.
13.1.9.2. Gráficos de forma de onda#
Um registro waveform é um bloco de amostras intercaladas com uma taxa de amostragem – áudio, eixos de acelerômetro, um traço de ADC – e a visualização o plota como um gráfico rolante, uma série por eixo, nomeada pelo script. Os controles do gráfico ficam em sua barra de ferramentas e no próprio gráfico:
Arraste para fazer panorâmica e role para dar zoom; clique duas vezes para voltar a seguir a borda ao vivo. Histórico define quanto de dados passados é mantido para que você possa voltar por eles.
Escala automática ajusta o eixo vertical aos dados; desligada, o eixo é a faixa que o script declarou.
Clique com o botão direito no gráfico para colocar um marcador e ler o tempo e o valor exatos de uma amostra, ou para definir um nível de gatilho. Com um Gatilho armado, o gráfico fica parado até o sinal cruzar o nível em uma borda de subida ou de descida – o jeito do osciloscópio de capturar um transiente – e Rearmar espera pelo próximo.
Espectro muda o gráfico para um gráfico de frequência dos mesmos dados, com escolha de janela (Hann, Hamming, Blackman, retangular), Média e Reter pico entre quadros, e um eixo de Frequência logarítmica. A leitura abaixo do gráfico nomeia a frequência de pico e seu nível.
Pausar congela o gráfico sem afetar uma gravação; Estat. adiciona uma linha de mín. / máx. / RMS; e o menu do botão direito salva o gráfico como imagem.

Dois registros de forma de onda rolando ao vivo: um traço de microfone e um traço de IMU de três séries.#
Um campo de forma de onda recebe a taxa de amostragem e, para vários sinais ao mesmo tempo, o número de series intercaladas e seus nomes; cada atualização são os bytes brutos de um array de amostras no typecode do 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 profundidade#
Um registro depth é uma grade de distâncias – os quadros que um sensor time-of-flight produz – e a visualização o desenha como um mapa em falsa cor ampliado até a altura do gráfico. A barra de ferramentas escolhe a renderização: a paleta (as próprias paletas Profundidade, Arco-íris e Ironbow da câmera, mais paletas clara e escura para câmeras de eventos), o filtro de escala que amplia a pequena grade do sensor (bicúbica para uma superfície suave, bilinear, ou vizinho mais próximo para um bloco por pixel do sensor), e o mapeamento de tons que converte distância em cor: Faixa do script usa a faixa que o script declarou, Faixa automática estende as cores pelas distâncias realmente presentes em cada quadro (ignorando os poucos por cento discrepantes), e Equalizar as espalha pela distribuição do quadro, de modo que uma cena plana ainda mostre seus detalhes. O cabeçalho informa o tamanho do mapa, a faixa declarada e o mínimo, o máximo e a média do quadro; passar o cursor sobre o mapa lê a distância sob o cursor, e Salvar imagem grava o mapa renderizado em um PNG.

Um mapa de profundidade time-of-flight de uma mão em frente ao sensor, com os seletores de paleta, escala e mapeamento de tons na barra de ferramentas.#
Um campo de profundidade declara o tamanho de sua grade e sua faixa; cada atualização é a grade como floats de 32 bits empacotados, que é o que o leitor do módulo tof produz:
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. Gravação#
Todo gráfico e mapa tem um botão Gravar, e um canal com mais de um deles tem uma barra Gravar tudo que os inicia juntos. A gravação grava os dados conforme chegam – não a renderização – em um arquivo cujo formato segue a extensão que você escolhe na caixa de diálogo de salvar: CSV para planilhas e ferramentas de plotagem, WAV para formas de onda de áudio de canal único, arrays NumPy .npy para Python, e JSON ou CBOR do Edge Impulse para enviar diretamente a um projeto do Edge Impulse como dados de treinamento, com um rótulo opcional que nomeia os arquivos. Apenas os formatos que podem conter os dados de um registro são oferecidos; um mapa de profundidade, por exemplo, não pode ser um arquivo WAV. Uma captura longa é dividida em partes numeradas para que nenhum arquivo cresça demais, e uma gravação sobrevive ao script registrar seus canais de novo. A leitura ao lado do botão acompanha quantas amostras foram gravadas e o tamanho do arquivo.
O intervalo de Channel Polling do painel, na seção de protocolo das preferências, define com que frequência a IDE pede novos dados de canal à câmera; o padrão serve para scripts que publicam algumas vezes por segundo, e um script transmitindo áudio se beneficia de um intervalo mais curto.
Ver também
protocol.CBORChannel para o lado do script – os tipos de registro, seus argumentos e o callback on_write – e os exemplos 12-Protocol em File → Examples para scripts funcionais que publicam leituras, controles e um mapa de profundidade.