Skip to content

Hardware Reference

Peter Pak edited this page Jul 26, 2026 · 2 revisions

Hardware Reference

Facts about the Inova MK1 + SLS4All Compact firmware that were verified empirically (firmware audit, decompilation, build-40 telemetry) and are load-bearing for tooling decisions.

Two APIs, two ports

The printer exposes two parallel HTTP surfaces, both unauthenticated on this unit:

  • Port 5001 — our Inova API Plugin: live numeric telemetry (/state/stream WS), positions, runtime overrides.
  • Port 80 — the firmware's own API: images and rich status the plugin deliberately doesn't proxy.

Firmware port-80 endpoints

Endpoint Returns Notes
GET /api/status small JSON heartbeat online, isPrinting flags (~225 B)
GET /api/printingservice/status rich JSON heartbeat Phase, Progress, Remaining, JobName, CpuTemp, SurfaceTarget (~566 B). The plugin can't serve this — IPrintingService lives in AppCore.
GET /api/videocamera/image/{uuid} JPEG chamber camera; {uuid} is an opaque cache-buster. Native ~20–22 fps.
GET /api/videocamera/workingarea/{uuid} PNG print-bed projection overlay (calibration views)
GET /api/bedmatrix/image/{uuid} GIF IR thermal heatmap, ~6 Hz native, ~51 KB/frame
GET /api/plottedimage/{uuid} PNG live galvo plot of the laser path on the current layer
GET /api/plottedimage/{uuid}/{layerIndex} PNG historical per-layer plot
GET /api/slicingimage/{version}/{layerIndex} PNG pre-print sliced layer preview

Rule of thumb: images and rich status from :80; numeric telemetry from :5001.

Not exposed on either port: raw 1 kHz galvo positions (only the rasterized PNG + 10–100 Hz snapshots), raw thermal float matrix (only the rendered GIF), per-laser/heater PWM duty.

Recoater "passes" = staged powder delivery

Decompiled from the deployed (obfuscated) firmware: with PowderBedDivision = "Thickness", RecoatPasses = N means fractional powder staging, not N full recoats:

  • The powder piston feeds 1/N of the dose per pass (GetZ1Pos(pass) = (pass+1) · z1Thickness / N).
  • Mid passes run with the print bed dropped extra (MidRecoatThicknessFactorOverride = 2.0); only the final pass sweeps at true layer height and planes the surface.
  • Observed: pass i stops ~i/N across the bed, pauses ~1 s (recoater shake), continues.

This is why the MCP surface has two distinct mechanisms: recoater_passes_* (staged, firmware-native) and recoater_full_passes_* (plugin's FullRecoatLayerClient — genuine repeated full recoats). Never treat them as interchangeable.

Z-axis conventions (verified from build-40 telemetry)

  • Z1/Z2 positions are in micrometers (z1 ≈ 33928, z2 = 29600 mid-print).
  • Z1 decreases as powder feeds — piston rising = negative delta; z1 fell 42.5 mm → 33.8 mm over a print.
  • Per-layer feed dose ≈ LayerThickness × (PrintChamberArea 31109 / PowderChamberArea 39074) × VolumeFactor ≈ 105.6 µm observed; the per-layer Z1 dance is −(dose+700)/+700 pairs (700 µm = ZMoveDefault clearance).
  • Manual feed primitive: IMovementClient.MoveAux(Z1, MoveAuxItem(-dose, Relative: true)) — what the full-recoat powder feed uses. The firmware's powder-depth planner doesn't know about manual feeds, so the chamber runs down faster than it predicts.

Trust the data, not the labels

  • Profile names can lie — a "20mJ/mm" profile has been observed to contain 15. Always read the JSON field, never the name.
  • Profile thickness fields are micrometers, not mm: layerThickness 100, bedPreparationThickness 13000, printCapThickness 5000 (live-data confirmed 2026-07-18; the GUI mislabeled them mm for weeks and could never edit them).
  • One firmware PrintSession can span multiple recorder builds (restarts/false starts) — the registry maps them via builds.inova_session_id.
  • Overrides land on the next layer — verify there, not on the current one. Layer time ≫ agent latency, which is exactly why agentic control fits AM's timescale.

Clone this wiki locally