TIA "Komplexe" Datenstruktur mittels UDP von S7-1500 lesen

eXe

Level-1
Beiträge
17
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Guten Tag miteinander,

Mein Name ist Mark und ich versuche mich gerade am UDP-Protokoll mittels S7-1500. Meine Aufgabe ist es ein -leider nicht änderbares- Datenpaket mittels UDP auszulesen. Dazu möchte ich eine S7-1516-3PN/DP verwenden. Ich denke, dass ich den Empfang mittels TRCV_C-Baustein hinbekomme. Mein Problem ist eher die "Datenstruktur" welche ich lesen möchte. Mir ist leider nicht bekannt, wie ich der SPS diese Struktur beibringe, sei es in einem globalen DB oder einem Array-DB oder wie auch immer. Ziel ist nun mal, dass die Daten die gesendet werden auch geordnet ankommen und weiter verarbeitet werden können. Das Paket sieht wie folgt aus:

Code:
[B]struct UDPPacket[/B]
{
    float m_time;

    float m_lapTime;
    float m_lapDistance;
    float m_totalDistance;
    float m_x;                // World space position
    float m_y;                // World space position
    float m_z;                // World space position
    float m_speed;                // Speed of car in MPH
    float m_xv;                // Velocity in world space
    float m_yv;                // Velocity in world space
    float m_zv;                // Velocity in world space
    float m_xr;                // World space right direction
    float m_yr;                // World space right direction
    float m_zr;                // World space right direction
    float m_xd;                // World space forward direction
    float m_yd;                // World space forward direction
    float m_zd;                // World space forward direction
    float m_susp_pos[4];    // Note: All wheel arrays have the order:
    float m_susp_vel[4];            // RL, RR, FL, FR
    float m_wheel_speed[4];
    float m_throttle;
    float m_steer;
    float m_brake;
    float m_clutch;
    float m_gear;
    float m_gforce_lat;
    float m_gforce_lon;
    float m_lap;
    float m_engineRate;
    float m_sli_pro_native_support;    // SLI Pro support
    float m_car_position;            // car race position
    float m_kers_level;            // kers energy left
    float m_kers_max_level;        // kers maximum energy
    float m_drs;            // 0 = off, 1 = on
    float m_traction_control;        // 0 (off) - 2 (high)
    float m_anti_lock_brakes;        // 0 (off) - 1 (on)
    float m_fuel_in_tank;        // current fuel mass
    float m_fuel_capacity;        // fuel capacity
    float m_in_pits;            // 0 = none, 1 = pitting, 2 = in pit area
    float m_sector;            // 0 = sector1, 1 = sector2, 2 = sector3
    float m_sector1_time;        // time of sector1 (or 0)
    float m_sector2_time;        // time of sector2 (or 0)
    float m_brakes_temp[4];        // brakes temperature (centigrade)
    float m_tyres_pressure[4];        // tyres pressure PSI
    float m_team_info;            // team ID 
    float m_total_laps;            // total number of laps in this race
    float m_track_size;            // track size meters
    float m_last_lap_time;        // last lap time
    float m_max_rpm;            // cars max RPM, at which point the rev limiter will kick in
    float m_idle_rpm;            // cars idle RPM
    float m_max_gears;            // maximum number of gears
    float m_sessionType;        // 0 = unknown, 1 = practice, 2 = qualifying, 3 = race
    float m_drsAllowed;            // 0 = not allowed, 1 = allowed, -1 = invalid / unknown
    float m_track_number;        // -1 for unknown, 0-21 for tracks
    float m_vehicleFIAFlags;        // -1 = invalid/unknown, 0 = none, 1 = green, 2 = blue, 3 = yellow, 4 = red
    float m_era;                        // era, 2017 (modern) or 1980 (classic)
    float m_engine_temperature;      // engine temperature (centigrade)
    float m_gforce_vert;        // vertical g-force component
    float m_ang_vel_x;            // angular velocity x-component
    float m_ang_vel_y;            // angular velocity y-component
    float m_ang_vel_z;            // angular velocity z-component
    byte  m_tyres_temperature[4];    // tyres temperature (centigrade)
    byte  m_tyres_wear[4];        // tyre wear percentage
     byte  m_tyre_compound;        // compound of tyre – 0 = ultra soft, 1 =  super soft, 2 = soft, 3 = medium, 4 = hard, 5 = inter, 6 = wet
    byte  m_front_brake_bias;             // front brake bias (percentage)
    byte  m_fuel_mix;                     // fuel mix - 0 = lean, 1 = standard, 2 = rich, 3 = max
    byte  m_currentLapInvalid;        // current lap invalid - 0 = valid, 1 = invalid
    byte  m_tyres_damage[4];        // tyre damage (percentage)
    byte  m_front_left_wing_damage;    // front left wing damage (percentage)
    byte  m_front_right_wing_damage;    // front right wing damage (percentage)
    byte  m_rear_wing_damage;        // rear wing damage (percentage)
    byte  m_engine_damage;        // engine damage (percentage)
    byte  m_gear_box_damage;        // gear box damage (percentage)
    byte  m_exhaust_damage;        // exhaust damage (percentage)
    byte  m_pit_limiter_status;        // pit limiter status – 0 = off, 1 = on
    byte  m_pit_speed_limit;        // pit speed limit in mph
    float m_session_time_left;  // [B]NEW:[/B] time left in session in seconds 
    byte  m_rev_lights_percent;  // [B]NEW: [/B]rev lights indicator (percentage)
    byte  m_is_spectating;  // [B]NEW: [/B]whether the player is spectating
    byte  m_spectator_car_index;  // [B]NEW: [/B]index of the car being spectated


    // Car data
    byte  m_num_cars;                  // number of cars in data
    byte  m_player_car_index;            // index of player's car in the array
    CarUDPData  m_car_data[20];       // data for all cars on track
};


[B]struct CarUDPData[/B]
{
    float m_worldPosition[3];     // world co-ordinates of vehicle
    float m_lastLapTime;
    float m_currentLapTime;
    float m_bestLapTime;
    float m_sector1Time;
    float m_sector2Time;
    float m_lapDistance;
    byte  m_driverId;
    byte  m_teamId;
    byte  m_carPosition;     // [B]UPDATED: [/B]track positions of vehicle

    byte  m_currentLapNum;
     byte  m_tyreCompound;    // compound of tyre – 0 = ultra soft, 1 = super  soft, 2 = soft, 3 = medium, 4 = hard, 5 = inter, 6 = wet
    byte  m_inPits;               // 0 = none, 1 = pitting, 2 = in pit area
    byte  m_sector;               // 0 = sector1, 1 = sector2, 2 = sector3
    byte  m_currentLapInvalid;     // current lap invalid - 0 = valid, 1 = invalid

    byte  m_penalties;  // [B]NEW: [/B]accumulated time penalties in seconds to be added

};

Meine Frage an die Profis unter euch: Geht das überhaupt?
Über Antworten freue ich mich riesig :)!
Mit freundlichen Grüßen,
Mark
 
Um mir kurz selber zu antworten:
Ich habe gerade gesehen, dass man ein Array in einem Struct anlegen kann. Das müsste es ja schon fast gewesen sein?

Viele Grüße,
Mark
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Mit UDP hat das Problem eigentlich erst mal nix zu tun.
So wie es aussieht hat das Protokoll eine feste Länge.
Du kannst dir also einfach einen fixen Empfangsbuffer definieren und die Daten dort ablegen.
Anschließend kannst du dir daraus deine Daten in die passenden Structuren kopieren.
Es kann z.B. durchaus sein, dass du die Byte-Order bei Float anpassen musst.
Datenübertragung ist immer für eine Überraschung gut.

Gruß
Blockmove
 
Hey,
Zunächst mal vielen Dank für deine Antwort! Das klingt alles ziemlich logisch, zumal ja "Float" gar nicht wählbar ist im Tia.
Mit fixem Empfangsbuffer meinst du was genau?
Ich habe mal einen Datenbaustein mit genau dem Paket was geliefert werden soll angelegt. Also genau diese Struktur mit den verschiedenen Arrays. Für die Float-Variablen habe ich erst mal Real eingetragen. Ich hoffe damit komme ich erst mal weiter. Wenn es darum geht ein paar Bytes zu schubsen ist da halt - je nach dem ob der Hersteller hilft oder nicht - viel Arbeit, aber es sollte machbar sein.
Ich werde das ganze die Tage mal ausprobieren und mich nochmal melden.

Viele Grüße,
Mark
 
Zuletzt bearbeitet:
Real = Float nach IEEE754, sollte also passen.

Ein paar Hinweise dazu noch:
a) Der DB muss "nicht optimiert" sein
b) Aufpassen musst du auf die Byte Reihenfolge, Stichwort Big / LittleEndian
c) Siemens fänge immer an einer geraden Byte-Adresse an, d.h. im UDP Typ hast du eine ungerade Anzahl an Bytes, bevor das nächst Float kommt, ab hier ist im DB dann ein Byte Versatz, hierzu nach dem übersetzen des DBs die Offset Spalte beachten
d) Prinzipiell sollte das aber mit ein wenig schieberei etc. ohne größere Probleme machbar sein

Mfg
Manuel
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo MSB,
Danke für die Antwort.
Die Kommunikation ist hergestellt und ich bekomme fleissig Daten rein. Die Daten sind - wie du vermutet hast - "vertauscht" sodass ich sie nun drehen muss. Daran setze ich mich die Tage.
Was du unter c.) geschrieben hast verstehe ich noch nicht ganz. Ich soll den Offset anpassen, damit die Daten wieder stimmen? Ich habe mal ein Bild von meinem DB hochgeladen. Wenn du es mir anhand des Bildes nochmal kurz erklären könntest wäre das super ;)
daten.JPG

Vielleicht noch interessant:
In einer Beobachtungstabelle habe ich mal das Anzeigeoformat der "m_time"-Variable geändert. Auffällig war, dass die ersten 2 Bytes (links vom schwarzen strich) sich verändert haben wie verrückt und die letzten beiden kaum. Das hat bestimmt auch etwas mit dem Big/Little Endian zu tun?
daten2.JPG
Viele Grüße und danke für deine Hilfe!
Mark
 
Zuletzt bearbeitet:
Mit c) bezog ich mich unter anderem auf den Abschnitt, der Einfachheit wg. habe ich jetzt mal bei 0 begonnen.
Code:
[COLOR=#ff0000]0[/COLOR]    float m_session_time_left;  // [B]NEW:[/B] time left in session in seconds 
[COLOR=#ff0000]4[/COLOR]    byte  m_rev_lights_percent;  // [B]NEW: [/B]rev lights indicator (percentage)
[COLOR=#ff0000]5[/COLOR]    byte  m_is_spectating;  // [B]NEW: [/B]whether the player is spectating
[COLOR=#ff0000]6[/COLOR]    byte  m_spectator_car_index;  // [B]NEW: [/B]index of the car being spectated


    // Car data
[COLOR=#ff0000]7[/COLOR]    byte  m_num_cars;                  // number of cars in data
[COLOR=#ff0000]8[/COLOR]    byte  m_player_car_index;            // index of player's car in the array
[COLOR=#ff0000]Streng nach Beschreibung ginge hier nun also ab Byte 9 CarUDPData, im DB geht es aber bei Byte 10 weiter.[/COLOR]
[COLOR=#ff0000]10[/COLOR]    CarUDPData  m_car_data[20];       // data for all cars on track

Du hast z.B. zwischen den Float m_session_time_left, und dem UDT-Array m_car_data z.B. 5 Byte stehen, rot habe ich jetzt einfach mal den Offset eingetragen ...Geh mal auf den Abschnitt in deinem DB und zeige die Offset Spalte.

Ja, du hast definitiv ein Big/Little Endian Problem, z.B. m_car_Position, hat in deinem Bild einen HEX-Wert von 16#803F, zurechtgerückt (TAD / SWAP), entspräche das einen Wert von 1.0 .

Mfg
Manuel
 
Hey,
Dank für die Antwort!
Die Zeilen im DB habe ich mir angeschaut und sie sind tatsächlich verschoben. Gibt es da keine Möglichkeit den Offset zu verändern? Ich wüsste da grade keine Alternative als den DB ab dem Punkt in Bytes aufzubauen und mir die Werte einzeln rauszusuchen. Das macht die Sache ja wirklich kompliziert.
TAD/SWAP versuche ich mich gleich mal dran! Danke

Viele Grüße,
Mark
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
das mit dem offset kannst du nicht ändern. s7 beginnt bei einem wechselnden Datentyp immer mit dem geraden offset.
also ein Datentyp ist immer mindesten 16 bit breit.
entweder du sortierst dir die Daten so das nur am ende ein Byte oder so falsch ist (was die Sache aber evtl unübersichtlich macht) oder du fügst an den entsprechenden stellen dummy-bytes (so würde ich das machen) ein.
 
Vielen Dank für deine Antwort.
Das mit den dummy-byte habe ich gerade versucht. Das Problem ist ja dann, dass auch dort Informationen reingeschrieben werden die ich dann wohl weiter sortieren müsste.
Ich komme wohl nicht drumrum den DB ab dann Byteweise zu betrachten.

Ich habe - leider erst spät - folgendes gelesen:
"The data is sent as raw data in the UDP packet, converted to a char array, with packing enabled (no padding to align different sized types). To decode this into something usable it should be a case of casting the packet data back to the UDPPacket struct (or another structure with the same layout). The layout of the UDP data is as follows:"

Weiß jemand ob das mein Packet, bzw. so wie ich es lese, beeinflusst? Bisher habe ich nicht daran gedacht irgendwelche character zu empfangen, sondern die puren Nullen und Einsen. Vielleicht zu kompliziert gedacht?

Viele Grüße,
Mark
 
Zuletzt bearbeitet:
Hallo zusammen,

Ich möchte mich nur nochmal bei allen Beteiligten bedanken. Ihr habt mir sehr weitergeholfen und das Projekt kommt so langsam in Fahrt ;)! Danke!
 
Zurück
Oben