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.
| 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.
| 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.
| 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.
| 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; |
| 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 |