The Serial Out node is the writing complement to the Serial input. Wire any source — a key, a MIDI knob, a Resolume-in subscription — into a serial-out, and the value goes straight to a COM port. If you've been wishing your Arduino LED ring would mirror the Resolume opacity slider, this is what closes the loop.
Where it lives
Add one with the Serial Out button on the topbar. The node body shows the chosen port, baud rate, and the current payload template. Like every sink it has a left-side input handle.
Inspector
Each serial-out node carries:
- Port — picked from the OS's COM-port list. Refresh re-queries
serialport.list(). If you select a port that disappears (cable unplugged, firmware reset), the picker remembers the choice and tags it as(offline)until it reappears. - Baud rate — matches your firmware's
Serial.begin(). Defaults to 9600. - Payload template — the bytes XOSC writes on each fire. See Placeholders below.
- Line ending — appended raw after the rendered template. Defaults to
\n, which is what most Arduino sketches read withSerial.readStringUntil('\n'). - Trigger mode — same semantics as OSC out: Pulse fires on press, Toggle alternates 1/0, Hold sends 1 down + 0 up. Continuous inputs (CC, axis, parameter feedback) ignore trigger mode and stream the normalized value.
Placeholders
The payload template is sent verbatim with these substitutions:
| Placeholder | Replaced with |
| ----------- | -------------------------------------------------------------- |
| {v} | The 0..1 normalized value, formatted to 3 decimals (0.500) |
| {V} | The same value scaled to 0..255 as a byte string (128) |
| {s} | 1 or 0 reflecting press / toggle / hold state |
Discrete pulse fires use 1 for {v} / 255 for {V} / 1 for {s}. The line ending is appended after substitution.
Useful templates
{V}— bare 0..255 byte. Pair withSerial.parseInt()on the firmware side.LED:{V}— labelled command. Lets the same firmware multiplex many LEDs without ambiguity.{v}— 0..1 float. Useful when the firmware does its own scaling (e.g. PWM duty cycle).{s}— bare state. For button-mirror firmware where you only need on / off.
Sharing a port with a serial-input node
This is supported and probably what you want. XOSC's serial bridge opens each (path, baudRate) once; the same handle reads incoming bytes (for the input node) and writes outgoing bytes (for the output node). If two nodes pick conflicting baud rates, the first to open wins and the bridge logs a warning — fix it by setting both to the same rate.
Example: Arduino LED mirror
The Arduino sketch:
const int LED_PIN = 9; // PWM-capable
void setup() {
pinMode(LED_PIN, OUTPUT);
Serial.begin(115200);
}
void loop() {
if (Serial.available()) {
int v = Serial.parseInt();
analogWrite(LED_PIN, constrain(v, 0, 255));
while (Serial.available()) Serial.read(); // drain to next \n
}
}
In XOSC, add a resolume-in subscribed to /composition/layers/1/video/opacity, a serial-out with {V} payload at 115200 baud, and wire them together. Nudge the Resolume slider; the LED dims and brightens with it.
Limits
- One write at a time per port. The bridge serialises calls; back-to-back fires queue up. At 60 Hz axis traffic this is fine; if you wire many continuous sources to the same port, raise the per-edge throttle.
- No flow control. If the firmware is slow to read its buffer it eventually overflows and bytes drop. Keep the firmware loop tight.