Prof. Dr. Sebastian Zug, Technische Universität Bergakademie Freiberg
Die interaktive Ansicht dieses Kurses ist unter folgendem Link verfügbar.
Der Quellcode der Materialien ist unter https://github.com/liaScript/ArduinoEinstieg/blob/master/Course_06.md zu finden.
{{0-1}} !?Beispielvideo
{{1-2}}
Ein Wall Plotter (auch V-Plotter oder Seilplotter genannt) ist ein Zeichenroboter, der an einer Wand montiert wird und mit zwei Seilen einen Stift über eine Fläche bewegt.
\begin{tikzpicture}[scale=0.8]
% Wand
\fill[gray!15] (0,0) rectangle (12,9);
\draw[thick] (0,0) rectangle (12,9);
\node at (6, 9.4) {\textbf{Wand}};
% Motoren
\fill[blue!60] (1,8) circle (0.4);
\fill[blue!60] (11,8) circle (0.4);
\node[above] at (1,8.5) {\textbf{Motor A}};
\node[above] at (11,8.5) {\textbf{Motor B}};
% Spulen andeuten
\draw[thick] (1,8) circle (0.25);
\draw[thick] (11,8) circle (0.25);
% Seile
\draw[red, thick] (1,8) -- (5.5,4);
\draw[red, thick] (11,8) -- (5.5,4);
% Stifthalter
\fill[orange!80] (5.5,4) circle (0.3);
\node[below=0.4] at (5.5,4) {\textbf{Stift}};
% Bemaßung
\draw[<->, blue, thick] (1,7.5) -- (5.5,3.7) node[midway, left=0.3] {$L_A$};
\draw[<->, blue, thick] (11,7.5) -- (5.5,3.7) node[midway, right=0.3] {$L_B$};
\draw[<->, green!60!black, thick] (1.5,8.0) -- (10.5,8.0) node[midway, above] {$d$ (Abstand der Motoren)};
% Gezeichneter Stern
\draw[thick, purple] (4,3) -- (7,3) -- (4.8,1.2) -- (5.5,4) -- (6.2,1.2) -- cycle;
\end{tikzpicture}Das System besteht aus wenigen Komponenten:
- Zwei Schrittmotoren (oben links und rechts an der Wand befestigt)
- Zwei Seile/Ketten, die von den Motoren zum Stifthalter führen
- Ein Stifthalter mit Gewicht, das die Seile unter Spannung hält
- Ein Servo zum Anheben und Absenken des Stifts
Durch gezieltes Aufwickeln und Abwickeln der beiden Seile kann der Stift an jede Position auf der Wand bewegt werden.
{{2-3}}
Wall Plotter sind ein hervorragendes Projekt, um Mechanik, Mathematik und Programmierung zu verbinden!
Welche Probleme sehen Sie bei der Umsetzung?
Mathematik hat nichts mit Rechnen zu tuen, sondern mit Abstraktion und Modellbildung. Um den Wall Plotter zu bauen, müssen wir dessen Funktionsprinzip technisch beschreiben.
Wir definieren unser Koordinatensystem wie folgt:
- Motor A befindet sich bei
$(0, 0)$ - Motor B befindet sich bei
$(d, 0)$ - Die y-Achse zeigt nach unten (Schwerkraft!)
- Der Stift befindet sich bei
$(x, y)$
\begin{tikzpicture}[scale=0.9]
% Achsen
\draw[->, thick] (0,0) -- (11,0) node[right] {$x$};
\draw[->, thick] (0,0) -- (0,-6) node[below] {$y$};
% Motoren
\fill[blue!60] (0,0) circle (0.2);
\fill[blue!60] (10,0) circle (0.2);
\node[above left] at (0,0) {$A(0, 0)$};
\node[above right] at (10,0) {$B(d, 0)$};
% Abstand d
\draw[<->, green!60!black, thick] (0,0.5) -- (10,0.5) node[midway, above] {$d$};
% Stiftposition
\fill[red] (4,-5) circle (0.15);
\node[below right] at (4,-5) {$P(x, y)$};
% Seile
\draw[red, thick, dashed] (0,0) -- (4,-5) node[midway, left] {$L_A$};
\draw[red, thick, dashed] (10,0) -- (4,-5) node[midway, right] {$L_B$};
% Projektionen
\draw[dotted, gray] (4,0) -- (4,-5);
\draw[dotted, gray] (0,-5) -- (4,-5);
\draw[->, gray, thick] (0,-5) -- (4,-5) node[midway, below] {$x$};
\draw[->, gray, thick] (4,0) -- (4,-5) node[midway, right] {$y$};
\end{tikzpicture}Warum zeigt die y-Achse nach unten? Die Motoren sitzen oben (y=0), der Stift hängt darunter. Damit sind alle y-Werte im Arbeitsbereich positiv und die Seillängenformeln
$L_A = \sqrt{x^2 + y^2}$ funktionieren direkt ohne Vorzeichenprobleme. Würde y nach oben zeigen, müssten wir entweder mit negativen Koordinaten arbeiten oder den Ursprung nach unten verlegen — beides weniger intuitiv.
Gegeben: Die Seillängen
Gesucht: Die Position
Aus dem Satz des Pythagoras ergeben sich zwei Gleichungen:
{{1}}
Durch Subtraktion der beiden Gleichungen erhalten wir
Und daraus
Da
Die inverse Kinematik ist die für den Wall Plotter entscheidende Berechnung: Wir kennen die gewünschte Stiftposition und müssen die nötigen Seillängen berechnen.
Gegeben: Die gewünschte Position
Gesucht: Die Seillängen
Diese Formeln sind erstaunlich einfach - das ist ein großer Vorteil des Wall Plotters gegenüber anderen Roboterkinematiken!
{{1-2}}
Angenommen:
Berechnung der Seillängen:
Gegenprobe - Vorwärtskinematik:
Die inverse Kinematik liefert uns die benötigten Seillängen
$L_A$ und$L_B$ für eine gewünschte Position. Aber wie steuern wir die Motoren an, um diese Längen zu erreichen?
Ein Schrittmotor dreht sich nicht kontinuierlich, sondern in diskreten Schritten. Typischerweise hat ein Schrittmotor 200 Schritte pro Umdrehung (1,8 Grad pro Schritt).
Die Seillänge pro Umdrehung hängt vom Durchmesser der Spule ab:
Bei einem Spulendurchmesser von 10 mm und 200 Schritten pro Umdrehung ergibt sich:
$\frac{\pi \cdot 10,\text{mm}}{200} \approx 0{,}157,\text{mm pro Schritt}$
Um den Stift von Position
- Berechne
$L_{A1}, L_{B1}$ für die aktuelle Position - Berechne
$L_{A2}, L_{B2}$ für die Zielposition - Berechne die Differenz:
$\Delta L_A = L_{A2} - L_{A1}$ ,$\Delta L_B = L_{B2} - L_{B1}$ - Wandle die Differenzen in Motorschritte um
- Bewege beide Motoren gleichzeitig
graph LR
A[Zielposition] --> B[Inverse Kinematik]
B --> C[Seillängen-Differenz]
C --> D[Motorschritte]
D --> E[Motoren bewegen]
Welches Problem sehen Sie?
Wenn der Stift eine gerade Linie zeichnen soll, müssen sich beide Motoren synchron bewegen. Dabei müssen wir sicherstellen, dass der eine Motor nicht schneller fertig wird als der andere.
Der Bresenham-Algorithmus (bekannt aus der Computergrafik für das Zeichnen von Linien auf einem Pixelraster) löst genau dieses Problem: Er verteilt die Schritte beider Motoren gleichmäßig über die Zeit.
\begin{tikzpicture}[scale=0.6]
% Achsen
\draw[->, thick] (0,0) -- (11,0) node[right] {Zeit};
\draw[->, thick] (0,0) -- (0,7) node[above] {Schritte};
% Motor A - 8 Schritte
\draw[blue, thick] (0,0) -- (1,1) -- (2,1) -- (3,2) -- (4,3) -- (5,3) -- (6,4) -- (7,5) -- (8,5) -- (9,6) -- (10,6);
\node[blue, right] at (10,6) {Motor A (6 Schritte)};
% Motor B - 10 Schritte
\draw[red, thick] (0,0) -- (1,1) -- (2,2) -- (3,3) -- (4,3) -- (5,4) -- (6,5) -- (7,6) -- (8,7) -- (9,8) -- (10,8);
\node[red, right] at (10,8) {Motor B (8 Schritte)};
% Schrittmarkierungen
\foreach \y in {1,...,8} {
\draw[dotted, gray] (0,\y) -- (10,\y);
}
\end{tikzpicture}Obwohl die Mathematik elegant ist, gibt es in der Praxis viele Herausforderungen, die die Genauigkeit und Qualität der Zeichnung beeinflussen.
Die Auflösung des Wall Plotters ist nicht überall gleich! Sie hängt von der Position des Stifts ab.
-
Mitte der Zeichenfläche: Beide Seile ziehen schräg nach oben
$\rightarrow$ Änderungen in$x$ und$y$ werden gut aufgelöst -
Nahe einem Motor: Ein Seil ist fast senkrecht
$\rightarrow$ Kleine Winkeländerungen führen zu großen Positionsänderungen -
Oberer Rand: Beide Seile sind fast horizontal
$\rightarrow$ Vertikale Bewegungen sind schwer zu kontrollieren
Die Schwerkraft wirkt auf den Stifthalter und beeinflusst die Zeichengenauigkeit:
- Das Gewicht des Stifthalters sorgt dafür, dass die Seile gespannt bleiben
- Zu leicht: Seile hängen durch, Position wird ungenau
- Zu schwer: Zu viel Reibung auf der Zeichenfläche, Stift kratzt
\begin{tikzpicture}[scale=0.8]
% Setup links - durchhängende Seile
\node at (3,1) {\textbf{Zu leichter Stifthalter}};
\fill[blue!60] (0,0) circle (0.15);
\fill[blue!60] (6,0) circle (0.15);
% Durchhängende Seile (Katenare approximiert)
\draw[red, thick] (0,0) .. controls (1,-1.5) and (2,-2.5) .. (3,-3);
\draw[red, thick] (6,0) .. controls (5,-1.5) and (4,-2.5) .. (3,-3);
\fill[orange] (3,-3) circle (0.15);
\node[below] at (3,-3.3) {Ungenau!};
% Setup rechts - gespannte Seile
\node at (11,1) {\textbf{Richtige Gewichtung}};
\fill[blue!60] (8,0) circle (0.15);
\fill[blue!60] (14,0) circle (0.15);
% Gespannte Seile
\draw[red, thick] (8,0) -- (11,-3);
\draw[red, thick] (14,0) -- (11,-3);
\fill[orange] (11,-3) circle (0.15);
\draw[->, thick] (11,-3) -- (11,-4.5) node[below] {Gewicht};
\end{tikzpicture}- Seile können sich unter Last dehnen (vor allem Nylonseile)
- Beim Aufwickeln auf eine Spule ändert sich der effektive Durchmesser
- Lösung: Ketten oder Zahnriemen statt Seile, oder Umlenkrollen
\begin{tikzpicture}[scale=1.0]
% Spule mit wenig Seil
\draw[thick] (0,0) circle (0.5);
\draw[thick] (0,0) circle (0.6);
\node at (0,-1.2) {Wenig aufgewickelt};
\node at (0,-1.7) {$d_{eff}$ klein};
\draw[<->] (0,0) -- (0.55,0) node[midway, above] {\tiny $r$};
% Spule mit viel Seil
\draw[thick] (5,0) circle (0.5);
\draw[thick] (5,0) circle (0.7);
\draw[thick] (5,0) circle (0.9);
\draw[thick] (5,0) circle (1.1);
\node at (5,-1.5) {Viel aufgewickelt};
\node at (5,-2.0) {$d_{eff}$ gross};
\draw[<->] (5,0) -- (6.1,0) node[midway, above] {\tiny $r$};
% Pfeil
\draw[->, very thick] (1.5,0) -- (3.5,0) node[midway, above] {Mehr Seil};
\end{tikzpicture}Bei zunehmender Wicklung ändert sich die Seillänge pro Motorschritt - das verfälscht die Positionsberechnung!
Bei schnellen Bewegungen oder Richtungswechseln schwingt der Stifthalter nach (Pendelbewegung):
- Der Stifthalter ist ein Pendel an zwei Seilen
- Schnelle Richtungswechsel regen Schwingungen an
- Die Schwingungen verfälschen die Zeichnung
Gegenmaßnahmen:
- Langsame Bewegungen (Beschleunigungs- und Bremsrampen)
- Wartezeiten nach Richtungswechseln
- Schwerer Stifthalter (mehr Trägheit, aber auch mehr Reibung)
Professionelle CNC-Maschinen und auch Wall Plotter verwenden G-Code als Steuersprache. Die wichtigsten Befehle:
| Befehl | Bedeutung |
|---|---|
G0 X30 Y40 |
Schnell zu Position (30, 40) fahren (ohne Zeichnen) |
G1 X50 Y60 |
Linie zu Position (50, 60) zeichnen |
M3 |
Stift absenken (Zeichnen beginnen) |
M5 |
Stift anheben (Zeichnen beenden) |
G0 X20 Y20 ; Zur Startposition fahren
M3 ; Stift absenken
G1 X60 Y20 ; Linie nach rechts
G1 X60 Y60 ; Linie nach unten
G1 X20 Y60 ; Linie nach links
G1 X20 Y20 ; Linie nach oben (zurück zum Start)
M5 ; Stift anheben
\begin{tikzpicture}[scale=0.08]
% Motoren
\fill[blue!60] (0,0) circle (1.5);
\fill[blue!60] (100,0) circle (1.5);
\node[above] at (0,2) {A};
\node[above] at (100,2) {B};
% Quadrat
\draw[very thick, purple, ->] (20,20) -- (60,20) node[midway, below] {1};
\draw[very thick, purple, ->] (60,20) -- (60,60) node[midway, right] {2};
\draw[very thick, purple, ->] (60,60) -- (20,60) node[midway, above] {3};
\draw[very thick, purple, ->] (20,60) -- (20,20) node[midway, left] {4};
% Seile zum Startpunkt
\draw[red, dashed] (0,0) -- (20,20);
\draw[red, dashed] (100,0) -- (20,20);
\end{tikzpicture}Ein einfacher G-Code Interpreter für den Arduino liest Befehle über die serielle Schnittstelle:
void verarbeite_gcode(String zeile) {
zeile.trim();
if (zeile.startsWith("G0") || zeile.startsWith("G1")) {
// Position extrahieren
float x = extrahiere_wert(zeile, 'X');
float y = extrahiere_wert(zeile, 'Y');
if (zeile.startsWith("G0")) {
stift_heben();
}
fahre_zu(x, y);
}
else if (zeile == "M3") {
stift_senken();
}
else if (zeile == "M5") {
stift_heben();
}
}
float extrahiere_wert(String zeile, char achse) {
int pos = zeile.indexOf(achse);
if (pos == -1) return 0;
String wert = "";
pos++;
while (pos < zeile.length() && (isDigit(zeile[pos]) || zeile[pos] == '.' || zeile[pos] == '-')) {
wert += zeile[pos];
pos++;
}
return wert.toFloat();
}
void loop() {
if (Serial.available()) {
String zeile = Serial.readStringUntil('\n');
verarbeite_gcode(zeile);
Serial.println("OK"); // Bestätigung an den PC
}
}- Konzept: Ein Wall Plotter bewegt einen Stift über zwei Seile an einer Wand
-
Mathematik: Die inverse Kinematik berechnet aus
$(x, y)$ die benötigten Seillängen$L_A$ und$L_B$ - Motoransteuerung: Schrittmotoren bewegen die Seile in diskreten Schritten
- Interpolation: Der Bresenham-Algorithmus synchronisiert die beiden Motoren
- Herausforderungen: Auflösung, Schwerkraft, Seildehnung und Dynamik beeinflussen die Zeichenqualität
- Kalibrierungsroutine implementieren (automatische Vermessung des Arbeitsbereichs)
- SVG-Dateien in G-Code umwandeln (z.B. mit Inkscape + G-Code Plugin)
- Beschleunigungs- und Bremsrampen für sanftere Bewegungen
- Mehrfarbiges Zeichnen mit automatischem Stiftwechsel
graph LR
A[SVG-Datei] -->|Inkscape Plugin| B[G-Code]
B -->|Serielle Schnittstelle| C[Arduino]
C -->|Schrittmotoren| D[Wall Plotter]
D --> E[Zeichnung an der Wand]
!?Beispiel
