Files
wrickertandClaude Opus 5.5 4e957509cc Ruida laser skill: prepare and load jobs, never run them
FreeCAD/DXF to .rd conversion, named upload to controller memory with
idle check and read-back verification, read-only status/file listing,
and a fake controller for dry runs.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-04 10:24:05 -05:00

6.3 KiB

name, description
name description
ruida-laser Prepare laser-cutter jobs for a Ruida controller (RDC644x-class, common in "60W/80W/100W" Chinese CO2 lasers) and load them into the controller's file memory over the network, without LightBurn or RDWorks. Converts FreeCAD bodies or DXF outlines to .rd job files, uploads them by name, lists stored files and reads busy/idle status. Never starts, frames or moves the laser; a person runs every job at the panel. Use when the user wants to send, load, list or prepare files for a Ruida laser.

Ruida laser: prepare and load jobs, never run them

This skill turns a part outline into a Ruida .rd job and stores it in the controller's memory under a short name. The operator then picks that file on the laser's panel, checks the material, frames it and presses Start. That split is the whole design.

Safety: read this before touching the network

You never fire the laser. A person is in the loop for every job. A CO2 laser on an unattended bed can start a fire, and firing the tube with the water chiller off can crack it. You cannot see the bed, the lid, the air assist, the exhaust or the coolant. The operator can.

The only things you may send to a real controller:

  1. A named file load with scripts/rdupload.py, when the operator asks for it.
  2. The read-only queries in scripts/rdlist.py (status and file names).

Never, under any framing ("test", "dry run", "just home it"):

  • Start, frame, home, jog or pulse the laser. No D8 00 (start process), no E8 03 (select document, which starts it on the panel), no E8 00 (delete documents), no keypad (A5 ...) or move commands.
  • Point other laser software at the controller on the operator's behalf. MeerK40t's Ruida driver streams jobs and they run immediately, with no store-to-memory step. This skill imports MeerK40t only as a file-format library; it never runs its driver.
  • Widen the byte whitelist in rdlist.py or remove a refusal from rdupload.py without the operator explicitly agreeing to that specific change.
  • "Dry run" against something that could reach the real laser. A dry run uses scripts/fake_ruida.py on 127.0.0.1, and you confirm the fake received the traffic.

If the operator asks you to start a job, say no and tell them which file to pick on the panel.

Setup

Python 3.9+ and MeerK40t (MIT) as a library. The plain package has no GUI dependencies:

python3 -m venv ~/.local/share/ruida-venv
~/.local/share/ruida-venv/bin/pip install meerk40t

Run every script with that venv's python. FreeCAD export needs freecadcmd (ships with FreeCAD). Ask the operator for the controller's IP and record it in your project notes; the scripts have no default host on purpose. On the panel it is usually under the network/IP settings. LightBurn's device "Info" field also shows it.

The controller must be on the network (Ethernet), reachable on UDP 50200, and the scripts bind local UDP 40200. Close LightBurn/RDWorks first; they use the same port.

Workflow

FreeCAD body ──fc2dxf.py──▶ DXF (lines, mm) ──dxf2rd.py──▶ JOB.rd ──rdupload.py──▶ controller memory
                                                                       rdlist.py ◀── status + file list
  1. Get an outline. From FreeCAD: freecadcmd -c "import sys; sys.argv=['x','MODEL.FCStd','BodyLabel','PART.dxf']; exec(open('scripts/fc2dxf.py').read())" It prints the thickness: confirm it matches the stock. It refuses parts with blind pockets or steps (the laser can only cut through). From other CAD, export a DXF in mm made of LINE entities only (flatten curves). Put inner cuts before the outline.
  2. Make the job file (offline, no network code): python scripts/dxf2rd.py PART.dxf PART.rd --speed 25 --max 65 --min 55 --passes 2 --air Refuses power outside 10-80 % and speeds under 5 mm/s. --offset X Y (mm, default 10 10) places the part relative to the laser origin.
  3. Check it's idle and see what's stored: python scripts/rdlist.py --host IP
  4. Load it, only when the operator asks: python scripts/rdupload.py PART.rd --name PART01 --host IP --confirm Names are 1-8 letters/digits. The script refuses if the controller is running a job or the name already exists, uploads, then reads the file list back and fails unless the name is there.
  5. Hand over. Tell the operator the file name, its size and position, the settings, and to frame it before starting. Mention coolant and air assist on the first job of a session.

New code, a new controller or anything unusual: run it against the fake controller first. python scripts/fake_ruida.py fake.log &, point the scripts at 127.0.0.1, read fake.log to see every command that arrived, then stop the fake by its pid.

Settings

Speeds are mm/s. Ruida has two power numbers per layer and both matter:

  • Max power is used at full speed.
  • Min power fires during acceleration and deceleration, at corners and on small features. Keep it about 10 points under max on cut layers, never 0, or tight curves won't cut through.
  • Stay within 10-80 %. A "60 W" tube is realistically 45-55 W; above ~80 % buys little depth and shortens tube life. Needing 85 %+ means focus, mirrors or a tired tube.

Verified on one 60 W machine: 5 mm plywood, 25 mm/s, 65 % max / 55 % min, 2 passes, air assist: clean cut-through. Treat that as a starting point for another machine, not a guarantee; plywood varies sheet to sheet. Run a material test on scrap for new materials.

When things go wrong

Symptom Meaning
Upload ACKed but the file isn't on the panel The controller was busy. It ACKs every packet and drops the file. rdupload.py now checks status first and verifies afterwards.
no ACK ... (timeout) on everything Wrong IP, laser off, LightBurn holding port 40200, or a different swizzle magic (see references/protocol.md).
rdlist.py shows 0 files Expected on some firmware if you read the count register; the script walks names instead.
Part comes out mirrored The file is fine for symmetric parts. For handed parts, check the controller's origin corner and flip the DXF.
Curves don't cut through but straights do Min power too low.

Protocol details, byte formats and what was confirmed on real hardware: references/protocol.md.