DrawingBot
Worum geht es hier?
Seit geraumer Zeit beschäftige ich mich neben meiner Fotografie mit dem Thema Creative Code und Plotter-Art - siehe Nucleus . Ich nutze einen Stiftplotter um die Werke aus zu drucken. Die größe der Audrucke ist allerdings beschränkt. Das möchte ich ändern.
Das wird also eine Plattform um einen frei fahrenden Roboter - Drawingbot - zu bauen, der mit seinen 5 Stiften auf dem Boden beliebige große Zeichnungen anfertigen kann - quasi ein fahrbarer Druckkopf. Ich nenne das Teil Ploboter - eine Mischung aus Plotter und Roboter.
Drawingbot Hardware
Mechanik / Fahrgestell
So ungefähr soll das mal aussehen:

Mechanik / Stiftheber
folgt
Die Elektronik
Auswahl des Controllers
Die Frage ist: Arduino oder RaspberryPI, oder gar beide?
Das RaspberryPI Betriebssystem ist kein Echtzeitsystem. Ein Programm kann durch eine beliebige Anzahl anderer Dinge unterbrochen werden, die das Betriebssystem in diesem Moment zu tun beschließt, was zu zufälligen Verzögerungen führen kann. Python fügt noch eigene Timing-Probleme hinzu. Es ist also nicht gut geeignet um via Software für Schrittmotoren genaue und stabile Impulsfolgen im Mikrosekundenbereich zu erzeugen.
Ein Arduino ist für die Ansteuerung der Schrittmotoren also Pflicht. Man kann allerdings einen RaspberryPI davor schalten, der alle nicht zeitkritischen Aufgaben übernimmt.
Spannungsversorgung
- Lipo Akku: SLS 4S1P, 3700mAh 54,76 Wh, 14,8 V
- oder Netzteil über Galgen-Stativ im Keller.
- Spannungskonverter-Modul - bei Eckstein
- Joy-it - SBC -POW-BB - Spannungsversorgung für Breadboards
- SparkFun Logic Level Converter - 3.3V to 5V Bi-Directional (SF12009) bei Eckstein
Der Schaltplan
- 3 Schrittmotoren
- 3 Schrittmotor-Treiber
- 1 Bluetooth-Modul
- 1 Arduino
- 5x1 oder 5x2 Servos
Aufbau über Beedboard. Work in Progress - WIP:

Liste der Bauteile
3D Druckteile etc….
Drawingbot Theorie
Drucker-Auflösung
Da der NEMA 17 mit 1,8° Schrittwinkel direkt ein Rad mit 58 mm Durchmesser antreibt, müssen wir die lineare Bewegung pro Schritt berechnen.
Umfang des Rades berechnen
Der Umfang U eines Kreises mit Durchmesser d = 58 mm ist:
Das bedeutet, dass das Rad pro vollständiger Umdrehung ca. 182,21 mm zurücklegt.
Linearbewegung pro Schritt (Vollschrittbetrieb)
Da der Motor 200 Schritte pro Umdrehung macht, bewegt sich das Rad pro Schritt um:
Auflösung mit Mikroschrittbetrieb
Falls ein 16-fach Mikroschrittbetrieb verwendet wird, erhöht sich die Schrittzahl pro Umdrehung auf 3200 Schritte, sodass die Bewegung pro Mikroschritt beträgt:
Das ergibt:
- 0,911 mm pro Vollschritt.
- 0,057 mm pro 16-fach Mikroschritt.
Radgeschwindigkeiten
Die Radgeschwindigkeiten eines dreirädrigen omnidirektionalen Roboters können mit kinematischen Gleichungen bestimmt werden. Der Roboter hat drei omnidirektionale Räder, die jeweils in einem Winkel von 120 Grad zueinander angeordnet sind.
Gegebene Parameter
: Geschwindigkeit in x-Richtung (vorwärts/rückwärts)
: Geschwindigkeit in y-Richtung (seitwärts)
- ω: Drehgeschwindigkeit (Rotation um die eigene Achse)
- r: Abstand der Räder vom Mittelpunkt des Roboters
,
,
: Winkel der Räder relativ zur x-Achse
Kinematische Gleichungen
Für ein dreirädriges System mit Rädern in den Winkeln
,
,
gilt:
Da die Werte für
,
,
,
bekannt sind, erhalten wir:
Diese drei Formeln werden in Code gegossen.
Drawingbot Software
Arduino Firmware
- Die Software auf dem Bot muss Bluetooth zur kommunikation unterstützen.
- Der Bot wird mit G-Code gesteuert.
Code Skizze
Das ist erst mal eine grobe Code-Skizze:
#include <Arduino.h>
#include <SoftwareSerial.h>
#include <AccelStepper.h>
// Bluetooth Modul an RX=2, TX=3
SoftwareSerial Bluetooth(2, 3);
// Schrittmotoren definieren (Pins für STEP und DIR)
AccelStepper motor1(AccelStepper::DRIVER, 8, 9);
AccelStepper motor2(AccelStepper::DRIVER, 10, 11);
AccelStepper motor3(AccelStepper::DRIVER, 12, 13);
// Rad Berechnungen
const float sqrt3 = 1.73205;
float vx = 0.0, vy = 0.0, omega = 0.0, r = 0.3;
float lastX = 0.0, lastY = 0.0;
// Stift-Ansteuerung
char pen_nr;
char pen_command;
void parsePEN(String params) {
sscanf(params.substring(index).c_str(), "%f %f", &pen_nr, &pen_command);
}
void calculateWheelSpeeds(float vx, float vy, float omega, float r, float &v1, float &v2, float &v3) {
v1 = vx + r * omega;
v2 = -0.5 * vx + (sqrt3 / 2) * vy + r * omega;
v3 = -0.5 * vx - (sqrt3 / 2) * vy + r * omega;
}
void parseSVGPath(String path) {
float newX, newY, ctrlX1, ctrlY1, ctrlX2, ctrlY2;
char command;
int index = 0;
while (index < path.length()) {
command = path[index];
index++;
if (command == 'M' || command == 'L') { // Move to or Line to
sscanf(path.substring(index).c_str(), "%f %f", &newX, &newY);
vx = newX - lastX;
vy = newY - lastY;
lastX = newX;
lastY = newY;
} else if (command == 'C') { // Cubic Bézier curve
sscanf(path.substring(index).c_str(), "%f %f %f %f %f %f", &ctrlX1, &ctrlY1, &ctrlX2, &ctrlY2, &newX, &newY);
vx = newX - lastX;
vy = newY - lastY;
lastX = newX;
lastY = newY;
} else if (command == 'Q') { // Quadratic Bézier curve
sscanf(path.substring(index).c_str(), "%f %f %f %f", &ctrlX1, &ctrlY1, &newX, &newY);
vx = newX - lastX;
vy = newY - lastY;
lastX = newX;
lastY = newY;
} else if (command == 'Z' || command == 'z') { // Close path
vx = 0;
vy = 0;
}
index = path.indexOf(' ', index) + 1;
}
}
void setup() {
Serial.begin(115200);
Bluetooth.begin(9600); // Bluetooth-Modul starten
// Schrittmotoren initialisieren
motor1.setMaxSpeed(1000);
motor1.setAcceleration(500);
motor2.setMaxSpeed(1000);
motor2.setAcceleration(500);
motor3.setMaxSpeed(1000);
motor3.setAcceleration(500);
}
void loop() {
if (Bluetooth.available()) {
String input = Bluetooth.readStringUntil('\n');
if (input.startsWith("PATH")) {
parseSVGPath(input.substring(5));
} else if (input.startsWith("PEN")) {
// PEN 1|2|3|4|5|ALL UP|DOWN|TOGGLE
parsePEN(input.substring(4));
} else {
sscanf(input.c_str(), "%f %f %f", &vx, &vy, &omega);
}
}
float v1, v2, v3;
calculateWheelSpeeds(vx, vy, omega, r, v1, v2, v3);
// Radgeschwindigkeiten auf die Motoren übertragen
motor1.setSpeed(v1 * 200);
motor2.setSpeed(v2 * 200);
motor3.setSpeed(v3 * 200);
motor1.runSpeed();
motor2.runSpeed();
motor3.runSpeed();
delay(10);
}
SVG Grafik als Pfad
Guide: https://www.w3schools.com/graphics/svg_path.asp
Um die Fahrtrichtung aus einer SVG-Grafik wie bei einem Stift-Plotter zu berechnen, muss ich SVG-Pfadbefehle (zB. M
, L
, C
für kubische Bézierkurven, Q
für quadratische Bézierkurven und Z
zum Schließen des Pfads) analysieren und daraus Bewegungsvektoren für den Roboter ableiten. Der Code benötigt also eine Parser-Funktion, die die Richtung und Geschwindigkeit aus einer SVG-Pfadbeschreibung extrahiert. Die SVG-Pfadbeschreibung wird über Bluetooth gesendet, um den Roboter zu steuern.
Beispiele für die unterstützten SVG-Pfadbefehle
<svg height="210" width="400" xmlns="http://www.w3.org/2000/svg">
<path d="M150 5 L75 200 L225 200 Z"
style="fill:none;stroke:green;stroke-width:3" />
</svg>
- M (Move To): Bewegt den „Stift“ ohne zu zeichnen:
M 100 100
-> Der Roboter bewegt sich zu (100, 100), ohne eine Linie zu ziehen. - L (Line To): Zeichnet eine gerade Linie:
L 200 200
-> Der Roboter fährt von der aktuellen Position zu (200, 200). - C (Cubic Bézier Curve): Zeichnet eine kubische Bézier-Kurve mit zwei Kontrollpunkten:
C 150 50, 250 50, 300 100
-> Der Roboter folgt einer Bézier-Kurve mit Kontrollpunkten (150, 50) und (250, 50), bis er (300, 100) erreicht. - Q (Quadratic Bézier Curve): Zeichnet eine quadratische Bézier-Kurve mit einem Kontrollpunkt:
Q 200 50, 300 100
-> Der Roboter bewegt sich entlang einer Kurve mit (200,50) als Kontrollpunkt nach (300,100).
Ich müsste die normalen SVG Elemente in Pfade überführen… das sollte ich einem SVG Editor überlassen.
Ich könnte die svg Datei an den RaspberryPi übergeben und der gibt sie häppchenweise an den Arduino weiter.
Fernsteuerung über iOS App
Anforderungen
Sie muss in erster Linie:
- Bluetooth senden und empfangen.
- Eine SVG-Grafik laden.
- Die SVG-Grafik parsen um daraus G-Code zu erstellen.
- Den G-Code häppchenweise an den Bot verfüttern.
- Feedback vvom Bot empfangen.
In zweiter Linie darf sie gern etwas luxuriöser sein:
- Bluetooth-Connect
- Fernsteuerung
- Plotter - Assistent für Druckaufträge
- Jobs können in Projekten organisiert werden.
- Kompfortable Druckvorschau, mit Papierformat-Vorlagen, Stiftvorlagen, etc.
- Konvertierung von SVG in G-Code.
- Einstellungen
- About-Me
Eine Vorschau der iOS Version der App mit der Fernbedienung. Einige Schalter fehlen hier noch:

Klassendiagramm der iOS-App
Verschiedenes
SVG Grafik Format
Die wichtigen SVG-Elemente
- svg - Container für die gesamte Grafik, definiert Größe und Viewport.
- g - Gruppierung von Elementen, oft als “Ebene” verwendet, um Transformationen oder Styling anzuwenden.
- rect - Rechteck mit Position, Breite, Höhe, optional abgerundeten Ecken.
- circle - Kreis mit Mittelpunkt und Radius.
- ellipse - Ellipse mit Mittelpunkt und zwei Radien.
- line - Gerade Linie zwischen zwei Punkten.
- polyline - Offene Linienfolge durch mehrere Punkte.
- polygon: Geschlossene Form durch mehrere Punkte.
- path - Freie Formen/Kurven, definiert durch Pfadkommandos (zB. M, L, C, Q, A).
- M (Move to): Startpunkt.
- L (Line to): Gerade Linie.
- Q (Quadratic Bezier): Quadratische Kurve.
- C (Cubic Bezier): Kubische Kurve.
- A (Arc): Elliptischer Bogen.
- Z (Close path): Schließt den Pfad.
- text - Text mit Position und Styling.
- image - Einbettung von Rasterbildern (PNG, JPEG).
- use - Wiederverwendung von definierten Elementen.
- defs: - Container für wiederverwendbare Definitionen.
- symbol - Template für wiederverwendbare Grafiken.
- pattern - Muster für Füllungen.
- linearGradient - Linearer Farbverlauf.
- radialGradient - Radialer Farbverlauf.
- clipPath - Beschneidet Inhalte auf eine Form.
- mask - Definiert Transparenzmasken.
- a - Hyperlinks in der SVG.
- animate - Animation von Attributen.
- filter - Effekte wie Unschärfe, Schatten.
- title - Beschreibung für Barrierefreiheit.
- desc - Detaillierte Beschreibung für Barrierefreiheit.
Spezialisierte Elemente (zB. animateTransform, foreignObject) lass ich erst mal weg
Beispiel
- Layout: Die Elemente sind so angeordnet, dass sie in einer 500x500 SVG-Leinwand übersichtlich dargestellt werden.
- Barrierefreiheit: title und desc sind vorhanden.
- Bemerkung: Das image-Element verweist auf ein Platzhalterbild, da externe Bilder browserabhängig sind. Für lokale Tests könnte ein anderes Bild eingebettet werden.
<?xml version="1.0" encoding="UTF-8"?>
<svg width="500" height="500" viewBox="0 0 500 500" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Barrierefreiheit -->
<title>Komplettes SVG-Beispiel</title>
<desc>Eine SVG-Grafik mit allen wichtigen Elementen, inklusive Path.</desc>
<!-- Definitionen -->
<defs>
<!-- Symbol -->
<symbol id="mySymbol" viewBox="0 0 50 50">
<rect x="10" y="10" width="30" height="30" fill="blue"/>
</symbol>
<!-- Linearer Farbverlauf -->
<linearGradient id="linearGrad" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" style="stop-color:red"/>
<stop offset="100%" style="stop-color:yellow"/>
</linearGradient>
<!-- Radialer Farbverlauf -->
<radialGradient id="radialGrad" cx="50%" cy="50%" r="50%">
<stop offset="0%" style="stop-color:white"/>
<stop offset="100%" style="stop-color:green"/>
</radialGradient>
<!-- Muster -->
<pattern id="pattern" x="0" y="0" width="20" height="20" patternUnits="userSpaceOnUse">
<circle cx="10" cy="10" r="5" fill="purple"/>
</pattern>
<!-- ClipPath -->
<clipPath id="clip">
<circle cx="100" cy="100" r="50"/>
</clipPath>
<!-- Maske -->
<mask id="mask">
<rect x="0" y="0" width="100" height="100" fill="white"/>
<circle cx="50" cy="50" r="30" fill="black"/>
</mask>
<!-- Filter -->
<filter id="blur">
<feGaussianBlur in="SourceGraphic" stdDeviation="5"/>
</filter>
</defs>
<!-- Gruppe -->
<g transform="translate(10, 10)">
<!-- Rechteck -->
<rect x="0" y="0" width="60" height="60" fill="url(#linearGrad)"/>
<!-- Kreis -->
<circle cx="100" cy="50" r="30" fill="url(#radialGrad)"/>
<!-- Ellipse -->
<ellipse cx="200" cy="50" rx="40" ry="20" fill="url(#pattern)"/>
<!-- Linie -->
<line x1="0" y1="100" x2="80" y2="100" stroke="black" stroke-width="2"/>
<!-- Polylinie -->
<polyline points="100,100 120,120 140,100" fill="none" stroke="blue" stroke-width="2"/>
<!-- Polygon -->
<polygon points="160,100 180,120 200,100" fill="green"/>
<!-- Path (komplexer Pfad mit Bezier-Kurven und Bogen) -->
<path d="M220 100 L240 120 Q260 140 280 120 C300 100 320 140 340 120 A20 20 0 0 1 360 100 Z"
fill="orange" stroke="red" stroke-width="2"/>
<!-- Text -->
<text x="0" y="180" font-size="16" fill="black">Beispieltext</text>
<!-- Bild -->
<image x="100" y="160" width="60" height="60" xlink:href="https://via.placeholder.com/60"/>
<!-- ClipPath anwenden -->
<rect x="200" y="160" width="100" height="100" fill="cyan" clip-path="url(#clip)"/>
<!-- Maske anwenden -->
<rect x="320" y="160" width="100" height="100" fill="pink" mask="url(#mask)"/>
<!-- Filter anwenden -->
<circle cx="450" cy="50" r="30" fill="gray" filter="url(#blur)"/>
</g>
<!-- Wiederverwendung eines Symbols -->
<use xlink:href="#mySymbol" x="400" y="50"/>
<!-- Hyperlink -->
<a xlink:href="https://www.example.com">
<rect x="0" y="300" width="100" height="50" fill="lightblue"/>
</a>
<!-- Animation -->
<circle cx="200" cy="400" r="20" fill="purple">
<animate attributeName="r" from="20" to="40" dur="2s" repeatCount="indefinite"/>
</circle>
</svg>
G - Transform
Im SVG-Format steht das g-Element für eine Gruppe von Elementen, die zusammen behandelt werden können. Es dient dazu, mehrere SVG-Elemente zu organisieren und gemeinsame Eigenschaften oder Transformationen auf sie anzuwenden.
Die Koordinatenanpassung im Zusammenhang mit transformierten Gruppen bezieht sich auf die Verwendung des transform-Attributs, das auf ein g-Element angewendet wird. Dieses Attribut ermöglicht es, Transformationen wie Verschiebung (translate), Skalierung (scale), Rotation (rotate) oder Schiefe (skew) auf die gesamte Gruppe anzuwenden. Dabei wird das Koordinatensystem der enthaltenen Elemente relativ zu diesen Transformationen angepasst.
<g transform="translate(50, 30) rotate(45)">
<rect x="10" y="10" width="50" height="50" fill="blue"/>
<circle cx="20" cy="20" r="10" fill="red"/>
</g>
- transform=“translate(50, 30)” Verschiebt die gesamte Gruppe um 50 Einheiten nach rechts und 30 Einheiten nach unten.
- rotate(45) Dreht die Gruppe um 45 Grad (im Uhrzeigersinn) relativ zum Koordinatenursprung (0,0) oder einem angegebenen Rotationspunkt.
- Die Koordinaten der Elemente innerhalb der Gruppe (rect und circle) bleiben relativ zum ursprünglichen Koordinatensystem der Gruppe definiert, aber durch die Transformation wird das gesamte Koordinatensystem der Gruppe verändert.
Auswirkung auf Koordinaten:
- Ohne Transformation wären die Koordinaten der Elemente (zB. x=“10”, y=“10”) direkt im globalen SVG-Koordinatensystem platziert.
- Mit der Transformation wird das Koordinatensystem der Gruppe verschoben, gedreht oder skaliert, sodass die relativen Koordinaten der Kind-Elemente entsprechend angepasst erscheinen, ohne dass ihre x-, y-, cx-, oder cy-Werte selbst geändert werden.
Das <g>
-Element mit einem transform-Attribut passt das Koordinatensystem der enthaltenen Elemente an, indem es die gesamte Gruppe transformiert, während die internen Koordinaten der Elemente relativ zur Gruppe unverändert bleiben.
Styling mit CSS
CSS (Cascading Style Sheets) kann verwendet werden, um SVG-Elemente zu stylen, ähnlich wie bei HTML-Elementen, aber mit Fokus auf Vektorgrafik-spezifische Eigenschaften wie fill und stroke. SVG unterstützt Eigenschaften, die in HTML nicht üblich sind:
- statisches Styling
- einfache Interaktionen wie :hover
- Für fortgeschrittene Animationen oder komplexe Logik wird CSS oft mit JavaScript oder SVG-spezifischen Techniken wie SMIL kombiniert.
1. Anwendung von CSS in SVG
CSS kann auf drei Arten in SVG integriert werden:
- Inline-CSS: Direkt in einem SVG-Element mit dem style-Attribut.
<circle cx="50" cy="50" r="20" style="fill: blue; stroke: black;" />
- Internes Stylesheet: Innerhalb eines style-Tags in der SVG-Datei.
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
<style>
circle { fill: blue; stroke: black; stroke-width: 2; }
</style>
<circle cx="50" cy="50" r="20" />
</svg>
```
- Externes Stylesheet: Verlinkung einer separaten CSS-Datei mit <link> (nur wenn SVG in HTML eingebettet ist).
```html
<link rel="stylesheet" href="styles.css">
2. Styling-Eigenschaften für SVG
SVG unterstützt viele CSS-Eigenschaften, die speziell für Vektorgrafiken relevant sind. Wichtige Kategorien:
- Füllung (Fill)
- fill: Farbe oder Muster für die Fläche eines Elements (zB. fill: red; oder fill: url(#gradient);).
- fill-opacity: Transparenz der Füllung (zB. fill-opacity: 0.5;).
- Kontur (Stroke)
- stroke: Farbe der Kontur (zB. stroke: black;).
- stroke-width: Dicke der Kontur (zB. stroke-width: 2;).
- stroke-opacity: Transparenz der Kontur.
- stroke-dasharray: Muster für gestrichelte Linien (zB. stroke-dasharray: 5,5;).
- Transformationen
- transform: Drehen, Skalieren oder Verschieben (zB. transform: rotate(45deg);).
- Text-Eigenschaften
- font-family, font-size, text-anchor (zB. text-anchor: middle; für zentrierten Text).
- Sichtbarkeit und Anzeige
- display: none;, visibility: hidden; oder opacity: 0.5;.
Nicht alle HTML-CSS-Eigenschaften funktionieren in SVG. Zum Beispiel haben margin, padding oder box-shadow keine Wirkung, da SVG keine Box-Model-Logik wie HTML verwendet.
3. Selektoren in SVG
CSS-Selektoren funktionieren in SVG ähnlich wie in HTML:
- Elementselektoren: circle, rect, path.
- Klassen:
<circle class="my-circle" /> → .my-circle { fill: green; }
. - IDs:
<circle id="circle1" /> → #circle1 { fill: yellow; }
. - Pseudoklassen: SVG unterstützt einige wie :hover oder :active.
<style>
circle:hover { fill: purple; }
</style>
4. Besonderheiten
- Präsentationsattribute vs. CSS: SVG-Elemente können Stile direkt als Attribute haben (zB.
). CSS hat jedoch Vorrang, wenn es spezifischer ist. - Einheiten: SVG arbeitet oft ohne Einheiten (zB. stroke-width: 2), aber CSS-Einheiten wie px, rem oder % werden unterstützt.
- Interaktivität: Mit CSS können einfache Animationen oder Übergänge erstellt werden:
<style>
circle { transition: fill 0.3s; }
circle:hover { fill: orange; }
</style>
Für komplexere Animationen wird oft SMIL oder JavaScript verwendet.
- Filter und Effekte: SVG-spezifische CSS-Eigenschaften wie filter können auf Effekte wie Schatten oder Unschärfe zugreifen (zB. filter: url(#blur);).
5. Einschränkungen
- SVG hat keine echte Z-Index-Steuerung wie HTML. Die Reihenfolge der Elemente im Code bestimmt die Stapelreihenfolge (spätere Elemente liegen oben).
- Einige CSS3-Eigenschaften (zB. Flexbox, Grid) sind in reinem SVG nicht anwendbar.
- Browser-Kompatibilität: Ältere Browser unterstützen möglicherweise nicht alle CSS-Eigenschaften für SVG.
Beispiel: Komplexeres Styling
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200">
<style>
.shape-group { fill: none; stroke: blue; stroke-width: 3; }
.circle:hover { fill: yellow; stroke: red; }
.rect { fill: green; opacity: 0.7; }
</style>
<g class="shape-group">
<circle class="circle" cx="100" cy="100" r="50" />
<rect class="rect" x="50" y="50" width="100" height="50" />
</g>
</svg>
G-Code
RobArt sollte mit GCode arbeiten.
G-Code-Befehle teilen dem Computer, der die Motoren der Fertigungsanlage steuert, mit, wie weit und mit welcher Geschwindigkeit er sich bewegen soll.
G-Code-hat eine einfache Struktur: dem Buchstaben G, gefolgt von zwei Zahlen. Obwohl es viele G-Code-Befehle gibt, sind drei gängige Befehle G00, G01 und G02.
Der Befehl G00 oder Rapid Positioning bewegt die Maschine mit maximaler Geschwindigkeit von einer aktuellen Position zu einem bestimmten Punkt. Mit diesem Befehl bewegen sich alle Achsen zusammen, was zu einer geradlinigen Bewegung zur neuen Position führt. Nach der Bewegung kann ein anderer Auftrag, wie zum Beispiel Schneiden oder Drucken, eingeleitet werden.
Der Befehl G01 oder Lineare Interpolation weist die Maschine an, sich in einer geraden Linie mit einer festgelegten Geschwindigkeit F zu einer Endposition zu bewegen, die mit (x, y, z)-Werten angegeben wird. Während sich die Maschine bewegt, berechnet ihre Steuerung alle Zwischenpunkte, bis sie die Position F erreicht.
Der Befehl G02, oder Kreisinterpolation, weist die Maschine an, sich im Uhrzeigersinn in einem kreisförmigen Muster zu bewegen. Wie beim Befehl G01 müssen auch beim Befehl G02 die Endpunktparameter sowie der Drehmittelpunkt definiert werden.
Die drei Befehle können nacheinander verwendet werden, um der Maschine verschiedene Anweisungen zu erteilen. Zunächst kann G00 verwendet werden, um die Maschine an die gewünschte Position zu bewegen, gefolgt von G01, um Material zu schneiden oder zu extrudieren, und G02, um einen anderen Bearbeitungsprozess durchzuführen.
Zu den weiteren G-Code-Befehlen gehören:
- G03 oder Kreisinterpolation gegen den Uhrzeigersinn. Damit wird die Maschine angewiesen, sich gegen den Uhrzeigersinn in einem kreisförmigen Muster zu bewegen.
- Mit G20 werden die G-Code-Einheiten in Zoll definiert.
- Mit G21 werden die G-Code-Einheiten in Millimetern definiert.
- G17, G18 und G19 sind Anweisungen zum Einstellen der Arbeitsebenenkoordinaten der Maschine, die (XY/XZ/YZ) sind.
- G28 weist die Maschine an, sich zu ihrem Referenzpunkt oder ihrer Ausgangsposition zu bewegen.
G-Code-Befehle sind auch verfügbar, um Koordinaten zu interpretieren und das Werkzeug zu positionieren, die Verweilzeit festzulegen, die Fräserkompensation einzurichten, die Spindeldrehzahlen einzustellen, die Kühlmittelströme zu konfigurieren, die Skalierung zu initiieren und Werkzeugwechsel zu steuern.
M-Code
G-Codes und M-Codes arbeiten oft zusammen. Wie G-Code-Befehle haben auch M-Code-Befehle spezifische Anwendungen, sodass beide verwendet werden, je nachdem, was das Werkzeug tun soll.
M-Code, was für Maschinencode oder Miscellaneous Code steht, bezieht sich auf Befehle, die die verschiedenen Funktionen der Maschine steuern. Die Struktur von M-Code-Befehlen ist genauso einfach wie die Struktur von G-Code-Befehlen, mit einem Unterschied: Jeder Befehl beginnt mit einem M.
Einige häufig verwendete M-Code-Befehle sind:
- M00. Programmstopp.
- M02 und M30. Programmende
- M05. Spindelstopp.
- M06. Werkzeugwechsel
- M106. Lüftergeschwindigkeit einstellen. Wird für den 3D-Druck verwendet.
Links
- G-Gode erklärt: https://at-machining.com/de/g-code-cnc/
Parser SVG to G-Code
Guide: https://www.w3schools.com/graphics/svg_path.asp
Um die Fahrtrichtung aus einer SVG-Grafik wie bei einem Stift-Plotter zu berechnen, muss der Code SVG-Pfadbefehle (zB. M
, L
, C
) analysieren und daraus Bewegungsvektoren für den Roboter ableiten. Ich werde den Code erweitern, um eine einfache Parser-Funktion zu integrieren, die die Richtung und Geschwindigkeit aus einer SVG-Pfadbeschreibung extrahiert.
Beispiele für die unterstützten G-Code-Befehle
<svg height="210" width="400" xmlns="http://www.w3.org/2000/svg">
<path d="M150 5 L75 200 L225 200 Z"
style="fill:none;stroke:green;stroke-width:3" />
</svg>
M
(Move To): Bewegt den „Stift“ ohne zu zeichnen:M 100 100
-> Der Roboter bewegt sich zu (100, 100), ohne eine Linie zu ziehen.L
(Line To): Zeichnet eine gerade Linie:L 200 200
-> Der Roboter fährt von der aktuellen Position zu (200, 200).C
(Cubic Bézier Curve): Zeichnet eine kubische Bézier-Kurve mit zwei Kontrollpunkten:C 150 50, 250 50, 300 100
-> Der Roboter folgt einer Bézier-Kurve mit Kontrollpunkten (150, 50) und (250, 50), bis er (300, 100) erreicht.Q
(Quadratic Bézier Curve): Zeichnet eine quadratische Bézier-Kurve mit einem Kontrollpunkt:Q 200 50, 300 100
-> Der Roboter bewegt sich entlang einer Kurve mit (200,50) als Kontrollpunkt nach (300,100).
Ein Name für den DrawingBot
Der Name Robart ist einerseits eine Kombination aus „Robot“ und „Art“. Er klingt wie ein menschlicher Name (Robert), ist hoffentlich für jeden klar erstichtlich mit Kunst und Robotik verbunden.
Die einzelnen Buchstaben stehen für:
- R - für Rollen (durch die Räder)
- O - für Omnidirektional (bewegt sich in alle Richtungen)
- B - für Boden (zeichnet auf dem Boden)
- A - für Automatisierung oder Autonom (arbeitet selbstständig) und Art - also Kunst
- R - für Robotik (ist ein Roboter)
- T - für Technik oder Teilen (arbeitet mit mehreren Stiften/Pinseln)
Aktueller Stand
Breedboard for the win.

Wird fortgesetzt :-)