Skip to content
Christian edited this page Sep 29, 2026 · 1 revision

The Laser is QiTech's laser diameter gauge, available with one or two measuring axes. QiTech Control runs both variants as the same machine, Laser V1, over Modbus RTU on a USB serial port.

Machine ID 6
Schema laser_v1.yaml
Code laser_v1.rs, driver qitech_laser in qitech_lib

Specifications

Interface USB serial
Protocol Modbus RTU, the laser is the slave
Serial settings 38400 baud, 8 data bits, no parity, 1 stop bit (8N1)
Slave address 1
Axes 1, or 2 (X and Y)
Measurement rate 320 measurements per second (manufacturer specification)

Device settings

The laser has a small display for its own settings:

  • Unit: millimetres or inches. QiTech Control expects millimetres.
  • Alarm: the laser can beep when the diameter is out of tolerance. The laser's own tolerance is separate from the tolerance set in QiTech Control, so the two can differ.
  • Communication:
    • Set UART: 8N1 and 38400 baud. These are the settings the driver uses.
    • Set Protocol: Modbus RTU.
    • Set Slave Address: 1. If you change it, enter the same value as the slave ID when you assign the port (see below).
  • Calibration: with the 4 mm and 8 mm reference rods.

Connecting the laser

The laser isn't detected automatically. You bind its USB serial port to a Laser V1 machine once on the Setup page; the backend reads this binding at startup. For the general mechanism, see Identification.

  1. Plug the laser's USB serial adapter into the control PC.
  2. Open Setup → Modbus. The USB Serial Ports table lists every port with its USB description, VID:PID and USB serial number. If the port is missing, click Rescan ports.
  3. Click Assign in the laser's row. In the Machine Assignment dialog:
    • Maschine: select Laser V1.
    • Serial: the serial number of this laser (a number up to 65534). It identifies the machine in the UI and in the API.
    • Modbus Slave ID: the laser's slave address (default 1, allowed 1–254).
  4. Click Apply & restart. This saves the assignment and restarts the backend. Alternatively, click Save and restart later with Setup → Troubleshoot → Restart Backend Process.
  5. After the restart, the laser appears as Laser V1 in the machine list. The backend reads the assignments only at startup, so the laser has to be plugged in when the backend starts; otherwise no Laser V1 machine is created.

To remove a binding, open the dialog again, click Unassign, and restart the backend.

Where the assignment is stored

The backend writes the assignments to $STATE_DIRECTORY/modbus_assignments.json (assignments.rs). On the QiTech NixOS image that's /var/lib/qitech/modbus_assignments.json. Without STATE_DIRECTORY (development), the backend falls back to $XDG_STATE_HOME, then $HOME, then the working directory.

[
  {
    "port": "pci-0000:00:14.0-usb-0:1:1.0-port0",
    "machine": { "machine": { "vendor_id": 1, "machine_id": 6 }, "serial": 1 },
    "slave_id": 1
  }
]
  • port is the port's name under /dev/serial/by-path. It depends on the physical USB socket, not on the adapter, so it survives replugging into the same socket. Plugged into another socket, the adapter gets a new name and has to be assigned again.
  • Assigning a port that already has an entry replaces it. The file is written to a temporary file first and then renamed, so a crash can't truncate it. A missing or unreadable file counts as "nothing assigned".
  • An assigned port that is currently unplugged stays in the table as Not plugged in, so you can still reassign or unassign it.

What the software computes

LaserV1 (laser_v1.rs) does this every cycle:

  1. Polling. It asks the laser for a new reading at most every 6 ms, and only once the previous request has been answered. Each request reads up to three input registers from address 0x0E: diameter, X and Y, in µm. The values are converted to mm. A one-axis laser only returns the diameter, so X and Y stay empty.
  2. Roundness (two-axis only). roundness = min(X, Y) / max(X, Y), a ratio from 0 to 1 (the Control tab shows it in %). It's 0 when both axes read 0, and empty when only one of them is 0 or an axis is missing. The Control tab shows the X, Y and roundness values only when the laser reports them.
  3. In tolerance. in_tolerance is true while target − lower < diameter < target + upper.
  4. Out of tolerance. When in_tolerance changes from true to false, the machine emits the out_of_tolerance event.

Communication errors

The driver waits up to 2 s for each response. On a serial I/O error it reopens the port and retries the request once.

  • A serial I/O error that remains after the retry stops the machine at once (Physical hardware I/O broke.).
  • Other errors, such as timeouts or Modbus exceptions, are counted. Three in a row (about 6 s of silence) stop the machine (Laser stopped responding after 3 consecutive failed requests.).

A stopped machine is removed from the runtime and disappears from the UI. It only comes back after a backend restart.

Configuration

Parameter Config path Unit Default Range UI
Target diameter diameter.target mm 1.75 0–5 Control tab, Set Target Diameter
Lower tolerance diameter.tolerance.lower mm 0.05 ≥ 0 Control tab, Set Lower Tolerance (the UI limits it to 1 mm and to the target)
Upper tolerance diameter.tolerance.upper mm 0.05 0–1 Control tab, Set Higher Tolerance
Global warning global_warning – on – Config tab, Global Warning

The backend doesn't evaluate global_warning; it only stores it. The frontend uses it: while it's on, every state update with in_tolerance false shows an app-wide toast Laser diameter is out of tolerance that stays until dismissed. The frontend watches the first laser it finds.

Setting a target below the current lower tolerance also lowers the lower tolerance to the new target. Config values are held in memory, so they're back to their defaults after a backend restart.

Use with the winder

A winder can use the laser to adapt its puller speed to the measured diameter. In the winder's Adaptive Speed settings, select the laser as Reference Machine; only Laser V1 machines are offered. The winder then subscribes to the laser's diameter measurement and diameter.target config. With the puller's Adaptive speed algorithm, it nudges the puller faster when the filament is too thick and slower when it's too thin. See Winder for the parameters.

Clone this wiki locally