passtdas - ein Hilfsprogramm für die CNC
Das Problem
Ein Bekannter von mir schrieb mich an. Er betreibt eine CNC-Portalfräsmaschine als Hobby so wie ich und fertigt oft Einzelstücke. Die dabei entstehenden Reste sind aber teils zu schade zum Wegwerfen. Für eine bestmögliche Materialausnutzung probiert er, diese Reste als Rohlinge für weitere Projekte zu verwenden.
“Weißt du, wie ich an der Maschine herausfinden kann, ob mein Frästeil auf den Rohling passt?” - Anonym
Schnell ist es passiert: Den Maßen zufolge passt das Werkstück so gerade auf den Rohling. Setzt man den Nullpunkt nur leicht falsch, so fährt der Fräser über die Werkstückgrenzen hinaus und man kann das Werkstück wegwerfen.
Die Lösung
Es wäre doch toll, wenn die Maschine vor Beginn des Fräsvorganges die Kontur des Werkstückes abfahren würde, oder? So könnte man unkompliziert herausfinden, ob sich der Rohling wirklich komplett innerhalb der Werkstückgrenze befindet.
Da ich auf Anhieb keine schnelle Lösung online finden kann, denke ich an selbstgeschriebene Software für die Umsetzung. Daher mache ich mich an die Arbeit.
Die Software
Für einen schnellen Prototypen wähle ich die Hochsprache python. Warum? Ich beherrsche python recht gut, Bibliotheken für die erforderlichen geometrischen Berechnungen sind verfügbar, und das geschriebene Programm lässt sich leicht in eine all-in-one-Datei kompilieren.
Das Programm soll Maschineninstruktionen (G-Code) lesen und die Fräspfade analysieren. Die Stellen, an denen im Fräsprogramm die maximalen und minimalen X- und Y-Werte
angefahren werden, sollen abgespeichert und selbst als Bewegungskommando in einer Pfaddatei ausgegeben werden.
Lädt man dieses Programm auf die Maschine, so wird ein so ermittelter “Extremwert” angefahren und die Z-Achse von Sicherheits- auf Messhöhe abgesenkt. Anschließend wird das Programm pausiert, sodass der Bediener Anpassungen der Werkstückposition vornehmen kann. Erst durch Einabe eines weiteren Startbefehls wird der nächste Extremwert angefahren usw.
Dieses Programm wird passtdas heißen.
Programmart
Ich entscheide mich für ein Konsolenprogramm mit wenigen Parametern:
Shortcut | Parameter name | Description |
---|---|---|
-f |
--file |
The source file to be analyzed. Required. |
-s |
--zsafety |
Safety height the machine will do flyovers with. Optional. |
-p |
--zprobe |
Probe height the machine will pinpoint to. Optional. |
Die beiden Höhenparameter bekommen Default-Werte, sodass sie nicht immer mit angegeben werden müssen.
Eingabe
passtdas liest Dateien ein und durchsucht sie zeilenweise nach Bewegungsbefehlen G00, G01, G02, G03
. Während die Auswertung für lineare Bewegungen wie G00, G01
einfach ist - Lineare Bewegungen lassen sich durch Punkt-zu-Punkt-Verbindungen ausdrücken, deren Extremwerte nicht zwischen den Punkten liegen können - kann das für Kreissegmente durchaus herausfordernd sein.
Die Höheninformation auf der Z-Achse wird ebenfalls mitgelesen und gespeichert. So kann die Zerspanungstechnikerin schnell prüfen, ob die maximale Frästiefe mit der Gewünschten übereinstimmt.
Befinden sich in der G-Code-Datei keine oder falsch formulierte Anweisungen, so gibt das passtdas entsprechende Fehlermeldungen aus und bricht die Analyse ab.
Definition Kreissegmente
Zum Hintergrund: Im G-Code können Kreissegmente auf zwei Arten definiert werden.
[...]
G00 X5.660 Y-0.000 Z10.000
G02 X-5.660 Y0.000 R5.660 F1600
[...]
Kommando:
“Fahre einen Kreisbogen im Uhrzeigersinn ab dem Punkt
X5.66 Y0
mit Radius5.66mm
bis zum PunktX-5.66 Y0
mit Vorschub1600mm/min
auf Höhe10mm
.”
Zeichnet man diese Kommandos, entsteht ein hängender Halbkreis. Kreise können mittels dreier Punkte definiert werden. Doch nur zwei Punkte sind gegeben. Der dritte Punkt muss mit Hilfe von Anfangs- und Endpunkt aus dem ebenfalls angegebenen Kreisradius berechnet werden.
Aufgabe: Finde heraus, wo dieser Kreis seine Extremwerte in XY hat.
Aber auch so kann ein Kreissegment definiert sein:
[...]
G00 X-2.5696 Y5.0431
G03 X-4.6258 Y3.2616 Z-0.5000 I2.5696 J-5.0431
[...]
Kommando:
“Fahre einen Kreisbogen gegen den Uhrzeigersinn ab dem Punkt
X-2.56 Y5.04
mit MittelpunktkoordinatenI2.56 J-5.04
bis zum PunktX-4.62 Y3.26
.”
Zeichnet man diese Kommandos, entsteht ein kurzes Kreissegment im oberen linken Quadranten. Hier sind zwar drei Punkte (Start- und Endpunkt sowie Kreismittelpunkt) gegeben. Doch auch hier kann es mitunter schwierig werden, herauszufinden, ob irgendwo auf dem Kreisbogen ein Extremwert angefahren wird.
Aufgabe: Finde heraus, wo dieser Kreis seine Extremwerte in XY hat.
Extremwerte von Kreissegmenten berechnen
Ein Kreissegment kann je nach Spanne bis zu vier zusätzliche Extremwerte haben: X+, Y+, X-, Y-
. Bei einem Vollkreis sind dies stets die Koordinatenschnittpunkte vom Radius aus gesehen.
def get_extremes_from_arc(arc, coordinates):
# [...]
x_plus_radius = [center_x + radius, center_y, xyz[2]]
y_plus_radius = [center_x, center_y + radius, xyz[2]]
x_minus_radius = [center_x - radius, center_y, xyz[2]]
y_minus_radius = [center_x, center_y - radius, xyz[2]]
extremevalue_order = [x_plus_radius, y_plus_radius, x_minus_radius, y_minus_radius]
if (arc[1] - arc[0]) < 0:
# crossing the 0° line (x-axis), handle overflow with nested if below
arc[1] += 360
result = []
for crossing_angle in range(0, 721, 90):
if crossing_angle in range(int(arc[0]), int(arc[1] + 1)):
i = int(crossing_angle / 90)
if i > 3:
i -= 4
result.append(extremevalue_order[i])
# [...]
Sind Kreismittelpunkt sowie Kreisradius bekannt, kann aus den Anfangs- und Endpunkten der überstrichene Winkel bestimmt werden. Hierdurch wird nun klar, ob Kreisanfangspunkt und/oder -Endpunkt selbst Extremwerte darstellen, oder ob durch Überstreichen eines Koordinatennullpunktes zusätzliche Extremwerte entstehen. Genau dies tut das obige Codebeispiel.
Datentabelle
Alle möglichen Extremwerte (zwei bei einer Linie, bis zu vier bei einem Kreissegment) werden nun in einer Datentabelle gesammelt. Sobald jede G-Codezeile ausgewertet und die Liste damit komplett ist, werden die Maximal- und Minimalwerte für jede Achse aus dieser Liste bestimmt.
So entstehen schließlich vier XYZ
-Koordinaten, welche für jede Raumrichtung die maximale Ausdehnung des Werkstückes beschreibt.
Parallel durchsucht das Programm alle Befehle an die Z-Achse und merkt sich die maximale Eintauchtiefe.
Ausgabe
Das Kommandozeilenprogramm verfügt über keine visuelle Ausgabe. Daher beschränke ich mich auf die Erstellung eines Simulationsprogramms für die Fräsmaschine, in dem die Werkstückausdehnung angefahren wird und bei jedem Punkt pausiert:
G90
# Go to coordinate zero
MSG "Zmin of this job: -1.0"
G00 Z40
G00 X0 Y0
G01 Z15 F1200
MSG "PathPreview: Hit START to go to Ymin: ['0.0', '-5.66']"
M00
G00 Z40
G00 X0.0 Y-5.66
G01 Z15 F1200
MSG "PathPreview: Hit START to go to Xmin: ['-5.66', '0.0']"
M00
G00 Z40
G00 X-5.66 Y0.0
G01 Z15 F1200
MSG "PathPreview: Hit START to go to Ymax: ['0.0', '5.66']"
M00
G00 Z40
G00 X0.0 Y5.66
G01 Z15 F1200
MSG "PathPreview: Hit START to go to Xmax: ['5.66', '0.0']"
M00
G00 Z40
G00 X5.66 Y0.0
G01 Z15 F1200
# [...]
Obiges Beispiel fährt die Extremwerte eines Kreises mit r=5.66mm
ab. Dabei fährt es stets eine Sicherheitshöhe von Z40
zum Überstreichen der Punkte an und bewegt die Z-Achse bei Ankunft langsam mit F1200
auf die Zielhöhe von Z15
. Wichtig dabei ist, dass der Nullpunkt in Z
vorher korrekt vermessen wurde - sonst kommt es möglicherweise zur Kollision mit dem Werkstück.
Test und Verifikation
Um zu sehen ob das Programm auch wie erwartet funktioniert habe ich drei Testdateien erstellt:
- Unit tests: Prüft einzelne Funktionen im Programm, z.B. ob Linien- und Kreissegmente korrekt erkannt werden
- integration tests: Testen, ob Funktionen im Verbund korrekt funktionieren, z.B. die richtige Berechnung von Extremwerten anhand von Eingabewerten
- End to end tests: Diese Tests prüfen über die gesamte Funktionskette, z.B. ob falsch formatierte Eingabedateien erkannt werden
Zum Schluss erstelle ich mehrere Testdateien mit dem Programm und fahre die daraus erzeugten Extremwerte mit meiner CNC an.
Open-source software
Der Quellcode für passtdas steht kostenlos auf GitHub zur Verfügung, muss allerdings durch Python interpretiert werden.
Ich baue ein Endanwenderfreundliches und leicht zu bedienendes Programm daraus, sobald genügend Leute den Wunsch dafür geäußert haben.