Serial devices and Arduino
The Serial* builtins talk to anything that shows up as a COM port: an Arduino, ESP32 or Raspberry
Pi Pico over USB, a USB-to-serial adapter, a GPS receiver, a barcode scanner in serial mode, a
receipt or label printer, a 3D printer or CNC controller that takes G-code, a lab instrument, or a
home-made button box, macro pad, rotary knob or LED controller. The device sends and receives lines
of text; your scripts turn those lines into anything else Input.Observer can do.
Some ideas:
- A button box or macro pad. An Arduino reads its buttons and prints
B1,B2, ... A serial monitor turns each line into a shortcut, a media key or a window command. - A volume or scroll knob. A potentiometer or rotary encoder prints its position; the monitor sets the volume or scrolls.
- Status lights. A gesture or hotkey sends
LED 255 0 0to a board driving an LED strip, so a light shows that recording is on or the build failed. - Sensors. A timer asks a board for a temperature or light level and shows it, logs it to a file, or dims the screen.
- Scanners and readers. Every barcode or RFID tag the reader sends becomes typed text, a search, or a lookup in a file.
- Machines. Send G-code lines to a printer or plotter, one
SerialWriteTextLineper command.
Finding the port
Windows gives each device a name like COM3. Device Manager lists it under Ports (COM & LPT);
the Arduino IDE shows it in its board menu. A script can list them too:
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));
}
The list is sorted by number, so COM3 comes before COM10. The number can change when the device
moves to another USB socket.
Speed, framing and line endings
- Speed (
baudRate) must match the device: the number in an Arduino sketch'sSerial.begin(...), usually9600or115200. - Framing is almost always 8 data bits, no parity, one stop bit:
8,SerialParity.None,SerialStopBits.One. Write the constants: the plain number1as a stop-bits argument means one and a half stop bits. - Line endings. A received line ends at the
terminatoryou give, which is removed from the line. Empty text means CR LF, which Arduino'sSerial.printlnsends. For a device that ends lines with LF alone, use"\n"; for CR alone, use"\r".SerialWriteTextLineends what it sends with the same terminator, or with CR LF when the call opens the port itself. With CR LF, an Arduino sketch reading withSerial.readStringUntil('\n')gets the line with a trailing CR, whichtrim()removes; with"\n"there is no CR to remove. - Signals. Opening a port turns on its DTR and RTS signals, as the Arduino IDE does. That restarts most Arduino Uno and Nano boards, and other boards with the same reset circuit.
Three ways to talk to a device
-
One question, one answer.
SerialWriteTextLineandSerialGetTextLineon a port that isn't open open it at the call'sbaudRate, 8-N-1, for that one call. ThebaudRateargument is ignored when the port is already open. Fine for a device that doesn't restart when its port opens. See Ask a serial device a question. -
A port kept open.
SerialOpenPortopens the port with your settings untilSerialClosePort, collecting every line the device sends forSerialGetTextLineto read. Most Arduino Uno and Nano boards restart whenever their port opens, so open the port once, in the Load global event, and let gestures and hotkeys write to it.SerialOpenPortreturnsfalsefor a port that is missing, unplugged or open in another program; for a port that Input.Observer already has open, or that a monitor holds, it stops the action with an error.// 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, ""));} -
A monitor.
SerialMonitorCreateruns a script for every line the device sends, in the background, untilSerialMonitorDelete. The line isContextGetSerialTextLine(). See Map a serial device's buttons to media keys and:// 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);");
What to know about monitors.
- Lines run one at a time, in the order they arrived: the script for the next line starts when the script for the previous one has ended. Up to 256 lines wait; beyond that the oldest are dropped.
- Stopping all actions stops the script running for a line and drops the lines waiting. The monitor itself keeps running. The Stop all actions hotkey goes further: it deletes every monitor and closes its port.
- Any script, the monitor's own included, can send to a monitored port with
SerialWriteTextLine, so a monitor can answer its device.SerialGetTextLinecan't read a monitored port: every line goes to the monitor. - Each monitor name belongs to one port.
SerialMonitorCreatewith the name of this port's monitor replaces that monitor. It stops the action with an error when the name already monitors another port, when the port is open withSerialOpenPort, or when another monitor holds the port. A port that is missing, unplugged or open in another program givesfalse. - Unplugging the device ends the monitor and writes a line to the console's System tab.
Nothing restarts the monitor when the device comes back. Run the
SerialMonitorCreateagain (from a hotkey, or the Load event at the next start).
Only one program can have a COM port open. While the Arduino IDE's Serial Monitor or Serial
Plotter is open, Input.Observer can't open the port, and while Input.Observer has it open, the IDE
can't upload a sketch. Close the port (SerialClosePort or SerialMonitorDelete) before uploading.