One daemon per room.
A single edge daemon joins every instrument on the bench to the same control plane, no per-instrument gateways, no vendor lock-in.
Platform
Every instrument, one control plane
Connect and control every instrument. Daemons at the edge speak the protocols your hardware already speaks, SCPI over VISA (GPIB, USB-TMC, TCP/IP, serial), Modbus TCP/RTU, NI-DAQmx, and HTTP, with versioned profiles and tight local loops when latency matters.
Most labs run a museum of vendor software, one app per box, each with its own driver, its own scripting dialect, its own idea of where data goes. Carbon collapses that into a single control plane. A daemon sits on your network, speaks every instrument's native protocol, VISA, Modbus, DAQmx, HTTP, and presents one consistent surface to your team and to the AI working alongside them.
One command
The daemon installs as one binary. Start it on a bench machine and it discovers instruments, loads their profiles, and registers with your team over an encrypted connection.
A single edge daemon joins every instrument on the bench to the same control plane, no per-instrument gateways, no vendor lock-in.
Oscilloscopes, VNAs, lock-ins, cryostat controllers, and more, declared in versioned profiles your whole team shares and extends.
Drivers execute at the edge with tight loops at the bench, while telemetry streams up to the cloud in parallel.
How it works
Run one daemon per room. It discovers instruments across GPIB, USB, TCP/IP, serial, and Modbus and matches each to a versioned profile.
Drive instruments through the platform or let the agent drive. Loops execute at the edge; every reading streams to the cloud.
Add a bench, add a daemon. Every new instrument joins the same control plane, no rewiring, no per-device gateway.
Instrument profiles
A profile declares a device's transport, variables, and commands in plain YAML, the same shape whether it speaks SCPI, Modbus, or DAQmx. Your team reads, reviews, and extends them like any other code.
apiVersion: v1alpha1
identity:
manufacturer: "Stanford Research"
model: "SR860"
connection:
terminator: "\n"
bus:
- type: "gpib"
timeout: 5000
variables:
time_constant:
type: "enum"
options: ["10ms", "30ms", "100ms"]
default: "100ms"
commands:
read_xy:
type: "read"
command: "SNAP? 0,1"
response:
type: "tuple"
fields: [{ name: x }, { name: y }]apiVersion: v1alpha1
identity:
manufacturer: "ACME"
model: "DC Bank 48"
driver:
type: "modbus"
connection:
bus:
- type: "modbus-tcp"
host: "10.0.4.21"
port: 502
slave_id: 1
variables:
voltage:
type: "float"
range: { min: 0, max: 48 }
commands:
set_voltage:
type: "write"
command: "WR 0x0001" # holding register
read_current:
type: "read"
command: "IR 0x0010" # input registerapiVersion: v1alpha1
identity:
manufacturer: "National Instruments"
model: "USB-6212"
driver:
type: "daqmx"
commands:
read_ai0:
type: "read"
command: "AI Dev1/ai0"
set_ao0:
type: "write"
command: "AO Dev1/ao0"
pulse_do:
type: "write"
command: "DO Dev1/port0/line0"