CNC-Engine V0.9
Als ich
damals mit der CNC-Fräserei anfing, stellte ich mir drei Bedingungen:
1. so billig wie möglich,
2. so viel wie möglich selber machen,
3. alles verstehen.
Das heißt, von der Mechanik über Elektrotechnik, analogen Leistungselektronik, digitalen Elektronik bis hin zur Software alles zu durchdringen, zu vertstehen selbst zu fertigen bzw. zu programmieren, also jede Schraube, jeden Lötklecks, jeden Chip und jedes Bit persönlich mit dem Vornahmen ansprechen zu können.
Also programmierte ich ein einfaches CNC-Programm zur Ausgabe von Tack-Richtungssignalen auf die parallele Schnittstelle des PC. Es funktionierte recht gut bis zu Schrittraten von 10 kHz. Darüber hinaus unterbrach irgend ein Windows-Interrupt die Schrittsequenz und die Schrittmotoren blieben stehen. Als Importformat standen HPGL Dateien zur Verfügung. Später unter WindowsXP nutzte ich einen für private Anwendungen freien Hardwaretreiber von "entech". Am Ende verfügte das Programm über einen Interrupteingang für einen inkrementalen Encoder zum Anfahren des Werkstückes und über frei definierbare Pins.
Ansichten:
Mit diesem Programm habe ich 8-9 Jahre gearbeitet. Als die
neue Maschine fertig war, genügte mir dieses Programm nicht mehr. Ich fing an, einen Controller auf ATMEL-Basis zu programmieren.
Atmega-CNC-Controller
Der CNC-Controller basiert auf einem
Atmega128 und hat nur eine minimale externe Beschaltung, LCD-Display (4x27 Zeichen), einige Nand-Gatter, Quarz, Spannungsstabilisierung und RS232-Schnittstelle. Eigentlich war sie nur als Testplatine gedacht, arbeitet aber nun schon seit einigen Jahren zuverlässig.
Die Software wurde in c geschrieben und stellt einen NC-Interpreter dar, der die Standard-G-Codes interpretiert. Die Befehle erhält der Controller über ein beliebiges COM-Terminal mit Software-Handshake (Xon/Xoff).
Die Schrittsequenzen werden über einen der Timer erzeugt, wobei die linearen und zirkularen Bewegungen mit einem
Bresenham-Algorithmus berechnet werden. Der Bresenham-Algorithmus für die zirkularen Bewegungen ist so modifiziert, dass eine Kreisbahn mit beliebigem Anfangs- und Endpunkt, so auch mehrere Umläufe, gefahren werden kann. Somit ist auch eine Helix möglich. Mir ist es jedoch nicht gelungen, die genaue interne Schrittzahl für eine beliebige Bresenham-Kreisbahn voraus zu berechnen. Dies ist allerdings notwendig, wenn ein Gewinde mit definierter Steigung gerfertigt werden soll, um die Z-Achse mit dem jeweiligen Phasenwinkel zu synchronisieren. Als Ausweg führe ich bei Erkennen eines Helixbefehls die Simulation eines Umlaufes durch und ermittle so die Schrittzahl. Dies dauert nur wenige Millisekunden.
Der Controller beherrscht außerdem die vollständige Koordinatentransformation. Drehung, Verschiebung, Varia und Spiegelung sind im 3D-Raum möglich. Dies ist sehr nützlich, wenn das Werkstück (NC-Datei) gegenüber dem Rohling nicht in der richtigen Position liegt.
Besonders angenehm ist die
Gewindefertigung mit einem einzigen Befehl (G5 - Rechtsgewinde, G6 - Linksgewinde). Als Parameter werden X,Y - Gewindemittelpunkt auf der Arbeitsebene, Z - Gewindestart, A - Gewindelänge, I - Startradius, J - Endradius, K - Gewindesteigung, R - radialer Vorschub pro Helix, L - Werkzeugdurchmesser übergeben. Außen- und Innengewinde unterscheidet der Controller über die Relation von Start- und Endradius (I < J -> Innengewinde, J < I -> Außengewinde). Durch das Vorzeichen der Gewindelänge (A) wird mitläufiges oder gegenläufiges Fräsen bestimmt.
Ein wesentliches Problem, welches ich als Beschränkung und manchmal auch als nervraubend empfinde, ist die fehlende Vektorvorschau, weil die Maschine nach jedem Vektor stoppt. Da die Software jedoch "historisch" gewachsen ist, fällt es schwer eine Vektorvorschau einzubauen.
Die Register und der Befehlssatz sind in den folgenden Tabellen beschrieben.
Register:
Bezeichnung |
Funktion |
Wertebereich |
A | Position A-Achse, Koordinatentransformation, Gewinde | float |
D | Controller-Funktionen / Einstellungen | integer |
F | Vorschub | float |
G | G-Codes | integer |
H | Werkzeugoffset (nicht relevant) | float |
I | Kreis, Helix, Koordinatentransformation, Gewinde | float |
J | Kreis, Helix, Koordinatentransformation, Gewinde | float |
K | Kreis, Helix, Koordinatentransformation, Gewinde | float |
L | Gewinde Werkzkeugdurchmesser | float |
M | Maschinen-Funktionen | integer |
N | Befehlsnummer (nicht relevant) | integer |
P | Hilfe | integer |
R | Kreis, Helix, Koordinatentransformation, Gewinde | float |
S | Spindeldrehzahl (nicht relevant) | float |
T | Werkzeugnummer (nicht relevant) | integer |
U | Koordinatentransformation | float |
V | Verweilzeit | integer |
X | Position X-Achse, Koordinatentransformation, Gewinde | float |
Y | Position Y-Achse, Koordinatentransformation, Gewinde | float |
Z | Position Z-Achse, Koordinatentransformation, Gewinde | float |
D-Codes:
Nummer |
Funktion |
D1 | aktuelle Achseneinstellungen in ASCII ausgeben |
D2 | aktuelle Maschineneinstellungen in ASCII ausgeben |
D4 | aktuelle Maschineneinstellungen binär ausgeben |
D5 | aktuelle Achseneinstellungen binär ausgeben |
D6 | Maschineneinstellungen binär empfangen |
D7 | Achseneinstellungen binär empfangen |
D10 | Ready-Flag abfragen |
D11 | Status in ASCII ausgeben |
D12 | absolute Position (mm) ausgeben |
D121 | absolute Position (mm) Handachse ausgeben |
D13 | absolute Position (Schritte) ausgeben |
D14 | letzte Positionsabweichung (mm) ausgeben |
D15 | letzte Positionsabweichung (Schritte) ausgeben |
D16 | Einstellungen aus EEProm in RAM laden |
D17 | Einstellungen aus RAM in EEProm speichern |
D20 | Taktquelle Timer |
D21 | Taktquelle Handencoder |
D210 | Handencoderachse X |
D211 | Handencoderachse Y |
D212 | Handencoderachse Z |
D213 | Handencoderachse A |
D30 | Ausgaben: maschinenlesbar |
D31 | Ausgaben: klartext |
D32 | Ausgaben: maschinenlesbar+klartext |
D33 | Ausgabeziel: keins |
D34 | Ausgabeziel: LCD-Display |
D35 | Ausgabeziel: Terminal |
D36 | Ausgabeziel: LCD-Display+Terminal |
D37 | Koordinatenausgabe: absolut |
D38 | Koordinatenausgabe: aktuelle Transformation |
D510 | Ausgaben mit Debuginformationen |
D511 | Ausgaben ohne Debuginformationen |
G-Codes:
Nummer |
Funktion |
Parameter |
G0 | linear Schnellvorschub | - |
G1 | linear Arbeitsvorschub | F |
G2 | zirkular Uhrzeigerrichtung | X,Y,Z,A,I,J,K,R |
G3 | zirkular gegen Uhrzeigerrichtung | X,Y,Z,A,I,J,K,R |
G4 | Verweilen mit Verweilzeit | V |
G5 | Rechtsgewinde | X,Y,Z,A,I,J,K,R,L |
G6 | Linksgewinde | X,Y,Z,A,I,J,K,R,L |
G17 | Arbeitsebene XY | - |
G18 | Arbeitsebene XZ | - |
G19 | Arbeitsebene YZ | - |
G53 | linearen Offset aufheben | - |
G54..59 | linearer Offset | X,Y,Z,A |
G60 | auf Referenzpunkt fahren (hierarchisch) | - |
G61 | auf aktuellen Offset fahren (invers hierarchisch) | - |
G74 | referenzieren | - |
G75 | Positionstest | - |
G90 | Programmierung absolut | - |
G91 | Programmierung relativ | - |
G92 | Varia senkrecht zu Arbeitsebene ein | - |
G93 | Varia senkrecht zu Arbeitsebene aus | - |
G100 | Bewegung: direkt zum Ziel | - |
G101 | Bewegung: hierarchisch zum Ziel | - |
G102 | Bewegung: invers hierarchisch zum Ziel | - |
G103 | Koordinatentransformation aufheben | - |
G104-109 | Koordinatentransformation | X,Y,Z,A,I,J,K,R,U |
G120 | Kreisinterpolation mit linearen Einzelvektoren | - |
G121 | Kreisinterpolation mit Bresenham | - |
M-Codes:
Nummer |
Funktion |
M3 | Hauptspindel an, Uhrzeigerrichtung |
M4 | Hauptspindel an, gegen Uhrzeigerrichtung |
M5 | Hauptspindel aus |
M38 | Schrittmotorstrom aus |
M39 | Schrittmotorstrom an |
M100 | Notaus quitieren |