Anforderungen an das Skript und entsprechende Erweiterungen
erweiterungen_stud.zip - Download der folgenden C++ - Quelltexte.Parameter setzen und im Skript ansprechen
|
#include<iostream> #define PARAM_ANZ 5 #define PUFFER_GROESSE 30 using namespace std; class Befehle { public: void tudies() { cout<<"dies"<<endl; } void tudas() { cout<<"das"<<endl; } void tujenes() { cout<<"jenes"<<endl; } }; int main() { int param[PARAM_ANZ]={0,0,0,0,0}; //Parameter und Variablen, die dem Skript zur Verfügung stehen sollen int hilf; bool minus; char c; Befehle befehle; void (Befehle::*zeiger[3])(void) = { &Befehle::tudies, &Befehle::tudas, &Befehle::tujenes, }; char parameter_uebergabe[] = "-5,+37,+16000, $%&§ -23, +12,;"; //Teil 1 der späteren Kommunikation mit der Station: //Übrtragen der Parameter über Funk als Text, //Umwandlung in Integer-Werte und Übertragung auf das Array param: int i=0; int k=0; c = parameter_uebergabe[i]; while(c!=';' && c!='\0' && k<PARAM_ANZ) { if(c=='-') { minus=true; hilf=0; } else if(c=='+') { minus=false; hilf=0; } else if(c>='0' && c<='9') { hilf*=10; hilf+=c-48; } else if(c==',') { if(minus==true) hilf = -hilf; param[k]=hilf; k++; } i++; c = parameter_uebergabe[i]; } //Zur Kontrolle die gespeicherten Parameter ausgeben: for(int i=0;i<PARAM_ANZ;i++) cout<<"Parameter Nr."<<i<<":"<<param[i]<<endl; //Teil 2 der späteren Kommunikation mit der Station: //Übertragen des Skriptes und Ablauf des Skriptes. //(Bisher können die Variablen nicht mit dem Skript direkt verarbeitet werden.) char skript[PUFFER_GROESSE] = "ABBCCABabcd;"; i=0; c = skript[i]; while(c!=';' && c!='\0' && i<PUFFER_GROESSE) { if(c>='A' && c<='Z') //...dann ist es ein Funktionsaufruf (befehle.*(zeiger[c-'A']))(); else if(c>='a' && c<='z') //...dann ist es ein Parameter cout<<"Parameter Nr."<<(c-'a')<<":"<<param[c-'a']<<endl; c=skript[i]; i++; } }
Code 0-1: skripterweiterung01_parameter.cpp - Einführung von Parametern.
Übergabeparameter und Rückgabewerte bei Funktionen
|
#include<iostream> #define PARAM_ANZ 5 #define PUFFER_GROESSE 30 using namespace std; class Befehle { public: void tudies(int* y, int* a, int* b) //A { cout<<"dies: y=a+b"<<endl; *y = *a + *b; } void tudas(int* y, int* a, int* b) //B { cout<<"das: y[a]=b"<<endl; y+=*a; *y = *b; } void tujenes(int* y, int* a, int* b) //C - Hier werden a und b nicht benötigt. { cout<<"jenes: y=0"<<endl; *y=0; } }; int main() { int param[PARAM_ANZ]={0,0,0,0,0}; //Parameter und Variablen, die dem Skript zur Verfügung stehen sollen int hilf; bool minus; char c,c1,c2,c3,c4,c5; Befehle befehle; void (Befehle::*zeiger[3])(int*,int*,int*) = { &Befehle::tudies, &Befehle::tudas, &Befehle::tujenes, }; // a b c d e char parameter_uebergabe[] = "-5,+2,+4, $%&§ +5, +3,;"; //Teil 1 der späteren Kommunikation mit der Station: //Übrtragen der Parameter über Funk als Text, //Umwandlung in Integer-Werte und Übertragung auf das Array param: int i=0; int k=0; c = parameter_uebergabe[i]; while(c!=';' && c!='\0' && k<PARAM_ANZ) { if(c=='-') { minus=true; hilf=0; } else if(c=='+') { minus=false; hilf=0; } else if(c>='0' && c<='9') { hilf*=10; hilf+=c-48; } else if(c==',') { if(minus==true) hilf = -hilf; param[k]=hilf; k++; } i++; c = parameter_uebergabe[i]; } //Zur Kontrolle die gespeicherten Parameter ausgeben: for(int i=0;i<PARAM_ANZ;i++) cout<<"Parameter Nr."<<i<<":"<<param[i]<<endl; //Folgende Operationen sollen durchgeführt werden: //param[3]=0 (d=0) //param[3]+=param[4] (d=d+e) //param[param[1]] = param[4] (,also c=e) char skript[PUFFER_GROESSE] = "CdeeeAddeeBabee;"; i=0; c1=skript[i]; while(c1!=';' && c1!='\0' && i<PUFFER_GROESSE) { c2=skript[i+1]; c3=skript[i+2]; c4=skript[i+3]; c5=skript[i+4]; if(param[c5-'a']>0) { (befehle.*(zeiger[c1-'A']))( ¶m[c2-'a'], ¶m[c3-'a'], ¶m[c4-'a'] ); //Testweise alle Parameter nach Ausführen des Befehls anzeigen: cout<<"Parameterbelegung nach "<<i/4<<". Befehl:"<<endl; for(int k=0;k<PARAM_ANZ;k++) cout<<param[k]<<" "; cout<<endl; } i+=5; c1=skript[i]; } }
Code 0-2: skripterweiterung02_uebergabeparameter.cpp - Verarbeitung von Parametern
Elementare Rechenoperationen und Ansprechen von Array-Elementen über einen Index
|
#include<iostream> #define PARAM_ANZ 20 #define PUFFER_GROESSE 300 #define FUNK_ANZ 13 using namespace std; int dummy_i = -1; int dummy_k = -1; int dummy_pwm_antrieb = 0; int dummy_pwm_servo = 0; //Um eine bessere Übersicht zu erhalten, werden die Methoden der Klasse "Befehle" //zunächst nur als Prototypen hingeschrieben und erst hinter der Klasse implementiert. class Befehle { private: char skript[PUFFER_GROESSE]; int param[PARAM_ANZ]; void (Befehle::*zeiger[FUNK_ANZ])(int*,int*,int*); int anzahl_befehle; int befehls_zaehler; public: Befehle() { zeiger[0] = &Befehle::A_Null; zeiger[1] = &Befehle::B_Ink; zeiger[2] = &Befehle::C_Dek; zeiger[3] = &Befehle::D_Plus; zeiger[4] = &Befehle::E_Minus; zeiger[5] = &Befehle::F_Mal; zeiger[6] = &Befehle::G_Durch; zeiger[7] = &Befehle::H_Mod; zeiger[8] = &Befehle::I_Array; zeiger[9] = &Befehle::J_Antrieb; zeiger[10] = &Befehle::K_Servo; zeiger[11] = &Befehle::L_Sensor; zeiger[12] = &Befehle::M_Om4; // (Befehle::Befehle::*zeiger[FUNK_ANZ])(int*,int*,int*) } //Funktionen, die elementare Operationen umsetzen: void A_Null(int* y, int* a, int* b); //y=0 void B_Ink(int* y, int* a, int* b); //y++ void C_Dek(int* y, int* a, int* b); //y-- void D_Plus(int* y, int* a, int* b); //y=a+b void E_Minus(int* y, int* a, int* b); //y=a-b void F_Mal(int* y, int* a, int* b); //y=a*b void G_Durch(int* y, int* a, int* b); //y=a/b void H_Mod(int* y, int* a, int* b); //y=a%b //Funktion, um Folgen von Arrayelementen verarbeiten zu können: void I_Array(int* y, int* a, int* b); //arr=Adresse von y, arr[a]=arr[b] //Funktionen, die den Zugriff auf die COACH-Peripherie erlauben: void J_Antrieb(int* y, int* a, int* b); //PWM_Antrieb = y (+/-1023) void K_Servo(int* y, int* a, int* b); //PWM_Servo = y (+/-36) void L_Sensor(int* y, int* a, int* b); //y=Distanz [mm] void M_Om4(int* y, int* a, int* b); //y=omega_viertel (Wert muß durch vier geteilt werden, um Omega zu erhalten.) void uebertrageSkript(char* text) { int i=0; while(text[i]!=';') { if(i%5==0) skript[i] = text[i]-'A'; else skript[i] = text[i]-'a'; i++; } anzahl_befehle = i/5; befehls_zaehler = 0; } void uebertrageParameter(char* parameter_uebergabe) { int i=0; int k=0; char c = parameter_uebergabe[i]; bool minus=false; int hilf=0; while(c!=';' && c!='\0' && k<PARAM_ANZ) { if(c=='-') { minus=true; hilf=0; } else if(c=='+') { minus=false; hilf=0; } else if(c>='0' && c<='9') { hilf*=10; hilf+=c-48; } else if(c==',') { if(minus==true) hilf = -hilf; param[k]=hilf; k++; } i++; c = parameter_uebergabe[i]; } } void zeigeParameter() { cout<<"Parameter:"<<endl; for(int i=0;i<PARAM_ANZ;i++) cout<<param[i]<<" "; cout<<endl; } void bearbeiteNaechstenBefehl() { if(param[ skript[befehls_zaehler*5+4] ] > 0) (this->*(zeiger[skript[befehls_zaehler*5]]))( ¶m[skript[befehls_zaehler*5+1]], ¶m[skript[befehls_zaehler*5+2]], ¶m[skript[befehls_zaehler*5+3]] ); befehls_zaehler++; befehls_zaehler%=anzahl_befehle; } }; //Funktionen, die elementare Operationen umsetzen: void Befehle::A_Null(int* y, int* a, int* b) //y=0 { *y=0; } void Befehle::B_Ink(int* y, int* a, int* b) //y++ { (*y)++; } void Befehle::C_Dek(int* y, int* a, int* b) //y-- { (*y)--; } void Befehle::D_Plus(int* y, int* a, int* b) //y=a+b { *y=*a+*b; } void Befehle::E_Minus(int* y, int* a, int* b) //y=a-b { *y=*a-*b; } void Befehle::F_Mal(int* y, int* a, int* b) //y=a*b { *y=*a**b; } void Befehle::G_Durch(int* y, int* a, int* b) //y=a/b { *y=*a/ *b; } void Befehle::H_Mod(int* y, int* a, int* b) //y=a%b { *y=*a%*b; } //Funktion, um Folgen von Arrayelementen verarbeiten zu können: void Befehle::I_Array(int* y, int* a, int* b) //arr=Adresse von y, arr[a]=arr[b] { a = y + *a; b = y + *b; *a = *b; } //Funktionen, die den Zugriff auf die COACH-Peripherie erlauben: void Befehle::J_Antrieb(int* y, int* a, int* b) //PWM_Antrieb = y (+/-1023) { dummy_pwm_antrieb = *y; cout<<"pwm_antrieb="<<dummy_pwm_antrieb<<endl; } void Befehle::K_Servo(int* y, int* a, int* b) //PWM_Servo = y (+/-36) { dummy_pwm_servo = *y; cout<<"pwm_servo="<<dummy_pwm_servo<<endl; } void Befehle::L_Sensor(int* y, int* a, int* b) //y=Distanz [mm] { int werte[] = {200,100,300,150,155,120,12,0,30,60}; //10 Zufallswerte dummy_i++; *y = werte[dummy_i%10]; cout<<"Sensor liefert Distanz="<<*y<<endl; } void Befehle::M_Om4(int* y, int* a, int* b) //y=omega_viertel (Wert muß durch vier geteilt werden, um Omega zu erhalten.) { int werte[] = {4,8,10,15,20,18,15,23,30,29}; //10 Zufallswerte dummy_k++; *y = werte[dummy_k%10]; cout<<"Drehgeber liefert om_viertel="<<*y<<endl; } int main() { Befehle befehle; //Zunächst die Funktionen direkt testen: int y=1, a=14, b=3; befehle.A_Null(&y,&a,&b); cout<<"y="<<y<<endl; befehle.B_Ink(&y,&a,&b); cout<<"y="<<y<<endl; befehle.D_Plus(&y,&a,&b); cout<<"y=14+3="<<y<<endl; befehle.F_Mal(&y,&a,&b); cout<<"y=14*3="<<y<<endl; befehle.H_Mod(&y,&a,&b); cout<<"y=14%3="<<y<<endl; int arr[] = {1,3,0,17,18,19}; befehle.I_Array(&arr[2],&arr[0],&arr[1]); cout<<arr[3]<<endl; befehle.C_Dek(&arr[1],&arr[1],&arr[1]); befehle.I_Array(&arr[2],&arr[0],&arr[1]); cout<<arr[3]<<endl; //Parameterübertragung testen: char parameter[] = {"-2,-1,+0,+1,+2,+3,+4,+5,+6,+7,+11,-11,+12,-12,+13,-13,+14,-14,+15,-15,;"}; befehle.uebertrageParameter(parameter); befehle.zeigeParameter(); //Einfaches Skript übertragen und testen: //B_Ink(f) => f=4 //D_Plus(a,e,f) => a=2+4=6 //I_Array(k,d,e) <=> I_Array(param[10],param[3],param[4]) => param[10+1]=param[10+2] => l=12 //M_Om4(a) Drehgeberwert in a speichern //F_Mal(a,a,g) a mit g multiplizieren //J_Antrieb(a), a als Antriebswert setzen char skript[] = {"BfffsDaefsIkdesMaaasFaagsJaaas;"}; befehle.uebertrageSkript(skript); cout<<"Ergebnisse bei einfachem Skriptbeispiel:"<<endl; befehle.bearbeiteNaechstenBefehl(); befehle.zeigeParameter(); befehle.bearbeiteNaechstenBefehl(); befehle.zeigeParameter(); befehle.bearbeiteNaechstenBefehl(); befehle.zeigeParameter(); befehle.bearbeiteNaechstenBefehl(); befehle.zeigeParameter(); befehle.bearbeiteNaechstenBefehl(); befehle.zeigeParameter(); befehle.bearbeiteNaechstenBefehl(); befehle.zeigeParameter(); }
Code 0-3: skripterweiterung03_operationen.cpp - Vervollständigung der Skriptsprache.
Aufgabe
|
#include<iostream> #define PARAM_ANZ 20 #define PUFFER_GROESSE 300 #define FUNK_ANZ 13 using namespace std; int dummy_i = -1; int dummy_k = -1; int dummy_pwm_antrieb = 0; int dummy_pwm_servo = 0; //Um eine bessere Übersicht zu erhalten, werden die Methoden der Klasse "Befehle" //zunächst nur als Prototypen hingeschrieben und erst hinter der Klasse implementiert. class Befehle { private: char skript[PUFFER_GROESSE]; int param[PARAM_ANZ]; void (Befehle::*zeiger[FUNK_ANZ])(int*,int*,int*); int anzahl_befehle; int befehls_zaehler; public: Befehle() { zeiger[0] = &Befehle::A_Null; zeiger[1] = &Befehle::B_Ink; zeiger[2] = &Befehle::C_Dek; zeiger[3] = &Befehle::D_Plus; zeiger[4] = &Befehle::E_Minus; zeiger[5] = &Befehle::F_Mal; zeiger[6] = &Befehle::G_Durch; zeiger[7] = &Befehle::H_Mod; zeiger[8] = &Befehle::I_Array; zeiger[9] = &Befehle::J_Antrieb; zeiger[10] = &Befehle::K_Servo; zeiger[11] = &Befehle::L_Sensor; zeiger[12] = &Befehle::M_Om4; // (Befehle::Befehle::*zeiger[FUNK_ANZ])(int*,int*,int*) } //Funktionen, die elementare Operationen umsetzen: void A_Null(int* y, int* a, int* b); //y=0 void B_Ink(int* y, int* a, int* b); //y++ void C_Dek(int* y, int* a, int* b); //y-- void D_Plus(int* y, int* a, int* b); //y=a+b void E_Minus(int* y, int* a, int* b); //y=a-b void F_Mal(int* y, int* a, int* b); //y=a*b void G_Durch(int* y, int* a, int* b); //y=a/b void H_Mod(int* y, int* a, int* b); //y=a%b //Funktion, um Folgen von Arrayelementen verarbeiten zu können: void I_Array(int* y, int* a, int* b); //arr=Adresse von y, arr[a]=arr[b] //Funktionen, die den Zugriff auf die COACH-Peripherie erlauben: void J_Antrieb(int* y, int* a, int* b); //PWM_Antrieb = y (+/-1023) void K_Servo(int* y, int* a, int* b); //PWM_Servo = y (+/-36) void L_Sensor(int* y, int* a, int* b); //y=Distanz [mm] void M_Om4(int* y, int* a, int* b); //y=omega_viertel (Wert muß durch vier geteilt werden, um Omega zu erhalten.) void uebertrageSkript(char* text) { int i=0; while(text[i]!=';') { if(i%5==0) skript[i] = text[i]-'A'; else skript[i] = text[i]-'a'; i++; } anzahl_befehle = i/5; cout<<"Anzahl der Befehle:"<<anzahl_befehle<<endl; befehls_zaehler = 0; } void uebertrageParameter(char* parameter_uebergabe) { int i=0; int k=0; char c = parameter_uebergabe[i]; bool minus=false; int hilf=0; while(c!=';' && c!='\0' && k<PARAM_ANZ) { if(c=='-') { minus=true; hilf=0; } else if(c=='+') { minus=false; hilf=0; } else if(c>='0' && c<='9') { hilf*=10; hilf+=c-48; } else if(c==',') { if(minus==true) hilf = -hilf; param[k]=hilf; k++; } i++; c = parameter_uebergabe[i]; } } void zeigeParameter() { cout<<"Parameter:"<<endl; for(int i=0;i<PARAM_ANZ;i++) cout<<param[i]<<" "; cout<<endl; } void bearbeiteNaechstenBefehl() { if(param[ skript[befehls_zaehler*5+4] ] > 0) (this->*(zeiger[skript[befehls_zaehler*5]]))( ¶m[skript[befehls_zaehler*5+1]], ¶m[skript[befehls_zaehler*5+2]], ¶m[skript[befehls_zaehler*5+3]] ); befehls_zaehler++; befehls_zaehler%=anzahl_befehle; } }; //Funktionen, die elementare Operationen umsetzen: void Befehle::A_Null(int* y, int* a, int* b) //y=0 { *y=0; } void Befehle::B_Ink(int* y, int* a, int* b) //y++ { (*y)++; } void Befehle::C_Dek(int* y, int* a, int* b) //y-- { (*y)--; } void Befehle::D_Plus(int* y, int* a, int* b) //y=a+b { *y=*a+*b; } void Befehle::E_Minus(int* y, int* a, int* b) //y=a-b { *y=*a-*b; } void Befehle::F_Mal(int* y, int* a, int* b) //y=a*b { *y=*a**b; } void Befehle::G_Durch(int* y, int* a, int* b) //y=a/b { *y=*a/ *b; } void Befehle::H_Mod(int* y, int* a, int* b) //y=a%b { *y=*a%*b; } //Funktion, um Folgen von Arrayelementen verarbeiten zu können: void Befehle::I_Array(int* y, int* a, int* b) //arr=Adresse von y, arr[a]=arr[b] { a = y + *a; b = y + *b; *a = *b; } //Funktionen, die den Zugriff auf die COACH-Peripherie erlauben: void Befehle::J_Antrieb(int* y, int* a, int* b) //PWM_Antrieb = y (+/-1023) { dummy_pwm_antrieb = *y; cout<<"pwm_antrieb="<<dummy_pwm_antrieb<<endl; } void Befehle::K_Servo(int* y, int* a, int* b) //PWM_Servo = y (+/-36) { dummy_pwm_servo = *y; cout<<"pwm_servo="<<dummy_pwm_servo<<endl; } void Befehle::L_Sensor(int* y, int* a, int* b) //y=Distanz [mm] { int werte[] = {200,100,300,150,155,120,12,0,30,60}; //10 Zufallswerte dummy_i++; *y = werte[dummy_i%10]; cout<<"Sensor liefert Distanz="<<*y<<endl; } void Befehle::M_Om4(int* y, int* a, int* b) //y=omega_viertel (Wert muß durch vier geteilt werden, um Omega zu erhalten.) { int werte[] = {4,8,10,15,20,18,15,23,30,29}; //10 Zufallswerte dummy_k++; *y = werte[dummy_k%10]; cout<<"Drehgeber liefert om_viertel="<<*y<<endl; } int main() { Befehle befehle; //Parameterübertragung: //P-Anteil=51, gespeichert in a (param[0]) //I-Anteil=335, gespeichert in b (param[1]) //D-Anteil=0.77, dargestellt als 77/100 // 77 gespeichert in c (param[2]) // 100 gespeichert in d (param[3]) //Führungsgroesse w=20, gespeichert in e (param[4]) //dt=0.001, Kehrwert 1000 gespeichert in f (param[5]) //letzte 5 Regeldifferenzwerte werden in param[10]..param[15] gespeichert (k,l,m,n,o) //Zur freien Verfügung stehen: g,h,i,j (param[6..9]) und p,q,r,s,t (param[16..19]) //Umzusetzen ist: //pwm_antrieb = P(w-om4) + Isum( (w-om4)alt0..4 )dt + D((w-om4)neu - (w-om4)alt)/dt //Dabei ist immer erst die älteste Regeldifferenz in dem Merkarray k,l,m,n,o zu ersetzen //und dann der neue pwm-Wert zu berechnen und zu setzen. //Notwendige Parameter und einige nützliche Konstanten in q,r,s,t: // P I Dz Dn w 1/dt // a b c d e f g h i j k l m n o p q r s t char parameter[] = {"+51,+335,+77,+100,+20,+1000,+0,+0,-1,+0, +0,+0,+0,+0,+0, +0,+0,+1,+5,-1,;"}; befehle.uebertrageParameter(parameter); befehle.zeigeParameter(); //i als Laufparameter für den Platz der neuen Regeldifferenz vorsehen. //in g die neue Regeldifferenz berechnen, vorher alten Wert in h merken: //h=g => D_Plus(h,g,q,r); h=g+q = g+0 //g=om4 => M_Om4(g,g,g,r); //g=g*-1 => F_Mal(g,g,t,r); //g=g+w => D_Plus(g,g,e,r); //Skript-Teil: DhgqrMgggrFggtrDgger //pwm Signal in j berechnen: //P-Anteil: //j=0 => A_Null(j,j,j,r); //j=j+g => D_Plus(j,j,g,r); //j*=a => F_Mal(j,j,a,r); //Skript-Teil: AjjjrDjjgrFjjar //D-Anteil in p bestimmen: //... //I-Anteil in p bestimmen: //... //j auf pwm übertragen: //... //Älteste Regeldifferenz mit jüngstem Wert überschreiben: //Index des zu überschreibenden Elements in i //Startadresse des Arrays ist k //Zu schreibender Wert wird in p abgelegt, was arr[5] entspricht, 5 steht in s zur Verfügung. //i++ => B_Ink(i,i,i,r); //i%=5 => H_Mod(i,i,s,r); //p=g => D_Plus(p,g,q,r); //arr[i]=w => I_Array(k,i,s,r); //Nur PD-Anteil: char skript2[] = {"..."}; cout<<"PD-Regler:"<<endl; befehle.uebertrageSkript(skript2); for(int i=0;i<14*10;i++) befehle.bearbeiteNaechstenBefehl(); //25 Befehle: char skript[] = {"..."}; cout<<"PID-Regler:"<<endl; befehle.uebertrageSkript(skript); for(int i=0;i<25*10;i++) befehle.bearbeiteNaechstenBefehl(); }
Code 0-4: skripterweiterung04_pid_aufgabe.cpp - Aufgabe, Skript für PID-Regler erstellen.