Dekodierung RS-232 in Simulink: Unterschied zwischen den Versionen

Aus HSHL Mechatronik
Zur Navigation springen Zur Suche springen
(Konkretere Einleitung formuliert, Quellcode Platzhalter eingefügt)
(Programm Ablauf Plan und Quellcode hinzugefügt)
Zeile 7: Zeile 7:
[[Datei:RX Modell.png|right|700px]] <br>
[[Datei:RX Modell.png|right|700px]] <br>


= Pseudo Code der S-Function =
Platzhalter Pseudocode
== Programmablaufplan ==
[[Datei:Send Data Big Endian First.png|800px]]
= Implementierung in C++ =
Die S-Function ist mit dem folgenden Quellcode implementiert. Die Unterbrechungen dienen dabei nur der Erklärung, in Simulink (2022a) ist es eine Textdatei. In den vorigen Simulink Versionen wird der Code unübersichtlich auf mehrere Reiter aufgeteilt.
<syntaxhighlight lang="c" style="background-color: #EFF1C1">
<syntaxhighlight lang="c" style="background-color: #EFF1C1">


Platzhalter S-Function Quellcode
/* Includes_BEGIN */
#define BITS_IN_BYTE 8
#define START_BYTE 170
#define STOPP_BYTE 85
 
</syntaxhighlight>
Platzhalter Quellcode Beschreibung
<syntaxhighlight lang="c" style="background-color: #EFF1C1">
 
float laneParamA = 0;
float laneParamB = 0;
float laneParamC = 0;
uint8_T lane_asign = 0;
uint8_T stop_insight = 0;
float stop_distance = 0;
uint8_T n_objekte = 0;
uint8_T number = 0;
float x_0 = 0;
float y_0 = 0;
float b = 0;
float t = 0;
float alpha = 0;
float v = 0;
uint8_T plausible = 0;
 
uint8_T data = 0;
 
static uint8_T Start_Flag = 0;
 
uint8_T stopp_Byte = 0;
 
static uint8_T zaehler_param = 0; // wertigkeit: 0 - 3
static uint8_T zaehler_uebertragung = 0; // wertigkeit: 1 - 12
 
static uint8_T oldState = 0; // Alter Zustand speichern
 
//int i = 0;
 
union data
{
uint8_T datenErfassung[4]; // collect data
float datenSpeicher;      // data storage
}polyn;
/* Includes_END */
 
/* Externs_BEGIN */
 
/* Externs_END */
 
void merge_rxdata_to_signals_Start_wrapper(const uint8_T *size_of_data, const int_T p_width0)
{
/* Start_BEGIN */
/*
* Custom Start code goes here.
*/
/* Start_END */
}
 
void merge_rxdata_to_signals_Outputs_wrapper(const uint8_T *rx_data_in,
                                            const uint8_T *Status,
                                            uint8_T *ZaehlerUertragung_out,
                                            uint8_T *ZaehlerParameter_out,
                                            real_T *SenKam_SpurA_f64,
                                            real_T *SenKam_SpurB_f64,
                                            real_T *SenKam_SpurC_f64,
                                            boolean_T *SenKam_Spurzuordnung,
                                            boolean_T *SenKam_StopplinieErkannt,
                                            real_T *SenKam_StopplinieAbstand,
                                            uint8_T *SenKam_ObjekteAnzahl,
                                            uint8_T *SenKam_ObjektNummer,
                                            real_T *SenKam_ObjektX,
                                            real_T *SenKam_ObjektY,
                                            real_T *SenKam_Objektbreite,
                                            real_T *SenKam_Objekttiefe,
                                            real_T *SenKam_Objektausrichtung,
                                            real_T *SenKam_Objektgeschwindigkeit,
                                            uint8_T *SenKam_Vertraunswert,
                                            const uint8_T *size_of_data, const int_T p_width0)
{
/* Output_BEGIN */
//if(*Status != oldState)
if(Status > 0)
{
    // Empfängte Daten abgreifen 
    data = *rx_data_in;
   
    // Wurde der Start Byte empfägt?
    if(data == START_BYTE && Start_Flag == 0 && zaehler_param == 0)
    {
        Start_Flag = 1; // flag setzen
    }
   
    // Wurde das Flag gesetz? 
    else if(Start_Flag == 1)
    {
        zaehler_uebertragung++;
       
        // Daten sammeln - erfolgt 4 mal --> 4 * 8 bit 
        if(zaehler_param <= 3)
        {
            polyn.datenErfassung[zaehler_param] = data; 
        }
        // Zähler variable übergeben als Ausgang der Funktion
        *ZaehlerParameter_out = zaehler_param;
       
        zaehler_param++;
       
        // Nach 4 Datenbyte --> Spurparameter A
        if(zaehler_uebertragung == 4)
        {
            laneParamA = polyn.datenSpeicher;
            *SenKam_SpurA_f64 = laneParamA; 
            zaehler_param = 0;
        }
        // Nach 8 Datenbyte --> Spurparameter B
        else if(zaehler_uebertragung == 8)
        {
            laneParamB = polyn.datenSpeicher;
            *SenKam_SpurB_f64 = laneParamB;
            zaehler_param = 0;
        }
        // Nach 12 Datenbyte --> Spurparameter C   
        else if(zaehler_uebertragung == 12)
        {
            laneParamC = polyn.datenSpeicher;
            *SenKam_SpurC_f64 = laneParamC;
            zaehler_param = 0;
        }
           
 
       
       
        // Nach 13 Datenbyte --> Spurzuordnung
        else if(zaehler_uebertragung == 13)
        {
            // Wenn nur ein Bit empfangen wird (0 oder 1) dann data direkt in Output schreiben
            // Vermeiden von Fehlern durch falsche decodierung des Arrays
            *SenKam_Spurzuordnung = data; 
            zaehler_param = 0;
        }
        // Nach 14 Datenbyte --> Stopplinie erkannt
        else if(zaehler_uebertragung == 14)
        {
            *SenKam_StopplinieErkannt = data; 
            zaehler_param = 0;
        }
        // Nach 18 Datenbyte --> Abstand Stopplinie
        else if(zaehler_uebertragung == 18)
        {
            stop_distance = polyn.datenSpeicher;
            *SenKam_StopplinieAbstand = stop_distance; 
            zaehler_param = 0;
        }
        // Nach 19 Datenbyte --> Anzahl der Objekte
        else if(zaehler_uebertragung == 19)
        {
            *SenKam_ObjekteAnzahl = data; 
            zaehler_param = 0;
        }
        // Nach 20 Datenbyte --> Objektnummer
        else if(zaehler_uebertragung == 20)
        {
            *SenKam_ObjektNummer = data; 
            zaehler_param = 0;
        }
        // Nach 24 Datenbyte --> Objekt x-Koordinate
        else if(zaehler_uebertragung == 24)
        {
            x_0 = polyn.datenSpeicher;
            *SenKam_ObjektX = x_0; 
            zaehler_param = 0;
        }
        // Nach 28 Datenbyte --> Objekt y-Koordinate
        else if(zaehler_uebertragung == 28)
        {
            y_0 = polyn.datenSpeicher;
            *SenKam_ObjektY = y_0; 
            zaehler_param = 0;
        }
        // Nach 32 Datenbyte --> Objektbreite
        else if(zaehler_uebertragung == 32)
        {
            b = polyn.datenSpeicher;
            *SenKam_Objektbreite = b; 
            zaehler_param = 0;
        }
        // Nach 36 Datenbyte --> Objekttiefe
        else if(zaehler_uebertragung == 36)
        {
            t = polyn.datenSpeicher;
            *SenKam_Objekttiefe = t; 
            zaehler_param = 0;
        }
        // Nach 40 Datenbyte --> Objektausrichtung
        else if(zaehler_uebertragung == 40)
        {
            alpha = polyn.datenSpeicher;
            *SenKam_Objektausrichtung = alpha; 
            zaehler_param = 0;
        }
        // Nach 44 Datenbyte --> Objektgeschwindigkeit
        else if(zaehler_uebertragung == 44)
        {
            v = polyn.datenSpeicher;
            *SenKam_Objektgeschwindigkeit = v; 
            zaehler_param = 0;
        }
        // Nach 45 Datenbyte --> Vertraunswert
        else if(zaehler_uebertragung == 45)
        {
            *SenKam_Vertraunswert = data; 
            zaehler_param = 0;
        } 
        // Nach Übertragung Objektparameter zurücksetzen
            if (SenKam_ObjektNummer < SenKam_ObjekteAnzahl)
            {
                    zaehler_uebertragung = 20;
            }
       
       
     
        // Nach Übertragung alle Parameter zurücksetzen
            else if (zaehler_uebertragung >= 46 )
            {
                Start_Flag = 0;
                zaehler_param = 0;
                zaehler_uebertragung = 0;
            }     
            *ZaehlerUertragung_out = zaehler_uebertragung;
    }
   
    // Wenn Start Byte nicht emfangen würde, Alle parameter bleiben auf 0
    else
    {
        Start_Flag = 0;
        zaehler_param =  0;
        zaehler_uebertragung = 0;
    }
    //oldState = *Status;
}
/* Output_END */
}
 
void merge_rxdata_to_signals_Terminate_wrapper(const uint8_T *size_of_data, const int_T p_width0)
{
/* Terminate_BEGIN */
/*
* Custom Terminate code goes here.
*/
/* Terminate_END */
}


</syntaxhighlight>
</syntaxhighlight>

Version vom 4. Dezember 2022, 16:59 Uhr

Autor: Tim Schonlau (WiSe 22/23)

Einleitung

Dieser Artikel beschreibt die Implementierung einer S-Function in Simulink. Die Daten, die von der x86-CPU über den COM Port an die dSPACE Karte gesendet werden, werden mit dieser S-Function dekodiert und im online Modell bereitgestellt. Der Quellcode der S-Function wird in C++ geschrieben. Sie ist ein wichtiger Teil des Simulink online Modells des CCF.

Orientierung in Simulink

Mit MATLAB Simulink 2019b ist der Quellcode unter Output im Function Block zu finden (ändert sich mit 2022a). Die Eingabe und Ausgabeparameter müssen in den entsprechenden Reitern konfiguriert werden.


Pseudo Code der S-Function

Platzhalter Pseudocode

Programmablaufplan


Implementierung in C++

Die S-Function ist mit dem folgenden Quellcode implementiert. Die Unterbrechungen dienen dabei nur der Erklärung, in Simulink (2022a) ist es eine Textdatei. In den vorigen Simulink Versionen wird der Code unübersichtlich auf mehrere Reiter aufgeteilt.

/* Includes_BEGIN */
#define BITS_IN_BYTE 8
#define START_BYTE 170
#define STOPP_BYTE 85

Platzhalter Quellcode Beschreibung

float laneParamA = 0; 
float laneParamB = 0; 
float laneParamC = 0; 
uint8_T lane_asign = 0; 
uint8_T stop_insight = 0; 
float stop_distance = 0; 
uint8_T n_objekte = 0; 
uint8_T number = 0;
float x_0 = 0;
float y_0 = 0;
float b = 0;
float t = 0;
float alpha = 0;
float v = 0;
uint8_T plausible = 0;

uint8_T data = 0;

static uint8_T Start_Flag = 0;

uint8_T stopp_Byte = 0;

static uint8_T zaehler_param = 0; // wertigkeit: 0 - 3
static uint8_T zaehler_uebertragung = 0; // wertigkeit: 1 - 12

static uint8_T oldState = 0; // Alter Zustand speichern

//int i = 0;

union data
{
	uint8_T datenErfassung[4]; // collect data
	float datenSpeicher;       // data storage 
}polyn;
/* Includes_END */

/* Externs_BEGIN */

/* Externs_END */

void merge_rxdata_to_signals_Start_wrapper(const uint8_T *size_of_data, const int_T p_width0)
{
/* Start_BEGIN */
/*
 * Custom Start code goes here.
 */
/* Start_END */
}

void merge_rxdata_to_signals_Outputs_wrapper(const uint8_T *rx_data_in,
                                             const uint8_T *Status,
                                             uint8_T *ZaehlerUertragung_out,
                                             uint8_T *ZaehlerParameter_out,
                                             real_T *SenKam_SpurA_f64,
                                             real_T *SenKam_SpurB_f64,
                                             real_T *SenKam_SpurC_f64,
                                             boolean_T *SenKam_Spurzuordnung,
                                             boolean_T *SenKam_StopplinieErkannt,
                                             real_T *SenKam_StopplinieAbstand,
                                             uint8_T *SenKam_ObjekteAnzahl,
                                             uint8_T *SenKam_ObjektNummer,
                                             real_T *SenKam_ObjektX,
                                             real_T *SenKam_ObjektY,
                                             real_T *SenKam_Objektbreite,
                                             real_T *SenKam_Objekttiefe,
                                             real_T *SenKam_Objektausrichtung,
                                             real_T *SenKam_Objektgeschwindigkeit,
                                             uint8_T *SenKam_Vertraunswert,
                                             const uint8_T *size_of_data, const int_T p_width0)
{
/* Output_BEGIN */
//if(*Status != oldState)
if(Status > 0)
{
    // Empfängte Daten abgreifen  
    data = *rx_data_in; 
    
    // Wurde der Start Byte empfägt? 
    if(data == START_BYTE && Start_Flag == 0 && zaehler_param == 0)
    {
        Start_Flag = 1; // flag setzen
    } 
    
    // Wurde das Flag gesetz?  
    else if(Start_Flag == 1)
    {
        zaehler_uebertragung++;
        
        // Daten sammeln - erfolgt 4 mal --> 4 * 8 bit  
        if(zaehler_param <= 3)
        {
            polyn.datenErfassung[zaehler_param] = data;   
        }
        // Zähler variable übergeben als Ausgang der Funktion
        *ZaehlerParameter_out = zaehler_param;
        
        zaehler_param++;
        
        // Nach 4 Datenbyte --> Spurparameter A 
        if(zaehler_uebertragung == 4)
        { 
            laneParamA = polyn.datenSpeicher; 
            *SenKam_SpurA_f64 = laneParamA;  
            zaehler_param = 0;
        }
        // Nach 8 Datenbyte --> Spurparameter B 
        else if(zaehler_uebertragung == 8) 
        {
            laneParamB = polyn.datenSpeicher;
            *SenKam_SpurB_f64 = laneParamB;
            zaehler_param = 0;
        }
        // Nach 12 Datenbyte --> Spurparameter C     
        else if(zaehler_uebertragung == 12)
        {
            laneParamC = polyn.datenSpeicher; 
            *SenKam_SpurC_f64 = laneParamC; 
            zaehler_param = 0;
        }
            
  
        
        
        // Nach 13 Datenbyte --> Spurzuordnung 
        else if(zaehler_uebertragung == 13)
        { 
            // Wenn nur ein Bit empfangen wird (0 oder 1) dann data direkt in Output schreiben
            // Vermeiden von Fehlern durch falsche decodierung des Arrays
            *SenKam_Spurzuordnung = data;  
            zaehler_param = 0;
        }
        // Nach 14 Datenbyte --> Stopplinie erkannt 
        else if(zaehler_uebertragung == 14)
        { 
            *SenKam_StopplinieErkannt = data;  
            zaehler_param = 0;
        }
        // Nach 18 Datenbyte --> Abstand Stopplinie 
        else if(zaehler_uebertragung == 18)
        { 
            stop_distance = polyn.datenSpeicher; 
            *SenKam_StopplinieAbstand = stop_distance;  
            zaehler_param = 0;
        }
         // Nach 19 Datenbyte --> Anzahl der Objekte
        else if(zaehler_uebertragung == 19)
        { 
            *SenKam_ObjekteAnzahl = data;  
            zaehler_param = 0;
        }
         // Nach 20 Datenbyte --> Objektnummer
        else if(zaehler_uebertragung == 20)
        { 
            *SenKam_ObjektNummer = data;  
            zaehler_param = 0;
        }
        // Nach 24 Datenbyte --> Objekt x-Koordinate
        else if(zaehler_uebertragung == 24)
        { 
            x_0 = polyn.datenSpeicher; 
            *SenKam_ObjektX = x_0;  
            zaehler_param = 0;
        }
        // Nach 28 Datenbyte --> Objekt y-Koordinate
        else if(zaehler_uebertragung == 28)
        { 
            y_0 = polyn.datenSpeicher; 
            *SenKam_ObjektY = y_0;  
            zaehler_param = 0;
        }
        // Nach 32 Datenbyte --> Objektbreite
        else if(zaehler_uebertragung == 32)
        { 
            b = polyn.datenSpeicher; 
            *SenKam_Objektbreite = b;  
            zaehler_param = 0;
        }
        // Nach 36 Datenbyte --> Objekttiefe
        else if(zaehler_uebertragung == 36)
        { 
            t = polyn.datenSpeicher; 
            *SenKam_Objekttiefe = t;  
            zaehler_param = 0;
        }
        // Nach 40 Datenbyte --> Objektausrichtung
        else if(zaehler_uebertragung == 40)
        { 
            alpha = polyn.datenSpeicher; 
            *SenKam_Objektausrichtung = alpha;  
            zaehler_param = 0;
        }
        // Nach 44 Datenbyte --> Objektgeschwindigkeit
        else if(zaehler_uebertragung == 44)
        { 
            v = polyn.datenSpeicher; 
            *SenKam_Objektgeschwindigkeit = v;  
            zaehler_param = 0;
        }
         // Nach 45 Datenbyte --> Vertraunswert
        else if(zaehler_uebertragung == 45)
        { 
            *SenKam_Vertraunswert = data;  
            zaehler_param = 0;
        }   
         // Nach Übertragung Objektparameter zurücksetzen
            if (SenKam_ObjektNummer < SenKam_ObjekteAnzahl)
            {
                    zaehler_uebertragung = 20; 
            }
        
        
       
         // Nach Übertragung alle Parameter zurücksetzen
            else if (zaehler_uebertragung >= 46 )
            {
                Start_Flag = 0;
                zaehler_param = 0;
                zaehler_uebertragung = 0;
            }      
            *ZaehlerUertragung_out = zaehler_uebertragung;
    }
     
    // Wenn Start Byte nicht emfangen würde, Alle parameter bleiben auf 0
    else 
    {
        Start_Flag = 0;
        zaehler_param =  0;
        zaehler_uebertragung = 0;
    }
    //oldState = *Status;
}
/* Output_END */
}

void merge_rxdata_to_signals_Terminate_wrapper(const uint8_T *size_of_data, const int_T p_width0)
{
/* Terminate_BEGIN */
/*
 * Custom Terminate code goes here.
 */
/* Terminate_END */
}



→ zurück zum Kommunikationsartikel: Kom - Kommunikation
→ zurück zum Hauptartikel: Praktikum SDE