13.1.9. A vista Canais#
O buffer de fotograma mostra o que a câmara vê; a vista Canais mostra o que o script mede e decide. Um script publica valores nomeados através do protocolo de depuração – uma temperatura, uma contagem de deteções, uma forma de onda de microfone, um mapa de profundidade de tempo de voo, ou um controlo que quer que o utilizador possa alterar – e o IDE apresenta cada um em direto como um widget, um gráfico ou um mapa no painel abaixo do buffer de fotograma. Nada tem de ser desenhado na imagem nem extraído do terminal. Do lado da câmara são algumas linhas com protocol.CBORChannel; do lado do IDE é a entrada Canais do seletor do painel.

Os controlos de um script de câmara térmica: duas leituras de temperatura, interruptores para os modos de medição e deslizadores para o intervalo de temperatura. Alterar qualquer um deles envia o novo valor para o script.#
A vista está organizada por canal. Cada canal que o script regista torna-se uma secção com o nome do canal como título, e cada registo no canal torna-se uma linha por baixo, pela ordem em que o script os adicionou. Quando o script regista um canal ou altera a forma de um, a vista reconstrói-se; quando o script para, os últimos valores permanecem no ecrã, com os controlos desativados, até o script seguinte começar.
13.1.9.1. Widgets#
As leituras e os controlos assumem as formas óbvias. Um label é um valor só de leitura com a sua unidade; um registo text é um bloco de texto formatado estático para títulos e explicações. Os tipos editáveis enviam o seu novo valor de volta para o script no momento em que o altera, onde o callback on_write do script recebe o nome e o valor do registo: um toggle é um interruptor, um slider e um spinbox definem um número dentro do intervalo e do passo do script (a caixa de incremento para introdução precisa), os 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 vista mantém a sua edição no ecrã em vez de a repor no último valor publicado pela câmara enquanto a escrita está em curso.
Do lado do script, o conjunto completo é 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: aparece uma secção chamada controls com os cinco widgets, e mover o deslizador imprime no terminal. Os outros tipos de widget – spinbox, radio, lineedit, text – são mais um add cada; o capítulo do protocolo de anfitrião percorre todos eles.
13.1.9.2. Gráficos de forma de onda#
Um registo waveform é um bloco de amostras intercaladas com uma taxa de amostragem – áudio, eixos de acelerómetro, um traço de ADC – e a vista traça-o como um gráfico deslizante, uma série por eixo, nomeada pelo script. Os controlos do gráfico estão na sua barra de ferramentas e no próprio gráfico:
Arraste para deslocar e use a roda do rato para ampliar; faça duplo clique para voltar a seguir a margem em direto. Histórico define quantos dados passados são mantidos para que possa recuar através deles.
Escala Automática ajusta o eixo vertical aos dados; desativada, o eixo é o intervalo 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 disparo. Com um Disparo armado, o gráfico fica imóvel até o sinal cruzar o nível num flanco ascendente ou descendente – a forma do osciloscópio de apanhar um transitório – e Rearmar espera pelo seguinte.
Espetro 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 fotogramas, e um eixo de Frequência Logarítmica. A leitura sob o gráfico indica a frequência de pico e o seu nível.
Pausa congela o gráfico sem afetar uma gravação; Estat. acrescenta uma linha de mín / máx / RMS; e o menu de contexto guarda o gráfico como imagem.

Dois registos de forma de onda a deslizar em direto: 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 os seus nomes; cada atualizaçã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 registo depth é uma grelha de distâncias – os fotogramas que um sensor de tempo de voo produz – e a vista desenha-o como um mapa de falsa cor ampliado até à altura do gráfico. A barra de ferramentas escolhe a renderização: a paleta (as paletas Depth, Rainbow e Ironbow da própria câmara, mais paletas clara e escura para câmaras de eventos), o filtro de escala que amplia a pequena grelha do sensor (bicúbico para uma superfície suave, bilinear, ou vizinho mais próximo para um bloco por pixel do sensor), e o mapeamento de tons que transforma distância em cor: Intervalo do script usa o intervalo que o script declarou, Intervalo automático estende as cores pelas distâncias realmente presentes em cada fotograma (ignorando os poucos por cento extremos), e Equalizar distribui-as pela distribuição do fotograma, para que uma cena plana continue a mostrar os seus detalhes. O cabeçalho indica o tamanho do mapa, o intervalo declarado e o mínimo, máximo e média do fotograma; passar o rato sobre o mapa lê a distância sob o cursor, e Salvar imagem escreve o mapa renderizado num PNG.

Um mapa de profundidade de tempo de voo 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 da sua grelha e o intervalo; cada atualização é a grelha 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#
Cada gráfico e mapa tem um botão Record, e um canal com mais do que um deles tem uma barra Record All que os inicia em conjunto. A gravação escreve os dados à medida que chegam – não a renderização – num ficheiro cujo formato segue a extensão que escolher no diálogo de guardar: CSV para folhas de cálculo e ferramentas de gráficos, WAV para formas de onda de áudio de um só canal, arrays NumPy .npy para Python, e JSON ou CBOR Edge Impulse para carregar diretamente num projeto Edge Impulse como dados de treino, com uma etiqueta opcional que dá nome aos ficheiros. Só são oferecidos os formatos que conseguem conter os dados de um registo; um mapa de profundidade, por exemplo, não pode ser um ficheiro WAV. Uma captura longa é dividida em partes numeradas para que nenhum ficheiro cresça demasiado, e uma gravação sobrevive a um novo registo dos canais pelo script. A leitura ao lado do botão acompanha quantas amostras foram escritas e o tamanho do ficheiro.
O intervalo de Channel Polling do painel, na secção de protocolo das preferências, define a frequência com que o IDE pede novos dados de canal à câmara; a predefinição serve para scripts que publicam algumas vezes por segundo, e um script a transmitir áudio beneficia de um intervalo mais curto.
Veja também
protocol.CBORChannel para o lado do script – os tipos de registo, os seus argumentos e o callback on_write – e os exemplos 12-Protocol em Ficheiro → Exemplos para scripts funcionais que publicam leituras, controlos e um mapa de profundidade.