Files
2026-09-06 22:51:29 +02:00

302 lines
17 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Tutorial: p5-wallplotter
Dieses Tutorial erklärt, wie du das Repository lädst, den Beispiel-Sketch in **VS Code** lokal startest, den Wandplotter per USB verbindest und was Marlin mit G-code eigentlich macht.
**Kurzüberblick:** Der Browser zeichnet mit p5.js. Die Library WallPlotter.js wandelt Linien in G-code um und schickt ihn über **Web Serial** an die Steuerung. Dort läuft **Marlin** mit Polargraph-Kinematik: Kartesische Koordinaten (X/Y in Millimetern) werden in zwei Riemenlängen übersetzt, die die Motoren auf- und abwickeln.
Voraussetzungen:
- **Chrome** (Web Serial; nicht Firefox oder Safari)
- **VS Code** (Editor für den Workshop)
- Python 3
- USB-Kabel zum Plotter
- Plotter mit Stromversorgung (Steuerung + Motoren)
## 1.1 Repository herunterladen
Das Projekt liegt hier:
[https://git.collectivemedia.space/martin/p5-wallplotter](https://git.collectivemedia.space/martin/p5-wallplotter)
Auf der Projektseite **Code → Download ZIP** (oder direkt [archive/main.zip](https://git.collectivemedia.space/martin/p5-wallplotter/archive/main.zip)). Archiv entpacken. Den Ordner *p5-wallplotter* an einem sinnvollen Ort ablegen. Wir arbeiten innerhalb von diesem Ordner weiter.
### Was im Ordner liegt
- *lib/WallPlotter.js* — p5-Library: Serial, G-code, Preview, Tasten
- *lib/README.md* — Kurzüberblick + Beispiel
- *lib/doc.md* — API-Referenz
- *examples/zickzack/* — Einstiegsbeispiel
- *examples/rechteck/* — Rechteck zeichnen
- *hardware.md* — Motoren, Board, Geometrie
- *gcode.md* — G-code in diesem Setup
- *plotter.svg* — Geräte und Signalweg
- *tutorial.md* — diese Anleitung
## 1.2 Umgebung starten
Ziel: den Ordner in **VS Code** öffnen, dort den lokalen HTTP-Server starten, danach den Sketch in **Chrome** öffnen. Chrome bringt **Web Serial** mit — darüber redet der Browser mit dem Plotter über USB. Firefox und Safari können das nicht.
### Server in VS Code
1. VS Code: *Datei → Ordner öffnen* → Ordner *p5-wallplotter* wählen.
2. Terminal in der IDE öffnen: *Ansicht → Terminal*. Das Terminal startet **im Projektordner**.
3. Server im VS-Code-Terminal starten:
Linux und macOS:
```
python3 -m http.server 8080
```
Windows (Python von [python.org](https://www.python.org/downloads/), beim Setup **Add python.exe to PATH**):
```
py -m http.server 8080
```
Falls *py* unbekannt ist: *python -m http.server 8080*.
4. Die Seite in Chrome öffnen: [http://localhost:8080/examples/zickzack/](http://localhost:8080/examples/zickzack/)
Server kann mit *Ctrl+C* im VS-Code-Terminal beendet werden.
### USB je nach System
**macOS.** Der Port heisst typischerweise */dev/cu.usbmodem…*. macOS hält einen Serial-Port oft fest, wenn der Tab nicht sauber schliesst. Seite neu laden oder den Tab schliessen, bevor du erneut verbindest — die Library gibt den Port beim Schliessen frei. Falls *python3* fehlt: *xcode-select --install* oder Python über Homebrew.
**Linux.** Für den USB-Port braucht dein Benutzer die Serial-Gruppe. Nach der Änderung einmal ab- und anmelden.
**Windows.** Das Board erscheint im Geräte-Manager unter **Anschlüsse (COM & LPT)** als virtueller COM-Port. Web Serial zeigt denselben Port im Verbindungsdialog. Extra-Treiber sind bei der SKR Mini E3 V3 meist nicht nötig; wenn der Port fehlt, USB-Kabel wechseln (manche Kabel sind nur Ladekabel) und den STM32 Virtual COM Port / WinUSB-Pfad prüfen.
### Browser-Check
- **Chrome**, aktuelle Version (Web Serial)
- *chrome://flags* nicht nötig; Web Serial ist standardmässig an
- Beim ersten Verbinden erscheint ein Port-Picker — das ist gewollt (Browser-Sicherheitsmodell)
## 2.1 Eigenen Sketch schreiben
Unter *examples/* liegen die Vorlagen (siehe Abschnitt 1): *zickzack/* und *rechteck/*. Lege einen Ordner *sketches/* an (neben *examples/*). Dupliziere ein Beispiel **hinein** und benenne es um, zum Beispiel *sketches/mein-sketch/*
```
p5-wallplotter/
├── examples/ Vorlagen, nicht ändern
│ ├── zickzack/
│ └── rechteck/
└── sketches/ deine Sketches
└── mein-sketch/
├── index.html
└── sketch.js hier drawPlot anpassen
```
Dann öffne darin *sketch.js*. Den Rest (HTML, Buttons, Verbinden) kannst du lassen. Ändere die Inhalte in der Funktion *drawPlot*: dort steht, was gezeichnet wird.
Chrome, gleicher Server: [http://localhost:8080/sketches/mein-sketch/](http://localhost:8080/sketches/mein-sketch/) (Ordnername in der URL anpassen). Wie du die Vorschau startest und nach Änderungen neu lädst: Abschnitt 3.
### Was *sketch.js* macht
*setup* läuft einmal beim Start:
- *createCanvas* — Zeichenfläche im Browser, so gross wie das Fenster
- *parent('sketch-host')* — Canvas in die HTML-Seite einhängen
- *new WallPlotter({ … })* — Verbindung zum Plotter. *penUpGcode* / *penDownGcode* sind die Servo-Winkel für Stift hoch und runter
- *setSpeed(3000, 1500)* — Tempo in mm/min: zuerst leer fahren (Travel), dann zeichnen (Draw)
- *enableKeyInputs* — Tastatur: C, H, Pfeile, …
- *enablePlotButtons* — Buttons Connect, Test, Plot, Bounding box, Abort
*plot* und *test* rufen dieselbe Zeichnung auf. *false* = G-code an den Plotter, *true* = nur Vorschau im Browser.
### Die Zeichnung: *drawPlot*
**Koordinatensystem.** In p5 liegt *(0, 0)* sonst oben links, und *y* wächst nach **unten**. Hier ist es anders: Ursprung ist die **Blattmitte** (Home, *x = 0*, *y = 0*), Werte in **Millimetern**. *y* nach **oben** ist positiv, *x* nach rechts ebenfalls.
```
+y (oben)
|
|
-x ------0------ +x
|
|
-y (unten)
```
```
async function drawPlot(testOnly) {
const s = 200; // halbe Seitenlänge: 200 mm → Quadrat 400 × 400 mm
wp.startPath(); // Queue leeren, neu beginnen
wp.move(-s, -s); // Stift hoch, zur unteren linken Ecke (−200, −200)
wp.draw(s, -s); // Stift runter, nach rechts unten (200, −200)
wp.draw(s, s); // nach rechts oben (200, 200)
wp.draw(-s, s); // nach links oben (−200, 200)
wp.draw(-s, -s); // zurück zur ersten Ecke, Rechteck zu
wp.move(0, 0); // Stift hoch, zurück zur Blattmitte
await wp.runPath(testOnly); // Queue abarbeiten: Test oder Plot
}
```
*move* und *draw* fahren noch nicht. Sie hängen nur Punkte an die Queue (Array). *runPath* arbeitet sie der Reihe nach ab.
- *wp.move(x, y)* — Stift oben, hinfahren, keine Linie
- *wp.draw(x, y)* — Stift unten, Linie vom letzten Punkt hierhin
- *wp.wait(ms)* — Pause
- *wp.startPath()* — Queue leeren
- *wp.runPath(true)* — Vorschau (Test)
- *wp.runPath(false)* — wirklich plotten
Mehr Befehle: [lib/doc.md](https://git.collectivemedia.space/martin/p5-wallplotter/src/branch/main/lib/doc.md).
## 3. Testen
Der Plotter bleibt aus. **Test** zeigt die Zeichnung nur im Browser — kein G-code, keine Motoren.
1. Sketch in Chrome öffnen, z. B. [http://localhost:8080/sketches/mein-sketch/](http://localhost:8080/sketches/mein-sketch/) (oder *examples/zickzack/*).
2. Button **Test** oder Taste **T**. Die Gondel-Linie läuft als Vorschau über den Bildschirm.
3. Nochmals **Test** oder **T** zeichnet die Vorschau neu (kein Abort während des Tests).
Nach jeder Änderung in *sketch.js*: in VS Code speichern, dann in Chrome **neu laden**, sonst siehst du die alte Version (Cache).
- Hart neu laden: *Ctrl+Shift+R* (Windows/Linux) bzw. *Cmd+Shift+R* (macOS).
- Oder die Entwicklertools öffnen (*F12* bzw. *Cmd+Option+I*), oben **Netzwerk**, Häkchen **Cache deaktivieren**. Die Tools müssen **offen bleiben**. Dann reicht ein normales Neuladen (*F5* / *Cmd+R*).
Danach wieder **Test** oder **T** — jetzt gilt der geänderte Sketch.
## 4. Plotten
## 4.1 Plotter anschliessen
### Hardware-Reihenfolge
1. **Strom** an die Steuerung (SKR Mini E3 V3, typisch 24 V). Motoren brauchen die Versorgungsspannung; USB allein reicht nicht zum Fahren.
2. **USB** von der Steuerung zum Rechner (Datenkabel).
3. Gondel hängt an beiden Riemen, Stift sitzt im Halter, Papier/Wand ist frei.
4. Sketch im Browser öffnen (localhost, siehe oben).
5. **Connect** klicken oder Taste **C**.
6. Im Dialog den Serial-Port der Steuerung wählen.
## 4.2 Home setzen (wichtig)
Marlin kennt nach dem Einschalten **keine** absolute Wand-Position. Du sagst ihm, wo „jetzt“ der Ursprung (Blattmitte = Koordinate 0/0) ist. Die Pfeiltasten funktionieren erst nach dem ersten Home:
1. Einschalten oder nach neuer Verbindung
2. Taste **H** — Home an der **aktuellen** Gondelposition.
3. Mit den Pfeiltasten zur **Mitte des Blattes** fahren.
4. Nochmals **H** — das setzt den Ursprung auf die Blattmitte.
Ohne Home bleibt Plot gesperrt.
### Not-Aus
Diese Firmware hat keinen *EMERGENCY_PARSER*. Ein Stopp im Browser bricht nur das *weitere Senden* ab; die bereits laufende *G1*-Fahrt läuft weiter. Für einen harten Stopp: **Strom trennen**.
## 4.3 Bedienung
### Tasten, Buttons, HUD
Shortcuts:
- **C** — Verbinden / trennen (Port-Dialog)
- **H** — Hier ist Home (*G92 X0 Y0*): zuerst an der Gondel, nach dem Joggen nochmals in der Blattmitte
- **T** — Test (Vorschau). Nochmals **T** zeichnet neu
- **B** — Bounding box: Gondel fährt Stift oben um die Ausdehnung der Zeichnung
- **A** — Abort: während eines Plots (laufendes *G1* fährt zu Ende), oder nach einem Reload den gespeicherten Plot verwerfen
- **P** — Stift umschalten
- **0** — Nach (0, 0) fahren (Stift oben)
- **← → ↑ ↓** — Joggen, Stift oben
- **Shift + Pfeile** — Joggen, Stift unten
- **+** / **−** — Schrittweite 1–100 mm
- **S** — Plot pausieren / fortsetzen
Nach **Test** erscheint **Bounding box**. **Plot** nur wenn verbunden. **Plot** schickt genau diese Vorschau an den Plotter — die Zeichnung wird nicht neu gewürfelt. **Bounding box** fährt Stift oben um das Rechteck der Zeichnung, damit du siehst, ob alles aufs Blatt passt. Während eines Plots wird **Plot** zu **Pause** / **Resume**, und **Abort** erscheint. Nach einem Reload mit gespeichertem Plot bleibt **Abort** sichtbar, falls du einen anderen Sketch geladen hast und den alten Pfad nicht fortsetzen willst. **Test** bleibt während des Tests **Test** (nochmals drücken = neu zeichnen).
Das HUD (unten und als Overlay) zeigt Verbindung, Home, Position, Stift, Serial-Log.
## 5. Polargraph und Marlin
### Der Plotter und seine Teile
Der Wandplotter ist ein **Polargraph**: eine Gondel hängt an zwei Riemen, die oben links und rechts über Motoren und Umlenkrollen laufen. Es gibt keine X/Y-Schienen. Position entsteht allein aus den beiden Riemenlängen.
Baugruppen, Anschlüsse und Geometrie: [hardware.md](https://git.collectivemedia.space/martin/p5-wallplotter/src/branch/main/hardware.md).
### Was Marlin mit G-code macht
**Marlin** ist die Firmware auf dem Controller: ein Programm, das dauernd auf der Platine läuft. Der Name klingt wie *Merlin* der Zauberer — gemeint ist aber der Speerfisch, und die Software für 3D-Drucker (hier mit Polargraph-Kinematik): [marlinfw.org](https://marlinfw.org/). Die Platine heisst **SKR** (BigTreeTech SKR Mini E3 V3): die Steuerkarte am Plotter, mit USB, Motorbuchsen und 24-V-Netzteil. Marlin nimmt G-code entgegen, rechnet ihn in Motorbewegungen um und gibt *ok* zurück. Ohne Marlin sind USB und Motoren nur Hardware — niemand versteht die Zeichenbefehle.
### G-code in einem Satz
G-code ist die Kommandosprache von CNC- und 3D-Druck-Steuerungen: eine Textzeile, ein Befehl. Der Host (hier der Browser) schreibt Zeilen auf die serielle Schnittstelle. Marlin liest sie, plant Bewegung oder I/O, und antwortet mit *ok*, wenn der Befehl angenommen ist.
Beispiel einer Fahrt mit Stift unten:
```
M280 P0 S30 ; Servo 0 auf 30° → Stift aufs Papier
G1 X120 Y-40 F2500 ; Gerade zu (120, −40) mm mit 2500 mm/min
M400 ; warten, bis die Bewegung wirklich fertig ist
```
### Der Weg einer Linie
*wp.draw* legt die Linie nur in eine Queue (ein Array von Punkten). Der Plotter hat noch nichts gehört.
**Plot** (*runPath(false)*) nimmt die Queue Eintrag für Eintrag und schickt sie per USB an Marlin. Marlin liest das Ziel in Millimetern, rechnet daraus zwei Riemenlängen, bewegt die Motoren und antwortet mit *ok*: Befehl angekommen, nächster Eintrag bitte. Die Library wartet auf *ok* und auf *M400* (Gondel steht wirklich still), erst dann kommt die nächste Linie. Sonst würde der Browser schon weiterreden, während die Gondel noch unterwegs ist.
**Test** (*runPath(true)*): gleiche Queue, nur Animation im Browser. Marlin bekommt keinen G-code. Gut zum Üben, bevor der Stift die Wand kennenlernt.
### Inverse Kinematik (Polargraph)
Ein kartesischer Drucker fährt Schlitten auf Schienen. Der Polargraph fährt **Riemenlängen**. Jeder Riemen ist die Hypotenuse vom Umlenkpunkt zur Gondel — Pythagoras, in Marlin *HYPOT*:
```
L_links = sqrt( (X − X_links)^2 + (Y − Y_rollen)^2 )
L_rechts = sqrt( (X_rechts − X)^2 + (Y − Y_rollen)^2 )
```
Auf dieser Maschine sitzen die Rollen bei *X_links = −830*, *X_rechts = 830*, *Y_rollen = 800* (Millimeter, Ursprung Blattmitte):
```
L_links = sqrt( (X + 830)^2 + (Y − 800)^2 )
L_rechts = sqrt( (830 − X)^2 + (Y − 800)^2 )
```
Beispiel Home *(0, 0)*: beide Riemen *sqrt(830² + 800²) ≈ 1153 mm*. Weiter unten oder zur Seite wird ein Riemen länger, der andere kürzer.
In der Firmware ist der X-Stepper die linke Länge, der Y-Stepper die rechte. Eine waagerechte Linie auf der Wand ist für die Motoren **keine** gleichmässige Rotation — beide Längen ändern sich gekoppelt. Marlin zerlegt die kartesische Gerade intern in kurze Segmente (*DEFAULT_SEGMENTS_PER_SECOND*), damit die Kurve der Riemenlängen der Geraden auf der Wand folgt.
Deshalb muss Home zur realen Geometrie passen. Falscher Ursprung (z. B. Ursprung zu weit unter den Rollen) erzeugt den typischen **Bogen nach oben** bzw. eine konische Zeichnung: Marlin glaubt, die Gondel sei woanders, als sie hängt.
Befehlsliste: [gcode.md](https://git.collectivemedia.space/martin/p5-wallplotter/src/branch/main/gcode.md).
### Was Marlin nicht ist
Marlin ist keine Zeichen-App. Es weiss nichts von p5 oder deinem Sketch. Es bekommt nur Koordinaten und Servo-Winkel. Pfadplanung, Stiftlogik und die Vorschau liegen in *WallPlotter.js*. Die Firmware ist der Bewegungscontroller: parsen, in Riemenlängen umrechnen, Schritte erzeugen, *ok* sagen.
## 6. Fehlerbehebung
- **Kein Port-Dialog, oder „Serial not supported“** — **Chrome**, nicht Firefox oder Safari. Seite über *http://localhost:…* öffnen, nicht als Datei.
- **Port erscheint nicht** — Strom der Steuerung an? Daten-USB-Kabel? Linux: Gruppe *dialout* oder *uucp*, neu einloggen; im Terminal nach *ttyACM* oder *ttyUSB* schauen. Windows: Geräte-Manager → COM-Port. macOS: Tab schliessen und neu öffnen (Port oft blockiert).
- **Connect, aber keine Bewegung** — Netzteil an der SKR einstecken (typisch 24 V). USB allein speist die Motoren nicht. Dann **H** drücken. Linker Motor an Buchse **X**, rechter an **Y**.
- **„Home not set“** — Zuerst **H**, dann zur Blattmitte joggen, nochmals **H**.
- **Stift bleibt oben oder kratzt** — *penUpGcode* / *penDownGcode* an den Servo anpassen (*S*-Winkel). Mit **P** testen.
- **Zeichnung bogenförmig / konisch** — Home falsch: Gondel 80 cm unter den Rollen, dann *G92 X0 Y0*. Rollenabstand 1660 mm.
- **Motoren heiss, Schritte verloren** — *M906 X1000 Y1000*. Riemen nicht zu straff. Tempo senken.
- **Plot hängt bei „waiting for Marlin ok“** — USB wackelt, Board reset, oder lange *G1* ohne *ok*. **Resume** nach Timeout; sonst USB neu stecken und Home neu setzen.
- **Stop im Browser, Gondel fährt weiter** — Normal: laufendes *G1* wird nicht abgebrochen. Strom weg für Not-Aus.
- **macOS verbindet nur einmal** — Seite komplett schliessen, Port freigeben, erneut **C**.
- **Beispiel sieht alt aus nach einem Update** — Browser-Cache: hart neu laden (*Ctrl+Shift+R*) oder *?v=* an *WallPlotter.js* in der HTML erhöhen.
Serial-Log im HUD lesen: Marlin-Fehler stehen dort als Text, nicht als Browser-Alert.
## 7. Mini-Ablauf zum Merken
1. ZIP herunterladen, in VS Code den Ordner *p5-wallplotter* öffnen.
2. Terminal in VS Code öffnen, *python3 -m http.server 8080* (Windows: *py -m http.server 8080*).
3. Chrome: [http://localhost:8080/examples/zickzack/](http://localhost:8080/examples/zickzack/).
4. Eigenen Ordner unter *sketches/* anlegen, *drawPlot* anpassen.
5. **Test** oder **T**. Nach Änderungen speichern, hart neu laden (*Ctrl+Shift+R*), nochmals **T**.
6. Plotter mit Strom und USB verbinden.
7. **C** → Port wählen.
8. **H** (aktuelle Position), zur Blattmitte joggen, nochmals **H**.
9. **Plot**.
API-Referenz: [lib/doc.md](https://git.collectivemedia.space/martin/p5-wallplotter/src/branch/main/lib/doc.md). G-code: [gcode.md](https://git.collectivemedia.space/martin/p5-wallplotter/src/branch/main/gcode.md).