This fork adapts the original OctoPrint/Octolapse workflow to a custom Marlin-based printer that is connected directly over USB serial and monitored with two cameras.
The new workflow is:
runopens two cameras and captures a background frame for each one.- It listens to the Marlin serial console for layer markers such as
M118 LAYER:12. - On every trigger, it captures frames from both cameras, computes the original NRMSE-based metrics per camera, and optionally runs spaghetti detection.
- If either camera reports a configured failure condition,
printcontrol.pysends Marlin pause G-code over serial.
If layer messages are not available yet, run can also fall back to timed captures.
SERIAL_PORTto the printer port, for exampleCOM5PAUSE_COMMANDSto the pause/stop G-code that matches the printer workflowCAMERASso both camera sources, crop areas, rotation, and mirroring are correctTRIGGER_MODEtolayer,timer, orhybrid
For best results, make your slicer emit a serial message at every layer change (didn't work well without this). A simple pattern is:
M118 LAYER:[layer_num]That lets run capture images at repeatable layer boundaries instead of arbitrary time intervals.
Create a Python environment and install the runtime dependencies:
pip install numpy scipy scikit-image opencv-python pyserial matplotlibFor spaghetti detection, also download the Darknet weights file into ml_api/model/model.weights using the URL in ml_api/model/model.weights.url.
The monitor needs to be started before beginning the print so capture index 000000.jpg becomes the empty-bed background reference:
python run --job-name test_partUseful options:
python run --trigger-mode layer
python run --trigger-mode timer --capture-interval 10
python run --background-only --job-name calibrationCaptured sessions are written under captures/<job-name>/ with this layout:
captures/
test_part/
cam0_top/
000000.jpg
000001.jpg
output.log
cam1_side/
000000.jpg
000001.jpg
output.log
combined/
000000.jpg
000001.jpg
events.log
The score rules run per camera:
- Detachment:
score > 1.0anddeviance > 1.0 - Breakage:
score_diff > 0.2anddeviance_diff > 0.2 - Filament runout/clog:
score < 0.2anddeviance < 0.2 - Spaghetti: Darknet model reports one or more spaghetti detections
The confirmation mode is controlled by FAILURE_CONFIRMATION_MODE in api_keys.py:
any: pause when one camera confirms a failureall: pause only when both cameras confirm a failure
get_score.pycalculates metrics for one saved framedata_visualisation.pyplots one cameraoutput.loggen_video.pybuilds a preview video from a camera or combined capture folder
- Some Arduino-style boards reset when a serial connection opens.
DISABLE_DTR_ON_CONNECTis included to reduce that risk, but behaviour still depends on your USB interface and firmware board. M25is mainly for SD-card prints. If your printer is driven differently, adjustPAUSE_COMMANDSto match your Marlin setup.- For the most reliable image comparison, park the toolhead out of frame at each trigger point or choose camera angles where the nozzle does not hide the part.