4 Zeitlicher Arbeitsablauf

4.6 Auswerte-Funktionen

Die Auswerte-Funktionen sind das Herzstück des Programms. Es geht darum für jedes Protokoll eine eigene Auswerte-Funktion zu schreiben. Diese sollen die von RapidForm2004 kommenden Strings verstehen können und in einen, für die vorhandene Schrittmotorkarte, verständlichen Befehl übersetzen können. Die Funktionen sollen weiterhin prüfen, ob der Befehl von der Schrittmotorkarte erkannt wurde und den Status der Schrittmotorkarte zurück an RapidForm2004 melden.
Alle bisherigen Arbeitsschritte hatten zum Ziel, die Kommunikation zwischen RapidForm2004 und der ersten Schrittmotorkarte zu ermöglichen. Nun fehlt nur noch der Teil des Programms der die ankommenden Befehle auswertet und in verständlicher Form an die Schrittmotorkarte weitergibt. Im folgenden Kapitel wird dieser Ablauf nun exemplarisch für den Befehlssatz eines Isel-Motors erklärt.

4.6.1 Auswerte-Funktion für Isel-Motoren

Wird der Befehl @01 empfangen, übergibt die in Kapitel 4.5.1.1 beschriebene Funktion, den String an die Auswerte-Funktion switch_Isel(str_rx). Der Ablauf dieser Funktion ist ähnlich aufgebaut wie bei der Kommunikation mit der Schrittmotorkarte (Kapitel 4.3) und bei der automatischen Auswahl des Befehlssatzes (Kapitel 4.5.1.1. In der Funktion switch_Isel(str_rx) sind in dem Array pOptions alle benötigten Befehle des Isel-Befehlssatzes hinterlegt. Mit der aus Kapitel 4.3.3 bekannten Funktion FindStringInArray(str_rx, pOptions) wird str_rx gegen diese Befehle geprüft. Wird der Befehl im Array gefunden gibt die Funktion FindStringInArray() die Position des Strings im Array zurück. Mittels einer switch-case-Struktur lässt sich nun so für jeden Befehl ein entsprechender Ablauf ausführen. Die einzelnen Abläufe werden übersichtlich in den folgenden Kapiteln beschrieben.

Listing 14: Übersetzungs Logik für einen Isel-Motor
1 // Uebersetzung Isel
2 void        switch_Isel                        (char * str_rx) {
3         const char* pOptions[] = {
4                         "XXXXXXX",      // 0 - Reserve
5                         "!CLS",         // 1 - LC-Display loeschen
6                         "Test",         // 2 - Test
7                         "@01",          // 3 - Achse auswaehlen
8                         "@0R",          // 4 - Status abfrage
9                         "@0M",          // 5 - Gehe zu Position
10                         0 };
11         switch (FindStringInArray(str_rx, pOptions, 3))

4.6.1.1 Initialisierung

Für den String @01 wird case 3 ausgeführt. Dieser Codeblock zeigt die Meldung Init auf dem Display an und sendet den erwarteten Befehl an RapidForm2004.

Listing 15: case 3: Initialisierung
1 case 3:                     // 3 - Achse auswaehlen (Initialisierung)
2         ms_spin(10);
3         lcd_puts("Init");
4         uart_put_string("0\r\n", D_RapidForm);
5         break;

4.6.1.2 Statusabfrage

Wird der String @0R empfangen, wird der Codeblock case 4 ausgeführt. Auf dem LC-Display wird Satusabfrage: ausgegeben. Danach wird der entsprechende Befehl für eine Statusabfrage an die Schrittmotorkarte gesendet. Nach einer kurzen Pause von 50ms, um die Verarbeitung auf der Schrittmotorkarte zu gewährleisten, wird mit einer if-Anweisung geprüft ob sich Daten im Schrittmotorkarten-Empfangsregister befinden. Sprich, die Schrittmotorkarte reagiert hat. Ist dies der Fall, wird der Ablauf, bekannt aus Kapitel 4.3, durchlaufen. Während diesem Ablauf wird die entsprechende Antwort der Schrittmotorkarte auf dem LC-Display ausgegeben. In einer weiteren if-Anweisung wird überprüft ob der angekommene String erfolgreich war. Wenn ja, wird dies an RapidForm2004 gemeldet. Andernfalls zeigt das Display Fehlgeschlagen an und sendet eine 1 an RapidForm2004.

Listing 16: case 4: Statusabfrage
1 case 4:                     // 4 - Status abfrage
2         lcd_puts("Statusabfrage:     \n");
3         uart_put_string("A\n", D_Stepper);      // Statusabfrage an Stepper senden
4         ms_spin(50);                                   // Verarbeitungszeit gewaehren
5         if ((UCSR1A & (1 << RXC1)))                 // Wenn ein Zeichen empfangen wurde
6                 uart_rx(D_Stepper);                     // Zeichen auslesen
7         if (!strcmp(str_rx,"0#"))                     // Empfangenes Zeichen ueberpruefen
8                 uart_put_string("0\r\n", D_RapidForm);    // Antwort Ok an RF melden
9         else {
10                 lcd_puts("Fehlgeschlagen     \n");         // Fehler auf Display anzeigen
11                 uart_put_string("1\r\n", D_RapidForm); // Fehler an RapidForm melden
12         }
13         break;

4.6.1.3 Rotation

Der Codeblock von case 5 ist für die Rotation verantwortlich. Es werden je ein String für die Endposition und für den Winkel mit Stringterminierungszeichen vorbelegt. Diese werden an die Funktion String_zerlegen_Isel(str_rx, Position, Winkel) (Codelisting 18) übergeben. Dort wird der String in die Bestandteile Achse, Rotationsbefehl, Position/Anzahl der Schritte und Geschwindigkeit zerlegt. Von diesen ist nur die Anzahl der Schritte relevant. Da die Anzahl der Schritte für den Schrittmotor angepasst werden muss, wird der String in eine Zahl umgewandelt und mit einem entsprechenden Faktor multipliziert. Zugunsten der Rechenzeit wird nicht exakt gerechnet und die Division im Faktor mit 1024 durchgeführt. Diese wird beim Kompilieren durch eine Bitverschiebung ersetzt. Dies spart mehrere Sekunden Rechenzeit und die Abweichung der Schritte beträgt nur maximal 3 Schritte. Die berechnete Anzahl der Schritte wird anschließend wieder als String gespeichert. Dieser wird dann an den String für den Rotationsbefehl der Schrittmotorkarte angehängt. Der neue String wird auf dem Display ausgegeben und an die Schrittmotorsteuerung gesendet. Die Antwort der Schrittmotorsteuerung wird ausgelesen und anschließend wird in einer while-Schleife so lange der Status des Motors abgefragt bis dieser keine Bewegung mehr meldet. Die Position ist damit erreicht und es wird der erwartete Befehl an RapidForm2004 gesendet.

Listing 17: case 5: Rotation
1 case 5:                     // 5 - Gehe zu Position MX , +600
2         ms_spin(10);
3         char Position[33], Winkel[6];
4         memset(Position, \0’, 33); // Strign 0 Terminiert vorbelegen
5         memset(Winkel, \0’, 6);    // String 0 Terminiert vorbelegen
6         String_zerlegen_Isel(str_rx, Position, Winkel); // String auswerten
7         // String fuer Stepper vorbereiten
8         char Move_To[40];
9         memset(Move_To,  \0’, 40);
10         Move_To[0] = M’;
11         Move_To[1] = A’;
12         Move_To[2] =  ’;
13         Move_To[3] = \0’;
14         strcat(Move_To, Position);
15         strcat(Move_To, "\n");
16         lcd_puts("Pos:");
17         lcd_puts(Move_To);
18         // String an Stepper senden
19         uart_put_string(Move_To, D_Stepper);
20         ms_spin(50);
21         if ((UCSR1A & (1 << RXC1)))
22                 uart_rx(D_Stepper);     // Antwort des Stepper auslesen
23         else {
24                 break; // Bei Fehler abbrechen
25         }
26         // Status des Stepper Abfragen
27         uart_put_string("A\n", D_Stepper);
28         ms_spin(50);
29         // Antwort des Stepper Abfragen
30         if ((UCSR1A & (1 << RXC1)))
31                 uart_rx(D_Stepper);
32         else {
33                 lcd_puts("Keine Bewegung!\n");
34         }
35         // So lange der Stepper Bewegung meldet erneut Statusabfrage
36         while (!strcmp(str_rx,"1#")){
37                 // Statusabfrage an Stepper
38                 uart_put_string("A\n", D_Stepper);
39                 ms_spin(50);
40                 // Statusabfrage auslesen und auswerten
41                 if ((UCSR1A & (1 << RXC1))){
42                         uart_rx(D_Stepper);
43                         lcd_clrscr();
44                         lcd_puts("Gehe zu Winkel: ");
45                         lcd_puts(Winkel);
46                         lcd_puts("\n");
47                 }
48                 else {
49                         lcd_puts("Keine Antwort\n");
50                 }
51                 wdt_reset();
52         }
53         lcd_puts("Winkel: ");
54         lcd_puts(Winkel);
55         lcd_puts(" Erreicht\n");
56         // Bewegung abgeschlossen an RapidForm melden
57         uart_put_string("0\r\n", D_RapidForm);
58         break;
Listing 18: Funktion: string zerlegen Isel()
1 void        String_zerlegen_Isel(char * str_rx, char * Position, char * Winkel) {
2         //0M5200, +600
3         //Achse M Position, +Geschwindigkeit
4         char * Achse="0";
5         Achse[0] = str_rx[1];      // Achse setzen
6         Achse[1] = \0’;
7         // Ausgeben welche Achse gewaehlt wurde
8         if(atoi(Achse)==0){
9                 lcd_puts("Achse: ");
10                 lcd_puts(Achse);
11                 lcd_puts(" (Rotation)\n");
12         }
13         if(atoi(Achse)==1){
14                 lcd_puts("Achse: ");
15                 lcd_puts(Achse);
16                 lcd_puts(" (Hoehe)   \n");
17         }
18         // Anzahl der Schritte aus dem String auslesen
19         char c;
20         int i = 0;
21         do {
22                 c = str_rx[i + 3];
23                 if (c != ,’) {
24                         Position[i] = c;
25                         i++;
26                 }
27         } while (i < 20 && c != \0 && c != ,’);
28         Position[i] = \0’; // String 0 Terminieren
29         int32_t z;
30         int32_t y;
31         z = atol(Position);  // String in Zahl(long) umwandeln
32         y = z / 7200;             // Berechnung des Winkel
33         z = (z * 71111)  /1024;   // Berechnung der Schritte
34         ltoa(y, Winkel,            10 ); // Winekl in String umwandeln
35         ltoa(z, Position,    10 ); // Schritte in String umwandeln