# WallPlotter API Public API for `WallPlotter.js`. Quick start: [README.md](README.md). --- ## `new WallPlotter(options?)` All options are optional. | Option | Default | What it is | |--------|---------|------------| | `baudRate` | `115200` | Serial baud (must match Marlin) | | `stepSize` | `10` | Keyboard jog step, mm | | `feedRateTravel` | `1500` | Pen-up speed, **mm/min** (G-code `F`) | | `feedRateDraw` | `300` | Pen-down speed, **mm/min** | | `penUpGcode` | `M280 P0 S90` | Command to lift pen | | `penDownGcode` | `M280 P0 S50` | Command to lower pen | | `penUpDelayMs` | `150` | Pause after pen up, ms | | `penDownDelayMs` | `50` | Pause after pen down, ms | | `machineXMin` / `machineXMax` | `-830` / `830` | Overlay X extents, mm (idler spacing 1660) | | `machineYMin` / `machineYMax` | `-1200` / `800` | Overlay Y; idlers at Y=800 (80 cm above work centre) | | `jogIntervalMs` | `150` | Repeat delay while holding arrows, ms | | `maxLogLines` | `40` | Serial lines in the selectable log (bottom-right) | | `previewMinDelayMs` | `30` | Floor for preview segment wait, ms | | `previewFrameMs` | `16` | Preview animation frame time, ms | | `timingMultiplier` | `1` | Scale **Test** preview waits (`2` = twice as slow) | | `onLog(line)` | no-op | Extra callback for each log line | | `onStatusChange(status)` | no-op | `'connected'` or `'disconnected'` | --- ## Setup / UI ### `enableKeyInputs()` Keyboard controls. Call from `setup()`. No arguments. | Key | Action | |-----|--------| | `C` | Connect / disconnect | | `T` | Run Test (preview). Press again to redraw | | `B` | Travel the drawing bounding box, pen up | | `A` | Abort live Plot, or discard a restored plot after reload | | `S` | Pause / resume live Plot | | `H` | Set home here (`G92 X0 Y0`) — required before Plot | | `0` | Travel to `(0, 0)` | | `P` | Toggle pen | | `← → ↑ ↓` | Jog one step, pen up | | `Shift + arrows` | Jog one step, pen down | | `+` / `-` | Jog step size 1–100 mm | ### `enablePlotButtons(options?)` Adds Connect, Test, Plot, Bounding box, and Abort. Expects global `plot()` and `test()` in the sketch. **Connect** is shown only while disconnected (same as key **C**). With no sketch yet, only **Test** is shown. After Test, **Bounding box** appears. **Plot** appears once connected (and a preview exists). **Plot** sends the existing preview path (it does not call `plot()` again). While plotting, Plot becomes **Pause**, then **Resume**. **Abort** is shown during a live Plot, and after a reload if a plot can be resumed (so you can drop it after switching sketches). **Bounding box** (key **B**) is shown when a sketch is visible and nothing is plotting: the gondola travels the drawing extents with the pen up, without replacing the preview. | Option | Default | What it is | |--------|---------|------------| | `parentId` | `'wallplotter-controls'` | DOM id for the button row | | `connectLabel` | `'Connect'` | Connect button text | | `plotLabel` | `'Plot'` | Plot button text when idle | | `pauseLabel` | `'Pause'` | Plot button while a path is running | | `resumeLabel` | `'Resume'` | Plot button while paused | | `testLabel` | `'Test'` | Test button text | | `bboxLabel` | `'Bounding box'` | Travel drawing extents, pen up | | `abortLabel` | `'Abort'` | Stop sending a live Plot | ### `showInfos()` Draw HUD, path preview, bounds, and key help. Call every frame from `draw()`. Also runs held-arrow jogging when keys are enabled. --- ## Speed ### `setSpeed(travel, draw)` Feed rates in **mm/min**. Used as G-code `F` and for Test preview timing. Clamped to **1–10000**. - `travel` (number): pen-up / `move()` speed. Or `{ travel, draw }`. - `draw` (number, optional): pen-down / `draw()` speed. Omit to leave draw rate unchanged. Practical range about **100–10000**. Values above **10000** are clamped. Do not use `0`. ```javascript wp.setSpeed(6000, 2500); wp.setSpeed({ travel: 6000, draw: 2500 }); ``` ### `setTimingMultiplier(mult)` Scales **Test** preview waits only. Plot is paced by Marlin (`ok` + `M400`). - `mult` (number): `1` = match `setSpeed` estimate, `2` = twice as slow, `0.5` = twice as fast. Clamped to ≥ `0.1`. --- ## Path (buffered drawing) `move` / `draw` / `wait` / `speed` only **queue**. Nothing is sent until `runPath`. ### `startPath()` Clear the path buffer. Returns `this`. ### `move(x, y, pressure?)` Queue pen-up travel to `(x, y)` mm. Returns `this`. - `pressure` (number, optional): **0–100**. Mapped linearly onto the `S` values of `penUpGcode` (0) and `penDownGcode` (100). Default **0** (pen fully up). ### `draw(x, y, pressure?)` Queue pen-down stroke to `(x, y)` mm. Returns `this`. - `pressure` (number, optional): **0–100**, same mapping as `move`. Default **100** (pen fully down). Use values in between for lighter contact. ```javascript wp.startPath(); wp.move(-200, -200); wp.draw(200, -200, 40); // light wp.draw(200, 200, 100); // full down await wp.runPath(false); ``` ### `wait(ms)` Queue a pause. `ms` is milliseconds. On Plot, sends `G4 P`. Returns `this`. ### `speed(travel, drawRate)` Queue a mid-path speed change (mm/min, clamped 1–10000). Either argument may be omitted. Restored after `runPath`. Returns `this`. ### `runPath(testOnly)` / `runPath(commands, testOnly?)` Run the path. **async**. - `testOnly` (boolean): `true` = preview only, no serial. `false` = send G-code. Home must be set for Plot. - `commands` (array, optional): explicit list instead of the `startPath()` buffer. Plot: wait for Marlin `ok`, then `M400` (move finished). Test: animate using distance / `setSpeed` × `timingMultiplier`. ```javascript wp.startPath(); wp.move(-200, -200); wp.draw(200, -200); wp.wait(500); await wp.runPath(false); // plot await wp.runPath(true); // test ``` Sketch: `plot()` → `runPath(false)`, `test()` → `runPath(true)`. ### `estimatePathMs(commands?)` Returns estimated duration in **milliseconds** for the current path buffer, or for `commands` if given. Uses `setSpeed`, queued `speed()`, `wait()`, and `timingMultiplier`. The HUD shows elapsed / est / remain while plotting. ### `stopPath()` / `stopPlot()` `stopPath()` aborts the current `runPath` after the in-flight command gets its `ok` (it does not cancel that wait — that was dropping the next `ok`). `stopPlot()` first press is the same as **Pause**: finish the current stroke, then **Resume** continues. Second press stops the browser from sending more moves. The **in-flight** `G1` still runs — this firmware does not have `EMERGENCY_PARSER`, so `M410` cannot interrupt motion (and on a polargraph it desyncs belts). Unplug power for a hard stop. ### `pausePlot()` / `resumePlot()` / `abortToStart()` **Pause** waits for the current segment to finish (`M400`), then lifts the pen. **Resume** continues from there. **Abort** is shown during a live Plot, and after reload if a plot was saved to resume. Button or **A**: while plotting it stops sending further moves (the machine finishes the in-flight `G1`). For a restored plot it discards that saved path, so Plot will not continue a previous sketch. During Test, press **Test** again to redraw. --- ## Serial / machine All **async**. Coordinate moves on Plot require home (`H`) first. ### `connect()` Web Serial port picker, enable steppers (`M17`), pen up, query polargraph area (`M665` → machine overlay bounds), `M114`. Reload/close releases the port (needed on macOS). If only one previously allowed port exists, it is reused. ### `disconnect()` Close the serial port. ### `send(line, options?)` Write one G-code line and wait for Marlin `ok`. - `line` (string): command without newline, e.g. `'M114'`. - `options.allowWithoutHome` (boolean): allow `G0`/`G1` before home. Default `false`. - `options.waitOk` (boolean): wait for `ok`. Default `true`. - `options.timeoutMs` (number): `ok` timeout. Default **15000**. `M400` / `G4` use a longer timeout based on the move or dwell. After 1s with no `ok`, the log shows `waiting for Marlin ok` and the HUD says **Waiting for plotter…**. During a plot, a timeout **pauses** so **Resume** can continue; **S** / Stop does the same. ### `penUp(force?)` / `penDown(force?)` Send pen G-code and wait the pen delay. By default, no-op if already at that pressure. Pass `true` to always send (used by `P` and on connect) so you can test the configured angles. `penUp` is pressure **0**, `penDown` is pressure **100**. ### `setPressure(pressure)` Set servo pressure immediately (**0–100**). Same mapping as `move`/`draw`: **0** = `penUpGcode` `S`, **100** = `penDownGcode` `S`. Waits the pen delay. ### `screenToPlot(px, py, options?)` Convert canvas pixel coordinates to plot coordinates in mm. - `px`, `py` (number): screen/canvas pixel coordinates. - `options.clamp` (boolean, default `true`): clamp result to bounds. - `options.useDisplayBounds` (boolean, default `false`): use current display bounds (preview when disconnected) instead of machine bounds. ### `moveTo(x, y, pressure?)` Pen up (or optional pressure), travel to `(x, y)` mm immediately (not queued), then wait for motion completion (`M400`). Requires home. - `pressure` (number, optional): **0–100**. Default **0**. ### `drawTo(x, y, pressure?)` Pen down (or optional pressure), draw to `(x, y)` mm immediately, then wait for motion completion (`M400`). Requires home. - `pressure` (number, optional): **0–100**. Default **100**. ### `goToZero()` `moveTo(0, 0)`. ### `step(dx, dy, draw?)` Relative move in mm. - `dx`, `dy` (number): delta mm - `draw` (boolean, default `false`): `true` → `drawTo`, else `moveTo` ### `setHomeHere()` `G92 X0 Y0`. Sets local `x,y` to 0 and marks home as set. --- ## Fields (read) | Field | Meaning | |-------|---------| | `connected` | Serial open | | `homeSet` | Home was set with `H` / `setHomeHere()` | | `x`, `y` | Current position, mm | | `isPenDown` | Pen is below fully-up (pressure > 0) | | `penPressure` | Last servo pressure, **0–100** | | `isPlotting` | `runPath` in progress | | `isPaused` | `runPath` is paused | | `feedRateTravel` / `feedRateDraw` | Current speeds, mm/min | | `timingMultiplier` | Preview wait scale | | `stepSize` | Jog step, mm |