Skip to main content

Open-source USB control stack for Roland DG MDX-series desktop mills

Project description

RollingMill

RollingMill logo

Open-source USB control stack for Roland DG MDX-series desktop mills, tested on the MDX-40A.

RollingMill communicates directly with the machine over libusb, replacing both the proprietary Windows kernel driver and the VPanel control application. It provides a terminal application that:

  • Shows live machine state read-out
  • Jogs four axes at variable speed, with cancel
  • Moves to stored origins, view position, or arbitrary coordinates
  • Controls spindle speed and rotary-axis drilling
  • Sets workspace origins and tool diameter offsets
  • Streams saved G-code (.nc files) to the mill
  • Runs on Linux and macOS

https://github.com/user-attachments/assets/d28e8a8f-c5a4-4877-8cd2-d2d479c63437

Reverse Engineering

The MDX USB protocol was reverse engineered from the official Windows driver stack using Ghidra (and the MCP bridge) and documented here in this respository. It should be stated that the Roland DG corporation neither authorised or approved of this work.

The official Windows stack consists of:

  • RD25D — kernel-mode USB and printer filter driver
  • VPanel — user-space control application

RollingMill implements both layers in Python, and works great on macOS.

Getting started

This library is available from PyPi as rollingmill.

$ pip install rollingmill
$ rollingmill                                            # launch TUI on real hardware
$ rollingmill --file sample-nc/example-doc-part.gcode    # stream an NC file

The interactive TUI exposes the following keybindings:

Jogging

Key Action
/ X axis −/+
/ Y axis −/+
a / z Z axis +/− (a raises, z lowers)
[ / ] A axis −/+
Esc cancel an in-flight jog
f cycle jog speed: vslow / slow / medium / fast
15 step size: XYZ 0.01 / 0.1 / 1.0 / 10.0 / 50.0 mm — A 0.01 / 0.1 / 1.0 / 10.0 / 90.0°

Spindle

Key Action
s spindle on / off
d A-axis rotary drilling on / off
< / > spindle target RPM −500 / +500
- / + spindle & feed override % −10 / +10

Dialogs

Key Action
c coordinate systems (activate / move-to / overwrite)
m Move-To picker (presets + User Specify numeric entry)
t tool diameter offsets
q quit

Cut panel (only when --file is given)

Key Action
r run — stream the file continuously to the end
x step — send one block; or, while running, stop after the current block

Gotchas/Notes using the mill

  • If your NC-code 'crashes' the Z position above absolute machine zero (i.e. at the top of the machine), then the machine's interpreter starts running all future G codes as rapid moves flattened against Z=0 (all feeds become rapid moves, descending is inhibited) until the end of the program. This is quite terrifying should it happen, but is a machine feature.
  • If you send NC-code (i.e. G-code) in RML-1 mode, it will hang. Recovery for now is a power-cycle.
  • Single-stepping nc-code partially works, but the MDX complains about being starved of NC code and lights the View-LED when you reach a cutting operation.
  • The progress display during a cutting job is that of filling the machine buffer, rather than the actual block being executed, which usually runs a few blocks behind. It's a shame there are not two counters so that this could be made 100% accurate.
  • There might be an issue with storing A-axis values in workspace offsets and recalling them, as sometimes I get an extra +360° rotation on recall.
  • I need a Z-origin sensor to test the sensor-based Z-origin setting, and decode the thickness settings — NYI.
  • The geometry of the mill means that without tooling, it is fairly difficult (but not impossible) to crash. The rotary axis makes this much easier as the firmware allow the collet to hit the vice area.
  • Be warned that bad, terrible things could happen driving your hardware with this experimental software, due to known or unknown bugs or defects, for which you entirely agree to take all risks in operating and hold the contributors blameless.

MDX GCode Intepreter Notes

  • G-codes must be two digits (G01, G00 etc)
  • Dont forget to turn the spindle on (Sxxxx M03) otherwise the machine will fault on the first G01 operation
  • Ensure all XYZ values have a decimal point, and no more than 3 digits of precision
  • Feed rates need a decimal point too
  • Machine coordinate moves G53 must be always given in G90 absolute programming. Specifying G53 in G91 incremental results in an error.

Check your code using this online G-code viewer, customised for the MDX G-code varient.

ZCL-40A 4th Axis

When this unit is installed, the X-, Y-, and Z-axis travel of the MDX-40A is reduced:

Axis MDX-40A MDX-40A + ZCL-40A
X 0 → 305 mm 34 → 305 mm
Y 0 → 305 mm 0 → 305 mm
Z 0 → −105 mm 0 → −68 mm
A 0 → 360° (continuous)

These limits are enforced in firmware, including from the physical jog controls on the machine itself. The X-restriction clears the rotary axis body, but not the rotary vice or tailstock, so care is needed.

Engraving text

rollingmill.text_to_gcode renders a text string to a single-line G-code file using a Hershey stroke font from the pyhershey library. Glyphs carry per-character advance-width metrics, so spacing is naturally kerned. The output is plain RS-274 intended to be streamed via the TUI's --file flow.

python -m rollingmill.text_to_gcode \
    --text "Parcels" \
    --out /tmp/label.gcode \
    --height 8 \
    --z-cut -0.1 --z-safe 2 \
    --feed 200 \
    --workspace G54

--workspace G54..G59 is optional; when set, the matching WCS-select word is emitted in the header so the cut runs against that work-offset.

Then load on the machine: rollingmill --file /tmp/label.gcode.

The default font is roman_simplex. List all available fonts with --list-fonts; pass any name (e.g. --font gothic_german_triplex) to switch. Use --letter-spacing 1.5 to add (or, with a negative value, remove) extra mm of gap after each glyph's natural advance.

Engraving text

Drawing spirals

rollingmill.spiral renders hypotrochoids, the curve traced when a small toothed wheel rolls inside a fixed toothed ring. You give it the two gear tooth counts and a pen-arm length, and it emits a single closed pen-down/pen-up loop scaled to fit your requested overall radius.

python -m rollingmill.spiral \
    --ring 96 --rotor 52 --pen 30 \
    --radius 40 --x0 100 --y0 100 \
    --out /tmp/spiral.gcode \
    --workspace G54

--ring R and --rotor r are tooth counts (R strictly greater than r). --pen d is the pen-arm length measured in the same tooth-count units as the rotor: d < r gives smooth curtate lobes, d = r gives a hypocycloid with cusps, d > r gives prolate loops. --radius is the desired max radial extent of the finished drawing in mm, centred on (--x0, --y0). The curve closes exactly after 2π · r / gcd(R, r) of the rolling parameter.

The output uses G02 / G03 arcs with incremental I/J offsets — each arc is fitted adaptively to the true hypotrochoid, with maximum deviation bounded by --chord-tol (default 0.05 mm).

Then load on the machine: rollingmill --file /tmp/spiral.gcode.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

rollingmill-0.1.0.tar.gz (217.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

rollingmill-0.1.0-py3-none-any.whl (63.1 kB view details)

Uploaded Python 3

File details

Details for the file rollingmill-0.1.0.tar.gz.

File metadata

  • Download URL: rollingmill-0.1.0.tar.gz
  • Upload date:
  • Size: 217.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for rollingmill-0.1.0.tar.gz
Algorithm Hash digest
SHA256 2cc7dc4be53029a692a467b29ca3693c22abdd7b28a7602cf28abc0ebac5d528
MD5 b1b33af61ce1005bd903bcc9804974fe
BLAKE2b-256 e4722579360b47a6165fc4c7154ca5162be651adb9cb0000e75efd76a9c3d03e

See more details on using hashes here.

Provenance

The following attestation bundles were made for rollingmill-0.1.0.tar.gz:

Publisher: publish.yml on TeaEngineering/rollingmill

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file rollingmill-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: rollingmill-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 63.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for rollingmill-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 f25105c09b3f47bfcd92a67dfdd43f52388a1d5786219985b29318a2c1d6a4dd
MD5 e4da13b988ab2aaf38f30d49e15004cd
BLAKE2b-256 a352d12672916534916ffa39806a43e7738b867a042fce91c209f3c4645f9fc5

See more details on using hashes here.

Provenance

The following attestation bundles were made for rollingmill-0.1.0-py3-none-any.whl:

Publisher: publish.yml on TeaEngineering/rollingmill

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page