Files
p5-wallplotter/tutorial.md
T
2026-09-05 13:39:34 +02:00

319 lines
13 KiB
Markdown
Raw 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 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** oder **Edge** (Web Serial gibt es nicht in Firefox oder Safari)
- Python 3
- USB-Kabel zum Plotter
- Plotter mit Stromversorgung (Steuerung + Motoren)
Web Serial funktioniert **nicht** über `file://`. Die Seite muss von `http://localhost` oder über HTTPS kommen.
---
## 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 und in den Ordner `p5-wallplotter` wechseln.
### Was im Ordner liegt
```
p5-wallplotter/
├── lib/
│ ├── WallPlotter.js # p5-Library: Serial, G-code, Preview, Tasten
│ ├── README.md # Kurzüberblick + Beispiel
│ └── doc.md # API-Referenz
├── examples/
│ ├── zickzack/ # Einstiegsbeispiel
│ └── rechteck/ # Rechteck zeichnen
├── hardware.md # Motoren, Board, Geometrie
├── gcode.md # G-code in diesem Setup
└── tutorial.md # diese Anleitung
```
Es gibt kein `npm install`. Der Sketch lädt p5.js vom CDN; der Rest sind statische Dateien.
---
## 2. Umgebung starten
Ziel: einen lokalen HTTP-Server im Projektordner, danach den Sketch in Chrome/Edge öffnen.
### Linux
Im Projektordner:
```bash
cd p5-wallplotter
python3 -m http.server 8080
```
Browser: [http://localhost:8080/examples/zickzack/](http://localhost:8080/examples/zickzack/)
Server mit `Ctrl+C` beenden.
Für den USB-Port braucht dein Benutzer die Serial-Gruppe. Nach der Änderung einmal ab- und anmelden:
```bash
# Debian / Ubuntu
sudo usermod -aG dialout "$USER"
# Arch / CachyOS
sudo usermod -aG uucp "$USER"
```
Prüfen, ob das Board erscheint (SKR Mini E3 V3 als USB-CDC):
```bash
ls /dev/ttyACM* /dev/ttyUSB*
```
### Windows
1. Python von [python.org](https://www.python.org/downloads/) installieren. Beim Setup **Add python.exe to PATH** aktivieren.
2. PowerShell oder Eingabeaufforderung im Projektordner:
```powershell
cd p5-wallplotter
py -m http.server 8080
```
Falls `py` unbekannt ist: `python -m http.server 8080`.
3. Chrome oder Edge: [http://localhost:8080/examples/zickzack/](http://localhost:8080/examples/zickzack/)
Das Board erscheint in der Geräte-Manager-Ansicht 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.
### macOS
Im Terminal:
```bash
cd p5-wallplotter
python3 -m http.server 8080
```
**Chrome** oder **Edge** öffnen (nicht Safari): [http://localhost:8080/examples/zickzack/](http://localhost:8080/examples/zickzack/)
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.
### Browser-Check
- Chrome oder Edge, aktuelle Version
- `chrome://flags` nicht nötig; Web Serial ist standardmässig an
- Beim ersten Verbinden erscheint ein Port-Picker — das ist gewollt (Browser-Sicherheitsmodell)
---
## 3. 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.
### Home setzen (wichtig)
Marlin kennt nach dem Einschalten **keine** absolute Wand-Position. Du sagst ihm, wo „jetzt“ der Ursprung ist. Die Pfeiltasten funktionieren erst nach dem ersten Home:
1. Taste **H** — Home an der **aktuellen** Gondelposition (`G92 X0 Y0`).
2. Mit den Pfeiltasten (Stift oben) zur **Mitte des Blattes** fahren.
3. 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. 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](hardware.md).
---
## 5. Was Marlin mit G-code macht
### 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 parst sie, plant Bewegung oder I/O, und antwortet mit `ok`, wenn der Befehl angenommen ist.
Beispiel einer Fahrt mit Stift unten:
```gcode
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
```
p5 sketch
wp.draw(x, y) → nur in eine Warteschlange legen
wp.runPath(false) → nacheinander senden
│
▼
USB Serial, 115200 Baud
│
▼
Marlin auf der SKR
1. Zeile lesen, parsen
2. G1: Ziel in mm merken
3. inverse Kinematik: (X, Y) → (linke Riemenlänge, rechte Riemenlänge)
4. Planner: Beschleunigung, Segmentierung
5. Stepper-ISR: X- und Y-Treiber takten
6. "ok" zurück an den Browser
│
▼
WallPlotter wartet auf ok, schickt M400, erst dann den nächsten Punkt
```
**Test** (`runPath(true)`) bleibt im Browser: gleiche Pfadliste, nur Animation. Es geht kein G-code raus.
### Inverse Kinematik (Polargraph)
Ein kartesischer Drucker fährt Schlitten auf Schienen. Der Polargraph fährt **Riemenlängen**. Marlin rechnet für jedes Ziel:
```
linke Länge = hypot( X − linke_Rolle , Y − Rollenlinie )
rechte Länge = hypot( rechte_Rolle − X , Y − Rollenlinie )
```
In der Firmware entspricht das `HYPOT` in `inverse_kinematics`: X-Stepper = linke Länge, Y-Stepper = rechte Länge. Eine waagerechte Linie auf der Wand ist für die Motoren **keine** gleichmässige Rotation — beide Motoren ändern die Länge gekoppelt. Marlin zerlegt die kartesische Gerade intern in kurze Segmente (`DEFAULT_SEGMENTS_PER_SECOND`), damit die Kurve der Riemelängen der Geraden auf der Wand folgt.
Deshalb muss Home zur realen Geometrie passen. Falsches `G92` (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](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. Eigenen Sketch schreiben
Kopiere den Ordner `examples/zickzack/` und öffne darin `sketch.js`. Den Rest (HTML, Buttons, Verbinden) kannst du lassen. Du änderst nur `drawPlot`: dort steht, was gezeichnet wird.
Koordinaten sind **Millimeter**, Ursprung = Home, **Y nach oben**.
Fertiges Rechteck: [examples/rechteck/](examples/rechteck/). Im Browser `http://localhost:8080/examples/rechteck/` öffnen. Nach dem Speichern die Seite neu laden (`F5`).
### 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, Plot, Test, Abort
`draw()` läuft dauernd (p5-Schleife): Hintergrund und HUD (`showInfos`).
`plot()` und `test()` rufen dieselbe Zeichnung auf. `false` = G-code an den Plotter, `true` = nur Vorschau im Browser.
### Die Zeichnung: `drawPlot`
```javascript
async function drawPlot(testOnly) {
const s = 200; // halbe Seitenlänge: 200 mm → Quadrat 400 × 400 mm
wp.startPath(); // alte Linie löschen, neue Liste 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); // Liste abarbeiten: Test oder Plot
}
```
`move` und `draw` fahren noch nicht. Sie merken sich nur Punkte. `runPath` arbeitet die Liste der Reihe nach ab.
| Aufruf | Stift | Wohin |
|--------|--------|--------|
| `wp.move(x, y)` | oben | hinfahren, keine Linie |
| `wp.draw(x, y)` | unten | Linie vom letzten Punkt hierhin |
| `wp.wait(ms)` | — | Pause |
| `wp.startPath()` | — | Liste leeren |
| `wp.runPath(true)` | — | Vorschau (Test) |
| `wp.runPath(false)` | — | wirklich plotten |
Mehr Befehle: [lib/doc.md](lib/doc.md).
---
## 7. Tasten, Buttons, HUD
| Taste | Aktion |
|-------|--------|
| **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) |
| **A** | Abort: Test auf Start zurück |
| **P** | Stift umschalten |
| **0** | Nach `(0, 0)` fahren (Pen-up) |
| **← → ↑ ↓** | Joggen, Stift oben |
| **Shift + Pfeile** | Joggen, Stift unten |
| **+** / **-** | Schrittweite 1–100 mm |
| **S** | Plot stoppen / pausieren |
Buttons: **Connect**, **Plot** (wird Pause / Resume), **Test** (wird Stop), **Abort**.
Das HUD (unten und als Overlay) zeigt Verbindung, Home, Position, Stift, Serial-Log. Das Log rechts unten kannst du markieren — nützlich, wenn Marlin nicht mit `ok` antwortet.
---
## 8. Fehlerbehebung
| Symptom | Was prüfen |
|---------|------------|
| Kein Port-Dialog, oder „Serial not supported“ | Chrome oder Edge, nicht Firefox/Safari. Seite über `http://localhost:…`, nicht als Datei öffnen. |
| Port erscheint nicht | Strom der Steuerung an? Daten-USB-Kabel? Linux: Gruppe `dialout` oder `uucp`, neu einloggen. `ls /dev/ttyACM*`. 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.
---
## 9. Mini-Ablauf zum Merken
1. ZIP herunterladen und entpacken.
2. `python3 -m http.server 8080` (Windows: `py -m http.server 8080`).
3. Chrome/Edge: `http://localhost:8080/examples/zickzack/`.
4. Plotter mit Strom und USB verbinden.
5. **C** → Port wählen.
6. **H** (aktuelle Position), zur Blattmitte joggen, nochmals **H**.
7. **Test**, dann **Plot**.
API-Referenz: [lib/doc.md](lib/doc.md). G-code: [gcode.md](gcode.md).