kramann.info
© Guido Kramann

Login: Passwort:










COACH2
1 Planung
2 Architektur
3 Anzeige
4 EEPROM
5 I2C
..5.1 MasterSendByte
..5.2 MasterSend2Bytes
..5.3 MasterReceiveByte
..5.4 MasterReceive2Bytes
6 UART
7 DFT
8 FFT
9 Planung2
10 Klassen
..10.1 AnzeigeTaster
..10.2 RS232
..10.3 MotorServo
..10.4 Drehgeber
..10.5 Sensor
..10.6 Funk
11 Adaption
..11.1 Programmiertechnik
..11.2 Evoopt
12 Fuzzy
..12.1 Uebungsaufgabe
..12.2 Fuzzygroesse
..12.3 Fuzzyset
..12.4 Lookuptable
13 Skript
..13.1 Funkkorrektur
..13.2 Skriptsprachen
..13.3 Anforderungen
..13.4 Agentensysteme
..13.5 Implementierung
..13.6 Experimente
14 Gesamtkonzept
..14.1 Skripterweiterung
..14.2 Makroverhalten
67 Echtzeitsysteme
..67.1 Einfuehrung
....67.1.1 Echtzeit
....67.1.2 Korrektheit
....67.1.3 Hardware
....67.1.4 Ziele
....67.1.5 Synchronprogramm
..67.2 Threads
....67.2.1 Java
....67.2.2 Synchronisierung
..67.3 COACH
....67.3.1 Kaskadenregler
....67.3.2 Zeitebene1
....67.3.3 Zeitebene2
....67.3.4 Zeitebene3
....67.3.5 Puck
....67.3.6 Puckschwarm
..67.4 RTAIlab
....67.4.1 Slax
....67.4.1 USB_Stick
....67.4.2 Sinus
..67.5 Semaphor
....67.5.1 Laufkatze
....67.5.2 Java
....67.5.3 Semaphor
..67.6 Audio
....67.6.1 wav
....67.6.2 Linux
..67.7 Lookup
....67.7.1 Fuzzy
....67.7.2 PWM
..67.8 NeuronaleNetze
....67.8.1 Neuron
....67.8.2 Backpropagation
....67.8.3 Umsetzung
....67.8.4 Winkelerkennung
..67.9 Internetprogrammierung
....67.9.1 Codegenerierung
....67.9.2 PHP_Programmierung
....67.9.3 PHP_OOP
....67.9.4 Java
....67.9.5 UDP
..67.10 DFT
..67.11 FFT
..67.12 Zustandsmaschine
..67.13 Fuzzy
....67.13.1 Fuzzylogik
....67.13.2 FuzzyRegler
....67.13.3 Uebung9
....67.13.5 Softwareentwicklung
......67.13.5.1 AgileSoftwareentwicklung
......67.13.5.2 FuzzyRegler
......67.13.5.3 Uebung
....67.13.6 Umsetzung
......67.13.6.1 FuzzyRegler
......67.13.6.2 Simulation
......67.13.6.3 Optimierung
......67.13.6.4 Uebung
....67.13.7 Haengependel
......67.13.7.1 Haengependel
......67.13.7.2 Simulation
......67.13.7.3 FuzzyRegler
......67.13.7.4 Optimierer
......67.13.7.5 Genetisch
....67.13.8 Information
....67.13.9 Energie

14.1 Anforderungen an das Skript und entsprechende Erweiterungen

erweiterungen_stud.zip - Download der folgenden C++ - Quelltexte.
Parameter setzen und im Skript ansprechen
  • Die notwendigen Parameter P, I und D wurden bereits identifiziert, sollten aber per Funk gesetzt werden können.
  • Es sollte ein Array für Parameter geben, deren Elemente vor Übertragung und Starten des Skriptes per Funk gesetzt werden.
  • Es erscheint ausreichend zu sein, als Datentyp Integer-Werte vorzusehen.
  • Im Skript könnten die Parameter durch Kleinbuchstaben kenntlich gemacht sein: a,b,c,d,...
  • Durch die Fortlaufende Reihenfolge ließe sich wie bei den Funktionen auch hier eine einfache Umrechnung von ASCII-Buchstabe zu Array-Index vornehmen.
  • Im Skript bedarf es keiner Unterscheidung zwischen (veränderlichen) Variablen und (festen) Parameter.
  • Mit a,b,c,... könnten genau so gut Parameter als auch Variablen gemeint sein.
  • Folgendes Testprogramm für den PC zeigt eine mögliche Umsetzung dieser Anforderung:
#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 14.1-1: skripterweiterung01_parameter.cpp - Einführung von Parametern.

Übergabeparameter und Rückgabewerte bei Funktionen
  • Bei dem Regler wird aus gemessenen Drehzahlwerten und deren algebraischen Umformungen ein PWM-Signal berechnet und auch gesetzt.
  • Hierzu ist es notwedig, Rückgabewerte von Funktionen in Variablen zu speichern und umgekehrt eine Funktion mit einer oder mehreren Variablen als Übergabeparameter aufzurufen.
  • Zu der Implementierung der notwendigen algebraischen Operationen auf Variablen kommen wir im nächsten Punkt.
  • Hier zunächst ein Testprogramm, bei dem über das Skript Zuweisungen von Funktionsrückgabewerten an Variablen und die Übergabe von Variablen an Funktionen testweise umgesetzt wird:
  • Um eine einheitliche Struktur zu erhalten und eine Vielzahl an Verarbeitungsmöglichkeiten zu eröffnen, werden grundsätzlich drei Parameter als Zeiger übergeben.
  • Erster Parameter: Ergebnis
  • Zweiter Parameter: Übergabeparameter Nr. 1
  • Dritter Parameter: Übergabeparameter Nr. 2
  • Vierter Parameter (nur in Skript, wird nicht übergeben): Ausführungsbedingung, größer Null: Methode wird ausgeführt, kleiner oder gleich Null: Methode wird nicht ausgeführt.
#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 14.1-2: skripterweiterung02_uebergabeparameter.cpp - Verarbeitung von Parametern

Elementare Rechenoperationen und Ansprechen von Array-Elementen über einen Index
  • Da sowohl für den Integral-Anteil, als auch für den Differentialanteil die Regeldifferenzen vergangener Messungen verfügbar sein müssen, muß es möglich sein mit dem Skript eine Art "Ringspeicher" zu realisieren, bei dem immer der älteste Wert durch den neusten Überschrieben wird.
  • Hierzu muß neben der Verfügbarkeit der Arrayelemente als Variablen mit Kleinbuchstaben auch eine Möglichkeit implementiert werden, diese über Indices anzusprechen.
  • Diese Indices müssen zudem in einer Variablen verarbeitet werden können.
  • Insbesondere müssen hierfür auch elementare Rechenoperationen, als auch die Modulo-Division zur Verfügung stehen.
  • Mit der nun folgenden Ergänzung der Skriptsprache stehen nun alle erforderlichen Elemente zur Verfügung.
  • Durch Integration der Verarbeitungsfunktionen in die Klasse Befehl, wird eine bessere Kapselung der Skriptverarbeitung und eine größere Übersichtlichkeit in dem main-Programm erreicht.
#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 14.1-3: skripterweiterung03_operationen.cpp - Vervollständigung der Skriptsprache.

Aufgabe
  • Auf Grundlage eines Skriptes soll der PID-Regler für den Antrieb realisiert werden.
  • Vervollständigen Sie unten stehendes Programm.
  • Vorgehen: Schreiben Sie erst eine Liste der auszuführenden Befehle. Notieren Sie daneben die hierfür aufzurufenden Funktionen. Schreiben Sie erst dann das Skript auf.
  • Achtung: In diesem Test werden keine sinnvollen PWM-Werte generiert, da die Drehgeberwerte Pseudozufallszahlen sind.
#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 14.1-4: skripterweiterung04_pid_aufgabe.cpp - Aufgabe, Skript für PID-Regler erstellen.