Dispositivos seriais e Arduino
As funções internas Serial* se comunicam com qualquer coisa que apareça como porta COM: um Arduino,
ESP32 ou Raspberry Pi Pico via USB, um adaptador USB-serial, um receptor GPS, um leitor de código de
barras no modo serial, uma impressora de recibos ou de etiquetas, uma impressora 3D ou um controlador
CNC que aceita G-code, um instrumento de laboratório, ou uma caixa de botões, um teclado de macros, um
botão giratório ou um controlador de LEDs feitos em casa. O dispositivo envia e recebe linhas de texto;
os seus scripts transformam essas linhas em qualquer outra coisa que o Input.Observer saiba fazer.
Algumas ideias:
- Uma caixa de botões ou um teclado de macros. Um Arduino lê os seus botões e imprime
B1,B2, ... Um monitor serial transforma cada linha em um atalho, uma tecla de mídia ou um comando de janela. - Um botão de volume ou de rolagem. Um potenciômetro ou um encoder rotativo imprime a sua posição; o monitor ajusta o volume ou rola a tela.
- Luzes de status. Um gesto ou uma tecla de atalho envia
LED 255 0 0a uma placa que controla uma fita de LEDs, para que uma luz mostre que a gravação está ativa ou que a compilação falhou. - Sensores. Um temporizador pede a uma placa a temperatura ou o nível de luz e o mostra, registra em um arquivo ou escurece a tela.
- Leitores e scanners. Cada código de barras ou etiqueta RFID que o leitor envia vira texto digitado, uma pesquisa ou uma consulta em um arquivo.
- Máquinas. Envie linhas de G-code a uma impressora ou plotter, um
SerialWriteTextLinepor comando.
Encontrar a porta
O Windows dá a cada dispositivo um nome como COM3. O Gerenciador de Dispositivos o lista em
Portas (COM e LPT); o Arduino IDE o mostra no seu menu de placas. Um script também pode listá-los:
n = SerialEnumeratePorts();
if (n == 0) UtilityPrint("No COM ports. Is the board plugged in?");
for (i = 0; i < n; i = i + 1) {
UtilityPrint(SerialGetEnumeratedPortAt(i));
}
A lista é ordenada por número, então COM3 vem antes de COM10. O número pode mudar quando o
dispositivo é conectado a outra porta USB.
Velocidade, enquadramento e terminações de linha
- A velocidade (
baudRate) precisa ser a mesma do dispositivo: o número noSerial.begin(...)de um sketch do Arduino, geralmente9600ou115200. - O enquadramento é quase sempre 8 bits de dados, sem paridade, um bit de parada:
8,SerialParity.None,SerialStopBits.One. Escreva as constantes: o número simples1como argumento de bits de parada significa um bit e meio de parada. - Terminações de linha. Uma linha recebida termina no
terminatorque você informar, que é removido da linha. Texto vazio significa CR LF, que é o que oSerial.printlndo Arduino envia. Para um dispositivo que termina as linhas só com LF, use"\n"; só com CR, use"\r".SerialWriteTextLinetermina o que envia com o mesmo terminador, ou com CR LF quando a chamada abre a porta por conta própria. Com CR LF, um sketch do Arduino que lê comSerial.readStringUntil('\n')recebe a linha com um CR no final, quetrim()remove; com"\n"não há CR para remover. - Sinais. Abrir uma porta liga os sinais DTR e RTS dela, como faz o Arduino IDE. Isso reinicia a maioria das placas Arduino Uno e Nano, e outras placas com o mesmo circuito de reinicialização.
Três formas de se comunicar com um dispositivo
-
Uma pergunta, uma resposta.
SerialWriteTextLineeSerialGetTextLineem uma porta que não está aberta a abrem com obaudRateda chamada, 8-N-1, só para essa chamada. O argumentobaudRateé ignorado quando a porta já está aberta. Serve para um dispositivo que não reinicia quando a sua porta é aberta. Consulte Fazer uma pergunta a um dispositivo serial. -
Uma porta mantida aberta.
SerialOpenPortabre a porta com as suas configurações atéSerialClosePorte reúne cada linha que o dispositivo envia paraSerialGetTextLineler. A maioria das placas Arduino Uno e Nano reinicia sempre que a sua porta é aberta, então abra a porta uma vez, no evento global Load, e deixe os gestos e as teclas de atalho escreverem nela.SerialOpenPortretornafalsepara uma porta que não existe, está desconectada ou aberta em outro programa; para uma porta que o Input.Observer já tem aberta, ou que um monitor ocupa, interrompe a ação com um erro.// Load global event: open the port once, at the sketch's speed. An Uno or Nano// restarts every time its port opens, so a port opened per command would lose// the command while the board boots.if (!SerialOpenPort("COM4", 115200, SerialParity.None, 8, SerialStopBits.One, "")) {UtilityPrint("COM4 isn't available: unplugged, or open in the Arduino IDE's Serial Monitor?");}// Any gesture or hotkey: send a command line and read the board's reply.// (The sketch reads a line with Serial.readStringUntil('\n') and answers OK.)if (SerialWriteTextLine("COM4", "LED 255 0 0", 115200)) {reply = SerialGetTextLine("COM4", 1, 115200);if (reply != "OK") UtilityPrint(StringFormat("Board said: {0}", reply, ""));} -
Um monitor.
SerialMonitorCreateexecuta um script para cada linha que o dispositivo envia, em segundo plano, atéSerialMonitorDelete. A linha éContextGetSerialTextLine(). Consulte Mapear os botões de um dispositivo serial para teclas de mídia e:// Arduino side: a potentiometer on A0, one reading per line.// void setup() { Serial.begin(115200); }// void loop() { Serial.println(analogRead(A0)); delay(50); }// Empty text as the terminator means CR LF, which Serial.println sends.SerialMonitorCreate("knob", "COM4", 115200, SerialParity.None, 8, SerialStopBits.One, "","line = ContextGetSerialTextLine(); if (StringIsNumber(line, true)) MultimediaSetVolume(AudioEndpoint.Playback, StringToNumber(line, true) / 1023.0);");
O que saber sobre os monitores.
- As linhas são executadas uma de cada vez, na ordem em que chegaram: o script da próxima linha começa quando o script da anterior termina. Até 256 linhas aguardam; além disso, as mais antigas são descartadas.
- Parar todas as ações interrompe o script em execução para uma linha e descarta as linhas em espera. O próprio monitor continua em execução. A Tecla de atalho para parar todas as ações vai além: ela exclui todos os monitores e fecha a porta de cada um.
- Qualquer script, inclusive o do próprio monitor, pode enviar para uma porta monitorada com
SerialWriteTextLine, então um monitor pode responder ao seu dispositivo.SerialGetTextLinenão consegue ler uma porta monitorada: toda linha vai para o monitor. - Cada nome de monitor pertence a uma porta.
SerialMonitorCreatecom o nome do monitor desta porta substitui esse monitor. Ele interrompe a ação com um erro quando o nome já monitora outra porta, quando a porta está aberta comSerialOpenPortou quando outro monitor ocupa a porta. Uma porta que não existe, está desconectada ou aberta em outro programa resulta emfalse. - Desconectar o dispositivo encerra o monitor e grava uma linha na guia Sistema do console. Nada
reinicia o monitor quando o dispositivo volta. Execute o
SerialMonitorCreatede novo (por uma tecla de atalho ou pelo evento Load na próxima inicialização).
Só um programa por vez pode manter uma porta COM aberta. Enquanto o Serial Monitor ou o Serial
Plotter do Arduino IDE estiver aberto, o Input.Observer não consegue abrir a porta, e, enquanto o
Input.Observer a mantiver aberta, o IDE não consegue carregar um sketch. Feche a porta
(SerialClosePort ou SerialMonitorDelete) antes de carregar.