Ansteuerung einer Schrittmotor-Achse mit Mikrocontrollern am Beispiel eines Arduino-Mega

Aus HSHL Mechatronik
(Unterschied) ← Nächstältere Version | Aktuelle Version (Unterschied) | Nächstjüngere Version → (Unterschied)
Zur Navigation springen Zur Suche springen

Zurück zum übergeordneten Projekt: 3-D-Bearbeitungsmaschine (Projekt des Schwerpunkts GPE im Studiengang MTR)

Kategorie: 2019/ 2020_WS_MTR7_Praktikum_GPE

Autoren: Felix Bruchhage, Leon Lieshek

Einleitung

Das Modul Global Production Engineering 3 im 7. Semester des Studiengangs Mechatronik beinhaltet das Praktikum Produktionstechnik. Dabei soll den Studierenden ein Einblick in die praktische Automatisierungstechnik gegeben werden. Die Praktikumsaufgabe ist Teil des Hauptprojektes „Aufbau einer 3-D-Bearbeitungsmaschine“ und beinhaltet die Ansteuerung von 3 CNC Achsen mit Hilfe des Microcontrollerboards Arduino Mega.
Im Jahrgang 2016/ 2017 wurden Teile des Projekts von Kuete Tetsop Anicet bearbeitet mit der Aufgabe eine Schrittmotor-Achse anzusteuern. Im Jahrgang 2019/ 2020 wird das Projekt von Felix Bruchhage und Leon Lieshek übernommen und auf die simultane Ansteuerung von drei Schrittmotor-Achsen erweitert.

Dazu wurden die folgenden Anforderungen als Aufgabe gestellt:

Aufgabenstellung

Die Aufgabe des Teilprojektes war es, drei Achsen der selbstgebauten CNC-Bearbeitungsmaschine mit Hilfe eines Arduino Mega 2560 Microcontrollerboards anzusteuern. Die drei Achsen werden von Igus Nema 23 Schrittmotoren angetrieben, die mit jeweils einem Geckodrive G201X Schrittmotortreiber gesteuert werden.
Die anzufahrenden Koordinaten werden durch einen zentralen Steuerungsalgorithmus mit der Software MATLAB aus dem G-Code des CAD/ CAM-Programms in Form eines Strings an den Microcontroller gesendet. Es sind grundsätzlich zwei Arten von Strings zu unterscheiden. Das Muster „U1000V1000W1000“ stellt eine Referenzposition dar. Diese gibt die Position des Fräsers zu Programmstart in 1/10 mm an und bildet eine absolute Position von Koordinaten-Ursprung der Fräsmaschine. Eine Anfahrtsposition wird nach dem Muster „X1111Y2222Z3333F4444" übermittelt. Auch sie enthält die Absolutkoordinaten [1/10 mm] des Zielpunktes, auf den der Fräser gefahren werden soll. Zusätzlich wird eine Verfahrgeschwindigkeit, der sogenannte Vorschub (F) in 1/10 mm/min angegeben.

Zu Beginn der Aufgabenbearbeitung wurden folgende Projektanforderungen aufgestellt:

• Aufbau/ Hardware

  • Schaltpläne erstellen mit den verwendeten Komponenten und Schnittstellen definieren
  • Gehäuse für Arduino und Platine entwickeln und herstellen (Zugänglichkeit der Schnittstellen RS232, Spannungsversorgung, D-Sub-Stecker vorsehen)
  • Kommunikationsschnittstelle mit D-Sub-Stecker kurzschlusssicher umsetzen (in Gehäuse integriert)
  • Verdrahtung nach Schaltplan zwischen Arduino und D-Sub-Stecker

• Software

  • String einlesen über RS232-Schnittstelle
  • Unterscheidung zwischen Referenz- und Anfahrkommando
  • Zahlenwerte für Positionen und Vorschub aus String extrahieren
  • Umrechnung von absoluten Positionswerten in inkrementale Verfahrwege
  • Umrechnung von Positionswerten [mm] in Schrittwerte zur Übergabe an Schrittmotortreiber
  • Ableitung von relativen Geschwindigkeiten für alle drei Achsen in Abhängigkeit der Verfahrwege und Vorschubgeschwindigkeit
  • Übergabe von Schritt- und Richtungswerten an die drei Schrittmotortreiber
  • Simultane Ansteuerung von drei Motoren

• Funktionstest

  • Verdrahtung zwischen Arduino und Schaltschrank prüfen
  • Einlese- und Umrechnungs-Funktionen der Strings testen
  • Verfahrtests mit verschiedenen Stings und Genauigkeit bestimmen
  • Kommunikation zwischen Matlab-Steuerungsalgorithmus testen
  • Finaler Test an der Maschine

Die genaue Systemübersicht mit allen Ein- und Ausgängen ist in Abb. 1 und 2 des funktionalen Systementwurfs detailliert erkennbar.

Technologien

Hardware

Microcontroller: Arduino Mega 2560

Microcontroller ATmega2560
Betriebsspannung 5V DC
Eingangsspannung (empfohlen) 7-12V DC
Eingangsspannung (Grenzwerte) 6-20V DC
maximale Stromaufnahme 500 mA
maximaler Strom je In-/ Output Pin 40 mA
maximaler Strom des 3,3V Pins 50 mA
Flash Speicher 256 KB (8 KB genutzt durch Bootloader)
SRAM 8 KB
EEPROM 4 KB
Analoge Eingänge 16
Digitale Pins 54 (konfigurierbar als In- oder Outputs), 14 als PWM-Outputs konfigurierbar
Anschlüsse USB, serielle Schnittstelle, Spannungsversorgung

Weitere Daten zum Arduino Mega 2560 Mikrocontroller: [1]


Schrittmotortreiber: GeckoDrive G201X

Eingangsspannung 18-80 VDC
maximale Stromaufnahme des angeschl. Motors 7 A
Induktivität des Motors 1-50 mH
Eingangsfrequenz des Step-Input 0-200 kHz
Spannung der Inputs 3,3-5 VDC
Inputs Spannungsversorgung, Disable, Direction, Step, Common, Current Set
Outputs Winding A+B (1 Schrittmotor)

Datenblatt Geckodrive G201X Schrittmotortreiber: Datei:Betriebsanleitung Schrittmotortreiber.pdf


Schrittmotor: Igus NEMA 23

Nennspannung 24-48 V DC
max. Eingangsspannung 60 V DC
Nennstrom 4,2 A
Haltemoment 2,0 Nm
Schrittwinkel 1,8°
Widerstand pro Phase 0,5 Ω ± 10%
Induktivität pro Phase 1,9 mH ± 20%
Pin 1 Signal A/ (braun)
Pin 2 Signal A (weiß)
Pin 3 Signal B/ (blau)
Pin 4 Signal B (schwarz)
Pin 5 PE
optionale Bauteile Encoder, Bremse

Datenblatt Igus Nema23 Schrittmotor: Datei:Motordatenblatt DE.pdf

Software

Arduino IDE

Die Arduino IDE (Integrated Development Environment) ist eine kostenfreie Programmierumgebung zur Erstellung von Anwendungen für Arduino Mikrocontroller. Die Programmiersprache ist angelehnt an C und C++ mit einigen speziellen Anforderungen an die Struktur. Zusätzlich zur eigentlichen Programmierungen werden Bibliotheken angeboten, die viele Softwareprobleme bereits abdecken und Funktionen bereitstellen.

HTerm

Die kostenfreie Software HTerm ermöglicht eine serielle Kommunikation über die RS232-Schnittstelle. Mit dieser wurde die serielle Schnittstelle eingerichtet und auf Ihre Funktion geprüft. Das Senden eines Strings an den Arduino ist ebenfalls mit der IDE möglich. Der Funktionstest wurde allerdings mit dieser Software durchgeführt, um sicherzustellen, dass die Kommunikation auch über ein externes Programm ohne Komplikationen funktioniert.

Fritzing

Firtzing ist eine freie Software der Fachhochschule Potsdam, die es ermöglicht elektronische Schaltungen am Computer zu entwerfen. Dazu stehen viele vorkonfigurierte Bauteile zur Verfügung, die durch eigen erstellte Bauteile ergänzt werden können. Das Sortiment ist primär auf die Arduino-Plattform abgestimmt, sodass speziell Arduino-Projekte einfach dokumentiert werden können. Insgesamt stehen drei verschiedene Entwicklungsansichten zur Verfügung (Steckplatine, Schaltplan und Platine). In diesem Projekt wurde die Schaltplanansicht ausgewählt.

Funktionaler Systementwurf

Der funktionale Systementwurf dient dazu, um die Struktur des Systems lösungs- und hardwareneutral zu ermitteln. Zunächst wurde eine Gesamtübersicht der gesamten CNC-Bearbeitungsmaschine erstellt (s. Abb. 1).

Abb. 1: Funktionaler Systementwurf Gesamtsystem















Das erstellte CAD-Modell wird in ein CAM-Programm eingeladen, das aus dem Volumenkörper Verfahrbefehle in Form von G-Code erzeugt. Mit dem Steuerungsprogramm wird dieser in Positionswerte für die X-, Y- und Z-Achsen und in Vorschubgeschwindigkeiten umgerechnet. Diese Strings erhält der Achs-Controller, um die Schrittmotortreiber und schließlich die Achsen anzusteuern.

Im Detail für den Achscontroller ergibt sich folgender Entwurf:

Abb. 2: Funktionaler Systementwurf des Achscontrollers

Die Originaldateien der Fotos des funktionalen Systementwurfs sind hier zu finden: Datei:Funktionaler Systementwurf Original.pptx









Technischer Systementwurf

Der technische Systementwurf (s. Abb. 3) detailliert die Systemübersicht dahingehend, dass die Schnittstellen der einzelnen Komponenten definiert werden:

Abb. 3: Technischer Systementwurf

Hier ist zu erkennen, dass der String als Systeminput über die serielle RS-232 Schnittstelle des Arduino Mega 2560 übergeben wird. Dieser bildet das Herzstück des Achscontrollers, verarbeitet die Eingaben und steuert die Schrittmotoren an. Zur Ansteuerung werden insgesamt 6 digitale Ausgänge des Microcontrollers benötigt. Die Verbindung zwischen Arduino und Schaltschrank, bzw. Eingängen der Schrittmotortreiber, wird über den 25-poligen D-Sub-Stecker hergestellt.

Die Originaldatei des technischen Systementwurfs ist hier zu finden: Datei:Technischer Systementwurf Original.pptx







Abb. 4: Signale des Schrittmotors [1]

Drei davon senden die Schrittsignale für die drei Achsen an die Schrittmotortreiber. Dabei handelt es sich um Rechtecksignale, das zwischen High (5V) und Low (0V) schaltet (s. Abb. 4). Die Dauer eines Pulses entscheidet über die Drehgeschwindigkeit der Motoren. Je kürzer ein Puls, desto schneller fährt der Motor.
Zur Vorgabe der Drehrichtung werden drei weitere digitale Ausgänge des Arduinos genutzt (s. Abb. 4). Ein Low-Signal lässt den Motor im Uhrzeigersinn fahren, ein High-Signal gegen den Uhrzeigersinn.





Zusätzlich wird im technischen Systementwurf der Programmablauf (s. Abb. 5) übersichtlich dargestellt:

Abb. 5: Programmablauf

Nach Initialisierung der Variablen und Festlegung der seriellen Datenübertragungsgeschwindigkeit (Baudrate) wird der String eingelesen. Über das erste Zeichen wird entschieden, ob es sich um ein Referenzkommando (1. Zeichen = „U“) oder ein Anfahrtskommando (1. Zeichen = „X“) handelt. Zum Auslesen der Anfahrten und Referenzen werden zwei Funktionen aufgerufen, die im String nach den Zahlenwerten für die jeweiligen Absolutpositionen bzw. Vorschubgeschwindigkeiten suchen und diese in Arrays speichern. Liegt ein Referenzkommando vor, wird wieder an den Programmanfang gesprungen und ein neuer String eingelesen. Bei einem Anfahrtskommando wird nach Einlesen der Koordinaten aus dem absoluten Verfahrweg ein inkrementaler Weg berechnet (s. Abb. 6). Dies geschieht durch Subtraktion der Anfahrtswerte von den Referenzwerten.

Die Originaldatei des Programmablaufs ist hier zu finden: Datei:Programmablauf Original.pptx

Abb. 6: Absolute und inkrementale Bemaßung [2]






Eine Absolutbemaßung bezieht sich stets auf den Ursprung des Koordinatensystems und wird von diesem aus angegeben. Es wird nun angenommen, dass der Fräser an Punkt P1 steht. Als Referenz wurde dementsprechend und vorgegeben. Wenn im Anschluss zum Punkt P2 gefahren werden soll, werden die Anfahrtswerte und übergeben. Den Schrittmotoren muss allerdings die Differenz zwischen beiden Punkten, also dx und dy übergeben werden, um auf P2 zu fahren. Diese Differenz wird als inkrementales Maß bezeichnet. In diesem Programmschritt wird dieses Maß von mm in Schritte für die Motoransteuerung umgerechnet. Dies geschieht durch Division des Inkrementalmaßes mit einem Schrittverhältnis:


Die Originaldatei des Bildes zur Erklärung der absoluten und inkrementalen Bemaßung ist hier zu finden: Datei:Absolut Inkremental Original.pptx


Danach wird die neue Referenzposition als altes Anfahrtskommando gesetzt, um beim nächsten Verfahren erneut ein inkrementales Maß berechnen zu können.

Außerdem werden aus der übergebenen Vorschubgeschwindigkeit relative Geschwindigkeiten für alle drei Achsen in Abhängigkeit ihrer Verfahrwege berechnet. Dies ist zwingend erforderlich, damit der Fräser in Schrägen verfahren kann, bei denen eine Achse einen längeren Weg zurücklegen muss als die andere. Würden dann die Motoren gleich schnell angesteuert, wird eine 45°-Schräge verfahren und die Achse mit dem längeren Weg würde länger angesteuert werden als die andere.

Abb. 7: 3D-Pythagoras [3]

Zunächst wird der dreidimensionale Pythagoras (s. Abb. 7) verwendet, um die Hypotenusenlänge zu berechnen:

Wird eine Achse nicht verfahren, so ist dieser Wert gleich null und c oder c‘ wird berechnet. Die resultierenden Geschwindigkeiten ergeben sich schließlich, indem man den inkrementellen Weg der Achse zur Hypotenusenlänge ins Verhältnis setzt und mit der übergebenen Vorschubgeschwindigkeit (F) multipliziert. Die Berechnung ist beispielhaft für die X-Achse angegeben:

Am Schluss des Programms werden alle drei Achsen mit den Schritt- und Richtungssignalen angesteuert.

Die Originaldatei des Bildes zur Erklärung der Berechnung der relativen Achsengeschwindigkeiten ist hier zu finden: Datei:3D Pythagoras Original.pptx



Entwicklung

Schaltplan

Die Entwicklung begann damit, die Systemübersicht des technischen Systementwurfs in einen Schaltplan zu überführen. Dazu wurde das Programm Fritzing verwendet. Der Arduino bekommt seine Versorgungsspannung von 5V DC über das USB-Kabel über den angeschlossenen PC, mit dem auch der String übergeben wird. Alternativ kann der Arduino auch über ein externes Netzteil bestromt werden. Ein weiteres Netzteil dient zur Bestromung der Schrittmotortreiber. Es ist darauf zu achten, eine gemeinsame Masse zwischen Arduino und Schrittmotortreibern herzustellen, damit sich alle Komponenten in einem gemeinsamen Bezugssystem befinden. Daher werden die Common Eingänge mit der Masse des Arduinos verbunden. Die weiteren Verbindungen zwischen Arduino und Schrittmotortreibern sind äquivalent wie bereits im technischen Systementwurf beschrieben.

Medium:Schaltplan_Arduino_3Schrittmotoren.jpg

Hier ist der originale Schaltplan zu finden: Datei:Schaltplan CNC Arduino.zip

Pinbelegungsplan

Als Schnittstelle zwischen Fräse und Microcontroller dient der 25-polige D-Sub-Stecker. Die Belegung von diesem und die Verbindung zum Arduino ist übersichtlich in der folgenden Tabelle dargestellt:

Pin D-Sub-Stecker Belegung im Schaltschrank Belegung am Arduino
2 Step x-Achse DO 09
3 Direction x-Achse DO 08
4 Step y-Achse DO 13
5 Direction y-Achse DO 12
6 Step z-Achse DO 11
7 Direction z-Achse DO 10
21 Common x-Achse Ground
22 Common y-Achse Ground
23 Common z-Achse Ground

Gehäuse

Abb. 8: Explosionsdarstellung des Gehäuses mit Arduino

Durch die Wahl eines additiven Fertigungsverfahrens, das Selektive Lasersintern (kurz: SLS), war ein hohes Maß an Freiheiten bei der Konstruktion gegeben. Daher sind keine konstruktiven Restriktionen durch das gewählte Fertigungsverfahren gegenüber konventionellen subtraktiven Fertigungsverfahren wie beispielsweise dem Fräsen gegeben.

Hier sind die originalen CAD-Daten des Gehäuses zu finden: Datei:Baugruppe Gehäuse Arduino.zip

Hardwareaufbau

Um die Verdrahtung entsprechend des Schaltplans umzusetzen, wurde eine Lochrasterplatine verwendet. Auf der Unterseite wurde eine Stiftleiste eingelötet, damit die Platine auf den Arduino gesteckt werden kann. Die Verbindung zwischen Lochrasterplatine und der D-Sub 25 Buchse wurde durch starre Leitungen mit einem Leitungsquerschnitt von 0,75mm² realisiert. Um Fehlkontaktierungen und Kurzschlüsse zu vermeiden, wurden die verschiedenen Signale mithilfe von Schrumpfschläuchen gegeneinander isoliert. Der Arduino Mega wird durch M3 Kunststoffschrauben in dem Gehäuse montiert. Die 25 polige D-Sub Buchse wird durch eine Nut im Unterteil des Gehäuses eingeschoben und durch den Deckel festgeklemmt.

Abb. 9: Hardwareaufbau im Gehäuse










Programmierung


Die Programmierung des Arduinos wurde mit der Arduino IDE durchgeführt. Der grundlegende Programmablauf wurde bereits beim technischen Systementwurf erläutert. Daher soll in den folgenden Ausführungen nur auf einzelne Abschnitte eingegangen werden. Zur Ansteuerung der Achsen wir die Accel-Stepper-Bibliothek verwendet.

Die Originaldatei des Programms ist hier zu finden: Datei:20190510 Verfahren mit Bib.zip

Deklarierung der Variablen

Am Anfang des Programms werden, wie in jedem C-Programm die benötigten Variablen deklariert und die Bibliotheken einbezogen.

 
#include <AccelStepper.h>                   //Einbeziehung der AccelStepper Bibliothek zur Ansteuerung von Schrittmotoren mit dem Arduino. Dokumentation: https://www.airspayce.com/mikem/arduino/AccelStepper/

//Konstruktor der AccelStepper Bibliothek zur Anlegung des Objektes X-Achse mit Attributen (Interface=Nutzung eines Schrittmotortreibers, Step Pin=Output 9, Direction Pin=Output 8)
AccelStepper Achse_X(1,9,8); 
//Konstruktor der AccelStepper Bibliothek zur Anlegung des Objektes Y-Achse mit Attributen (Interface=Nutzung eines Schrittmotortreibers, Step Pin=Output 13, Direction Pin=Output 12)               
AccelStepper Achse_Y(1,13,12); 
//Konstruktor der AccelStepper Bibliothek zur Anlegung des Objektes Z-Achse mit Attributen (Interface=Nutzung eines Schrittmotortreibers, Step Pin=Output 11, Direction Pin=Output 10)             
AccelStepper Achse_Z(1,11,10); 
             
double Anfahrten[4]={0.0,0.0,0.0,0.0};      //Array zur Speicherung der Anfahrtspositionen des aufgeteilten Strings (X_Pos, Y_Pos, Z_Pos, F)
double Referenzen[3]={0.0,0.0,0.0};         //Array zur Speicherung der Referenzpositionen des aufgeteilten Strings (X_Pos, Y_Pos, Z_Pos)

char Zeichen;                               //Zum Speichern des ersten Zeichens des Strings und zum Abgleich ob Referenz- oder Anfahrtskommando

double String_Umrechnung=0.1;               //Umwandlung der Einheit des Strings von 1/10 mm in mm 
double Schrittwinkel=1.8;                   //Zur Umrechnung von mm in Schritte: pro Schritt dreht der Motor 1,8°
double Distanz=40;                          //Zur Umrechnung von mm in Schritte: pro Umdrehung werden 40mm zurueckgelegt auf Maschine 66mm bei der Zahnriemenachse
double Treiberverhaeltnis=0.1;              //Zur Umrechnung von mm in Schritte: Verhälnis von Schrittmotortreiber Treiber/ Motor 1/10=0.1
double Schrittverhaeltnis=((Distanz*Schrittwinkel)/360)*Treiberverhaeltnis;  //Variable zur Umrechnung von mm in Schritte

double X_Schritte;                          //Speicherung der Schrittwerte, die die X-Achse zurücklegen soll, wird an Schrittmotor X-Achse übergeben
double Y_Schritte;                          //Speicherung der Schrittwerte, die die Y-Achse zurücklegen soll, wird an Schrittmotor Y-Achse übergeben
double Z_Schritte;                          //Speicherung der Schrittwerte, die die Z-Achse zurücklegen soll, wird an Schrittmotor Z-Achse übergeben
double F_Geschw;                            //Speicherung des Vorschubwertes
double c;                                   //Zwischenvariable zur Speicherung des Ergebnisses des 3D-Pythagoras und Ableitung der relativen Achsengeschwindigkeiten

//Variablen zur Speicherung der relativen Achsengeschwindigkeiten, die den Schrittmotoren übergeben werden
double Speed_X;
double Speed_Y;
double Speed_Z;

//Variablen zur Erkennung der Positionen der Buchstaben und Zahlenwerte im String. Falls ein benötigter Buchstabe im String nicht gefunden wird, liegt eine ungültige Eingabe vor.  
int x_pos=999;                              //Speicherung der Position des Verfahrweges in X-Richtung im Anfahrtenstring.        
int y_pos=999;                              //Speicherung der Position des Verfahrweges in Y-Richtung im Anfahrtenstring. 
int z_pos=999;                              //Speicherung der Position des Verfahrweges in Z-Richtung im Anfahrtenstring. 
int f_pos=999;                              //Speicherung der Position Vorschubwertes im Anfahrtenstring. 
int u_pos=999;                              //Speicherung der Position der X-Referenz im Referenzstring. 
int v_pos=999;                              //Speicherung der Position der Y-Referenz im Referenzstring. 
int w_pos=999;                              //Speicherung der Position der Z-Referenz im Referenzstring. 

//Variablen zur Zwischenspeicherung der extrahierten Strings
String string1;                            //Gesamter eingelesener String wird hier gespeichert und im Nachhinein aufgeteilt
String subs1;                              //Extrahierte X-Anfahrtswerte oder U-Referenzwerte werden hier gespeichert.
String subs2;                              //Extrahierte Y-Anfahrtswerte oder V-Referenzwerte werden hier gespeichert.
String subs3;                              //Extrahierte Z-Anfahrtswerte oder W-Referenzwerte werden hier gespeichert.
String subs4;                              //Extrahierte Vorschubwerte werden hier gespeichert.

In einem Arduino Programm wird eine setup-Schleife zum Programmstart ein Mal durchlaufen. Darin werden serielle Datenübertragungsgeschwindigkeit und weitere Vorgaben eingestellt. Zur Sicherheit werden hier eine maximale Vorschubgeschwindigkeit und Achsenbeschleunigung eingestellt.


void setup() {
 // Maximalgeschwindigkeiten der Achsen einstellen in Schritte/Sekunde. Nutzung einer Funktion der AccelStepper Bibliothek.
   Achse_X.setMaxSpeed(10000);
   Achse_Y.setMaxSpeed(10000);
   Achse_Z.setMaxSpeed(10000);
 // Beschleunigungen der Achsen einstellen in Schritte/Sekunde^2. Nutzung einer Funktion der AccelStepper Bibliothek.
   Achse_X.setAcceleration(10000.0);
   Achse_Y.setAcceleration(10000.0);
   Achse_Z.setAcceleration(10000.0); 
 //Baudrate zur Datenübertragung über Serielle Schnittstelle. Notwendig, um seriell zwischen Arduino und PC zu kommunizieren. 
   Serial.begin(9600); 
}

Funktion zum Auslesen der Anfahrtskommandos

Die Funktion erhält einen Zeiger auf das Anfahrtenarray. Zu Beginn wird der gesamte String eingelesen bis ein Zeilenumbruch vorliegt. Die Länge eines Strings ist bekannt. Diese liegt bei insgesamt 20 Zeichen. Da am Anfang des Programms jedoch das erste Zeichen bereits eingelesen wurde, um zu prüfen, ob ein Anfahrs- oder Referenzkommando vorliegt, ist ein gültiger String der Anfahrtskommandos 19 Zeichen lang. Falls ein zu kurzer oder zu langer String vorliegt, handelt es sich um eine ungültige Eingabe und es folgt kein weiteres Einlesen. Im Anschluss wird nach den Indizes der Buchstaben Y, Z und F gesucht und in Variablen gespeichert. Diese dienen dazu, um festzustellen, ob die geforderten Zeichen im String vorliegen. Ist dies nicht der Fall, bleiben die vorherigen Werte dieser Kommandos bestehen und es liegt eine ungültige Eingabe vor. Am Ende der Funktion werden die Zahlenwerte, die zwischen den jeweiligen Buchstabenpositionen liegen extrahiert, in einen Integer umgewandelt und an die jeweilige Arrayposition des Anfahrten-Arrays geschrieben.

In dieser Funktion werden viele Arduino Funktionen genutzt, um mit Strings umzugehen. Unter dem 8. Punkt ist eine gute Dokumentation zu finden: https://www.arduino.cc/en/Tutorial/BuiltInExamples


//Deklaration der Funktion string_Anfahrten_auslesen. Void --> kein Rückgabeparameter. double* Anfahrten --> Zeiger auf Array Anfahrten, um extrahierte Daten darin zu speichern.
void string_Anfahrten_auslesen(double* Anfahrten)
 {
   string1 = Serial.readStringUntil('\n'); //Auslesen und speichern des gesamten eingelesenen Strings. Ende des Strings wird durch \n erkannt. 
   if(string1.length()==19)                //Überprüfung, ob der String die richtige Länge hat, sonst liegt ungültige Eingabe vor.
   {
     //Positionswerte der einzelnen Buchstaben im String werden gesucht
     x_pos=0;                              //X-Position liegt bei 0 im String. X wurde am Programmanfang das erste Zeichen bereits extrahiert zur Entscheidung, ob Referenz- oder Anfahrtsstring.  
     y_pos=string1.indexOf('Y');           //Position des Zeichens Y wird im String gesucht und zwischengespeichert. Falls Buchstabe gefunden wird, liegt anderer Wert als 999 vor.
     z_pos=string1.indexOf('Z');           //Position des Zeichens Z wird im String gesucht und zwischengespeichert. Falls Buchstabe gefunden wird, liegt anderer Wert als 999 vor.
     f_pos=string1.indexOf('F');           //Position des Zeichens F wird im String gesucht und zwischengespeichert. Falls Buchstabe gefunden wird, liegt anderer Wert als 999 vor.

     //Überprüfung, ob der String alle Buchstaben eines Anfahrtskommandos enthält. Falls die Variablen x_pos usw. ihre ursprünglichen Werte(999) bei der vorherigen Suche beibehalten haben
     //also nicht gefunden wurden --> ungültige Eingabe
     if(x_pos!=999 && y_pos!=999 && z_pos!=999 && f_pos!=999)  
     {

       //Extrahieren der Substrings          
       subs1=string1.substring(x_pos, y_pos);       //Zwischen Position des Buchstaben X und Y liegt der Anfahrtswert für die X-Achse.
       subs2=string1.substring(y_pos+1, z_pos);     //Zwischen Position des Buchstaben Y und Z liegt der Anfahrtswert für die Y-Achse.
       subs3=string1.substring(z_pos+1, f_pos);     //Zwischen Position des Buchstaben Z und F liegt der Anfahrtswert für die Z-Achse.
       subs4=string1.substring(f_pos+1);            //Nach der Position des Buchstaben F liegt der Vorschubwert.

       //Umwandlung der Substrings in Integer-Werte und Speichern im Anfahrtenarray.
       Anfahrten[0]=subs1.toInt()*String_Umrechnung;                  //Speichern der X-Absolutkoordinaten und Umrechnung von 1/10 mm in mm
       Anfahrten[1]=subs2.toInt()*String_Umrechnung;                  //Speichern der Y-Absolutkoordinaten und Umrechnung von 1/10 mm in mm
       Anfahrten[2]=subs3.toInt()*String_Umrechnung;                  //Speichern der Z-Absolutkoordinaten und Umrechnung von 1/10 mm in mm
       Anfahrten[3]=subs4.toInt()*String_Umrechnung;                  //Speichern des Vorschubwerts und Umrechnung von 1/10 mm/min in mm/min

       //Auf ursprüngliche Werte setzen, um beim nächsten String erneut prüfen zu können, ob übergebenes Kommando korrekt ist.
       x_pos=999;
       y_pos=999;
       z_pos=999;
       f_pos=999;

     }
     else
     {
       Serial.println("Ungueltige Eingabe");         //Falls Unregelmäßigkeit (falsche String-Länge oder erwartete Buchstaben nicht gefunden), Error Message.
     }
   }
   else
   {
     Serial.println("Ungueltige Eingabe");          //Falls Unregelmäßigkeit (falsche String-Länge oder erwartete Buchstaben nicht gefunden), Error Message.
   }
 }      

Funktion zum Auslesen der Referenzkommandos

Diese Funktion ist äquivalent zu der Auslesefunktion von Anfahrtskommandos mit der Ausnahme, dass hier der String kleiner ist, nach anderen Buchstaben gesucht werden muss und nur drei Zahlenwerte in das Referenz-Array gespeichert werden.

Main Programm

Das Main Programm wird bei dem Arduino in der sog. void loop implementiert. Diese läuft kontinuierlich durch, solange der Arduino mit Strom versorgt wird. Am Anfang des Hauptprogramms wird abgefragt, ob Daten am seriellen Eingang verfügbar sind (Serial.available() > 0). Ist dies der Fall, wird das erste Zeichen eingelesen. Dies wird dazu genutzt, um zu prüfen, ob es sich um ein Anfahrts- oder Referenzkommando handelt. Ist das erste Zeichen ein „U“, liegt ein Referenzkommando vor und die Funktion zum Referenzen auslesen wird aufgerufen. Bei einem „X“ handelt es sich um ein Anfahrtskommando und die Funktion zum Auslesen der Anfahrten wird aufgerufen. Wird ein anderes Zeichen empfangen, liegt eine fehlerhafte Übergabe vor und es wird zum Programmanfang gesprungen. Danach finden die Berechnungen statt, wie bereits im technischen Systementwurf beschrieben. Die Achsengeschwindigkeiten werden mit der Funktion Achse_X.setSpeed(Geschw_X) gesetzt, die Entfernungen mit Achse_X.move(X_Schritte). Die simultane Ansteuerung wird über eine while-Schleife realisiert. Diese wird so lange durchlaufen bis alle Achsen ihre finale Position erreicht haben. Dies wird mit der Bibliotheksfunktion Achse_X.distanceToGo()!= 0 durchgeführt. In der Schleife wird allen Achsen der Befehl übergeben, dass die die eingestellte Geschwindigkeit verfahren sollen (Achse_X.runSpeed()). Danach muss erneut die gewünschte Geschwindigkeit eingestellt werden, da sonst die Geschwindigkeit von der Bibliotheksfunktion vergessen wird.


void loop() {
 if (Serial.available() > 0)                       //Überprüfen, ob Daten am seriellen Port vorhanden, die ausgelesen werden können.
 {

    Serial.println(" Werte empfangen:");           //Anzeige für den Nutzer, dass Daten empfangen werden. Übertragung war erfolgreich
    Zeichen = Serial.read();                       //Erstes Zeichen einlesen, um zu überprüfen, ob Referenzkommando oder Anfahrtskommando oder falsche Übertragung.

    if (Zeichen == 'X')                            //Falls das erstes emfangenes Zeichen X, dann liegen Anfahrtswerte vor.
    {

        string_Anfahrten_auslesen(Anfahrten);      //Funktionsaufruf zum Anfahrten auslesen (s.o.)

        //Ausgabe der Anfahrtswerte zur Kontrolle, ob die Daten richtig extrahiert werden. Wurde für Komponententest genutzt. Keine Relevanz für Programmfunktion.
        Serial.println("Anfahrtswerte:");          //Anzeige, dass empfangene Daten Anfahrtswerte sind 
        Serial.print("X: ");                       //Anzeige, dass folgender Zahlenwert die X-Anfahrtsposition ist 
        Serial.print(Anfahrten[0]);                //X-Anfahrtsposition wird ausgegeben
        Serial.println(" mm");                     //Ausgabe der Einheit des Anfahrtskommandos in mm
        Serial.print("Y: ");                       //Anzeige, dass folgender Zahlenwert die Y-Anfahrtsposition ist 
        Serial.print(Anfahrten[1]);                //Y-Anfahrtsposition wird ausgegeben
        Serial.println(" mm");                     //Ausgabe der Einheit des Anfahrtskommandos in mm
        Serial.print("Z: ");                       //Anzeige, dass folgender Zahlenwert die Z-Anfahrtsposition ist 
        Serial.print(Anfahrten[2]);                //Z-Anfahrtsposition wird ausgegeben
        Serial.println(" mm");                     //Ausgabe der Einheit des Anfahrtskommandos in mm
        Serial.print("F: ");                       //Anzeige, dass folgender Zahlenwert der Vorschubwert ist 
        Serial.print(Anfahrten[3]);                //Vorschubwert wird ausgegeben
        Serial.println(" mm/min");                 //Ausgabe der Einheit des Vorschubwertes in mm/min

        //Inkrementalwerte berechnen durch Differenz zwischen Anfahrts- und Referenzkommando. Und Umrechnung von mm in Schritte mit Hilfe der Variable Schrittverhaeltnis.
        X_Schritte=(Anfahrten[0]-Referenzen[0])/Schrittverhaeltnis;  
        Y_Schritte=(Anfahrten[1]-Referenzen[1])/Schrittverhaeltnis;
        Z_Schritte=(Anfahrten[2]-Referenzen[2])/Schrittverhaeltnis;

        //Neue absolute Referenzwerte sind absolute Anfahrtswerte, um bei nächster Fahrt erneut einen inkrementalen Verfahrweg zu berechnen.
        Referenzen[0]=Anfahrten[0];                //Werte für die X-Achse
        Referenzen[1]=Anfahrten[1];                //Werte für die Y-Achse
        Referenzen[2]=Anfahrten[2];                //Werte für die Z-Achse

        //Berechnung der relativen Vorschubgeschwindigkeiten für die jeweilige Achse
        F_Geschw=Anfahrten[3]/(Schrittverhaeltnis*60);                     //Vorschubgeschwindigkeit umrechnen von mm/min in Schritte/Sekunde (Schritte/Sekunde von AccelStepper Bib vorgegeben)
        c=sqrt(pow(X_Schritte, 2)+pow(Y_Schritte, 2)+pow(Z_Schritte, 2));  //Hypotenuse wird mit dreidimensionalen Pythagoras berechnen. Erklärung im technischen Systementwurf.
        Speed_X=round((X_Schritte/c)*F_Geschw);                            //Relative Geschwindigkeit der X-Achse berechnen im Verhältnis zum Verfahrweg.
        Speed_Y=round((Y_Schritte/c)*F_Geschw);                            //Relative Geschwindigkeit der Y-Achse berechnen im Verhältnis zum Verfahrweg.
        Speed_Z=round((Z_Schritte/c)*F_Geschw);                            //Relative Geschwindigkeit der Z-Achse berechnen im Verhältnis zum Verfahrweg.
            
        //Ausgabe der Schritte und Geschwindigkeiten nach Umrechnung zur Kontrolle. Keine Relevanz für Programmfunktion.
        Serial.println("Schrittwerte:");           //Anzeige, dass es sich um umgerechnete Werte handelt, die später an Schrittmotoren übergeben werden können.
        Serial.print("X: ");                       //Anzeige, dass folgender Zahlenwert die Anzahl der zu fahrenden Schritte in X-Richtung ist
        Serial.print(X_Schritte);                  //Schrittanzahl X-Richtung wird ausgegeben
        Serial.println(" Schritte");               //Ausgabe der Einheit des Verfahrweges in Schritten
        Serial.print("Y: ");                       //Anzeige, dass folgender Zahlenwert die Anzahl der zu fahrenden Schritte in Y-Richtung ist
        Serial.print(Y_Schritte);                  //Schrittanzahl Y-Richtung wird ausgegeben
        Serial.println(" Schritte");               //Ausgabe der Einheit des Verfahrweges in Schritten
        Serial.print("Z: ");                       //Anzeige, dass folgender Zahlenwert die Anzahl der zu fahrenden Schritte in Z-Richtung ist
        Serial.print(Z_Schritte);                  //Schrittanzahl Z-Richtung wird ausgegeben
        Serial.println(" Schritte");               //Ausgabe der Einheit des Verfahrweges in Schritten
        Serial.print("FX: ");                      //Anzeige, dass folgender Zahlenwert die abgeleitete Geschwindigkeit der X-Achse ist
        Serial.print(Speed_X);                     //Geschwindigkeit der X-Achse wird ausgegeben
        Serial.println(" Schritte/sek");           //Ausgabe der Einheit der Achsengeschwindigkeit in Schritte/s
        Serial.print("FY: ");                      //Anzeige, dass folgender Zahlenwert die abgeleitete Geschwindigkeit der Y-Achse ist
        Serial.print(Speed_Y);                     //Geschwindigkeit der Y-Achse wird ausgegeben
        Serial.println(" Schritte/sek");           //Ausgabe der Einheit der Achsengeschwindigkeit in Schritte/s
        Serial.print("FZ: ");                      //Anzeige, dass folgender Zahlenwert die abgeleitete Geschwindigkeit der Z-Achse ist
        Serial.print(Speed_Z);                     //Geschwindigkeit der Z-Achse wird ausgegeben
        Serial.println(" Schritte/sek");           //Ausgabe der Einheit der Achsengeschwindigkeit in Schritte/s

        //Geschwindigkeiten und Verfahrwege an Treiber schicken
        Achse_X.move(X_Schritte);                  //Schrittmotortreiber der X-Achse wird Anzahl der zu verfahrenden Schritte übergeben. Nutzen einer AccelStepper-Funktion
        Achse_Y.move(Y_Schritte);                  //Schrittmotortreiber der Y-Achse wird Anzahl der zu verfahrenden Schritte übergeben. Nutzen einer AccelStepper-Funktion
        Achse_Z.move(Z_Schritte);                  //Schrittmotortreiber der Z-Achse wird Anzahl der zu verfahrenden Schritte übergeben. Nutzen einer AccelStepper-Funktion
        Achse_X.setSpeed(Speed_X);                 //Schrittmotortreiber der X-Achse wird Vorschubgeschwindigkeit [Schritte/s] übergeben. Nutzen einer AccelStepper-Funktion
        Achse_Y.setSpeed(Speed_Y);                 //Schrittmotortreiber der Y-Achse wird Vorschubgeschwindigkeit [Schritte/s] übergeben. Nutzen einer AccelStepper-Funktion
        Achse_Z.setSpeed(Speed_Z);                 //Schrittmotortreiber der Z-Achse wird Vorschubgeschwindigkeit [Schritte/s] übergeben. Nutzen einer AccelStepper-Funktion

        //Die Schleife läuft so lange durch, bis alle Achsen die übergebenen Schritte verfahren sind. Nutzen der AccelStepper-Funktion Achse.distanceToGo(). In der Funktion wird bei jedem Durchlauf erneut die 
        //Geschwindigkeit der Achsen übergeben und der Befehl gegeben, zu verfahren. Dies ist eine Vorgabe der AccelStepper Bib.
        while(Achse_X.distanceToGo()!= 0 || Achse_Y.distanceToGo()!= 0 || Achse_Z.distanceToGo()!= 0) 
       {

           Achse_X.runSpeed();                      //Befehl an X-Achse zu verfahren
           Achse_X.setSpeed(Speed_X);               //Erneutes Einstellen der Vorschubgeschwindigkeit der X-Achse

           if(Achse_Y.distanceToGo() != 0)          //Prüfen, ob die Y-Achse schon die benötigte Distanz zurückgelegt hat, falls nein weiter Verfahen
           {
           Achse_Y.runSpeed();                      //Befehl an Y-Achse zu verfahren 
           Achse_Y.setSpeed(Speed_Y);               //Erneutes Einstellen der Vorschubgeschwindigkeit der Y-Achse         
           }

           if(Achse_Z.distanceToGo() != 0)          //Prüfen, ob die Z-Achse schon die benötigte Distanz zurückgelegt hat, falls nein weiter Verfahen
           {
           Achse_Z.runSpeed();                      //Befehl an Z-Achse zu verfahren 
           Achse_Z.setSpeed(Speed_Z);               //Erneutes Einstellen der Vorschubgeschwindigkeit der Z-Achse         
           }
         }
       }

       else
       {

         if(Zeichen == 'U')                           //Falls U --> Referenzkommando auslesen
         {

           string_Referenzen_auslesen(Referenzen);    //Funktion Referenzen auslesen aufrufen

           //Ausgabe der Referenzwerte zur Kontrolle des Einlesens. Keine Relevanz für Programmfunktion.
           Serial.println("Referenz:");               //Anzeige, dass empfangene Daten Referenzwerte sind 
           Serial.print("U: ");                       //Anzeige, dass folgender Zahlenwert die X-Referenzwert ist 
           Serial.print(Referenzen[0]);               //X-Referenzwert wird ausgegeben
           Serial.println(" mm");                     //Ausgabe der Einheit des Referenzwerts in mm
           Serial.print("V: ");                       //Anzeige, dass folgender Zahlenwert die Y-Referenzwert ist
           Serial.print(Referenzen[1]);               //Y-Referenzwert wird ausgegeben
           Serial.println(" mm");                     //Ausgabe der Einheit des Referenzwerts in mm
           Serial.print("W: ");                       //Anzeige, dass folgender Zahlenwert die Z-Referenzwert ist
           Serial.print(Referenzen[2]);               //Z-Referenzwert wird ausgegeben
           Serial.println(" mm");                     //Ausgabe der Einheit des Referenzwerts in mm     
         }

        else                                          //Falls weder Anfahrts noch Referenzkommando vorliegt --> Error Message
        {
           Serial.println("Ungueltige Eingabe");      //Ausgabe der Error Message
        }
       }
    }
}

Test des Systems

Die Funktionsüberprüfung unterteilt sich in vier Teile. Im Komponententest werden die einzelnen Programmteile einzeln überprüft. Der Integrationstest zielt darauf ab, ob der Zusammenbau funktioniert. Der Systemtest soll gewährleisten, dass das gesamte System seine Funktion erfüllt. Der Abnahmetest ist die Kundenübergabe, in denen der Kunde das Produkt auf die gewünschten Funktionen überprüft.

Die Ergebnisse der einzelnen Tests wurden in Excel-Listen zusammengefasst, um einen Nachweis darüber zu haben, dass das System wie gewünscht funktioniert und Verbesserungen aufzudecken.

Komponententest

Hier wurden die Funktionen zum Anfahrten und Referenzen auslesen sowie die Umrechnungen überprüft. Für die Auslesefunktionen wurden verschiedene Teststrings übergeben, um sicherzustellen, dass nur korrekt gesendete Strings ausgewertet werden und dass die Übergabewerte wie gewünscht gespeichert werden. Die Berechnungen wurden nach erfolgreichem Test der Einlesefunktionen getestet. Auch hier wurden verschiedene Kommandos gesendet, die berechneten Werte in einer Konsole ausgegeben und mit manuell berechneten Ergebnissen verglichen.

Hier ist das Protokoll des Komponententests zu finden: Datei:Komponententest.xlsx

Integrationstest

Ein erster Zusammenbau wurde an einer einzelnen Linearachse getestet. Dabei wurde zunächst nur geprüft, ob eine Achse in die gewünschten Richtungen verfährt und ob sie die korrekte Distanz zurücklegt. Auch hier wurden diverse Strings übergeben und über eine Messung des zurückgelegten Weges verifiziert, dass die Achse korrekt verfährt. Außerdem wurde bei verschiedenen Geschwindigkeiten eine saubere, ruckelfreie Fahrt der Achse beobachtet.

Hier ist das Protokoll des Datei:Integrationstests zu finden: Datei:Integrationstest.xlsx

Systemtest

Beim Systemtest wurde die Ansteuerung aller Achsen an der CNC-Fräse getestet. Hier wurde am Anfang für alle drei Achsen die korrekte Verfahrrichtung und Strecke überprüft. Daraufhin wurde über eine Weg-Zeit-Messung die Verfahrgeschwindigkeit getestet. Dabei ist aufgefallen, dass obwohl die richtig umgerechnete Geschwindigkeit an die Achsen gesendet wurde, ein zu langsames Verfahren stattfindet. Dieses Problem konnte nicht gelöst werden. Im nächsten Schritt wurde das simultane Verfahren von zwei und drei Achsen geprüft. Für das Verfahren der X- und Y-Achse wurde ein Stift an dem Fräskopf befestigt und ein Blatt Papier auf dem Maschinentisch befestigt. Das Aufzeichnen der Schräge und anschließende Vermessen hat gezeigt, dass verschiedene Fahrten, in denen die Achsen unterschiedlich schnell verfahren müssen, mit einer guten Genauigkeit vollzogen werden.

Hier ist das Protokoll des Datei:Integrationstests zu finden: Datei:Systemtest Protokoll.pdf

Bewertung des Arduinos bzw. der Arduino IDE für die Anwendung

Vorteile Nachteile
Einfache, übersichtliche Programmierumgebung Kein Debuggen möglich
Vertrautes System durch Elektrotechnik Praktikum Ansteuerung der CNC-Achsen simultan kompliziert
C-ähnliche Programmiersprache Bibliothek zur Ansteuerung der Achsen schlecht dokumentiert
Spannungsoutput der digitalen Pins passend zu Schrittmotortreibern Steuerung ausschließlich über Strings; Joystick denkbar
Einlesen des Strings sehr simpel
Kompakt; einfache Anbindung an die CNC-Fräse möglich
Viele vorimplementierte Bibliotheken

Zusammenfassung und Ausblick

Im Rahmen dieses Projektes konnte die 3D CNC Bearbeitungsmaschine erfolgreich mit einem Arduino Mega 2560 angesteuert werden. Durch die konsequente Anwendung des V-Modells konnten alle Meilensteine fristgerecht fertig gestellt werden.

Über die RS232-Schnittstelle kann der Arduino Strings einlesen. Anschließend wird zwischen Referenz- und Anfahrkommando unterschieden. Die Werte für Position und Vorschub werden ebenfalls aus dem String extrahiert. Die absoluten Positionswerte werden in inkrementelle Verfahrwege umgerechnet. In Abhängigkeit der Verfahrwege und der Vorschubgeschwindigkeit werden relative Geschwindigkeiten für alle drei Achsen durch den dreidimensionalen Satz des Pythagoras berechnet. Anschließend werden die Achsen durch Schrittmotortreiber angesteuert. Dazu wird jedem Schrittmotortreiber die Anzahl der Schritte und die Richtung übergeben.

Nach der Entwicklungsphase wurde gemäß des V-Modells vom Komponententest bis hin zum Abnahmetest das Projekt schrittweise getestet und entsprechende protokolliert.

Nach Abschluss des Projektes wird eine vollständig funktionsfähige Baugruppe hinterlassen. Die Funktionsfähigkeit zeigen die jeweils dokumentierten Tests. Für die Komponenten Arduino-Mega2560, die 25-polige D-Sub Buchse, die Platine und die Verdrahtung wurde ein Gehäuse konstruiert und mithilfe des additiven Fertigungsverfahrens Selektives Lasersintern gefertigt.

Für eine eventuelle nachfolgende Gruppe wäre ein Test des Gesamtsystems durch den Matlab-Algorithmus durchzuführen. Des Weiteren wäre die Integration von Steuerungstasten für jede Achse oder eines Joysticks in den Gehäusedeckel eine sinnvolle Erweiterung, um die gesamte CNC-Fräse auch manuell über den Arduino steuern zu können.

Weblinks und Literatur

  1. Signale des Schrittmotors: https://knowledge.ni.com/KnowledgeArticleDetails?id=kA00Z0000019ZTySAM&l=de-DE (Aufgerufen am 07.01.2020)
  2. Absolute und inkrementale Bemaßung: http://www.helmancnc.com/hust-cnc-mill-g90-absolute-coordinate-g91-incremental-coordinate-example/ (Aufgerufen am 07.01.2020)
  3. 3D-Pythagoras: http://www.pythagorasandthat.co.uk/3d-pythagoras (Aufgerufen am 07.01.2020)

Tutorials zum Einstieg mit einem Arduino: Arduino Tutorials

Arduino Bibliothek zur Ansteuerung von Schrittmotoren: AccelStepper-Bibliothek

Funktionen zur seriellen Kommunikation mit einem Arduino: Serielle Kommunikation Arduino

Korrektur/Rückmeldungen

Zurück zum übergeordneten Projekt: 3-D-Bearbeitungsmaschine (Projekt des Schwerpunkts GPE im Studiengang MTR)