Frame in 23 Bytes

GeorgSei

Level-1
Beiträge
58
Reaktionspunkte
1
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo, ich habe noch nicht viel Erfahrung mit Profibus und deren Kommunikation. Vielleicht könnt Ihr mir da ja helfen.

Ich habe ein Sensor der über Profibus angesteuert wird. Das Protokoll (Frame) zum steuern dieses Sensor ist 23 Byte groß

Code:
Adresse: 50 - Byte 0 - Eröffnungsbyte 0xA5 Hexadezimal
Adresse: 51 - Byte 1 - Header Byte
Adresse: 52 - Byte 2 - Sender-Adresse
Adresse: 53 - Byte 3 - Empfänger-Adresse
Adresse: 54 - Byte 4 - Kommando Byte
Adresse: 55 - Byte 5 - Subkommando Byte
Adresse: 56...61 - Byte 6 bis 21 - Parameter / Rückgabewert
Adresse: 62...63 - Byte 22/23 - CRC Checksumme


Der Frame sieht so aus

Code:
A550000001000000000000000000000000000000000069EF


Ich habe die Bytes wie in der Doku beschrieben angelegt. Aber wie bekomme ich nun den Frame in die einzelnen Bytes rein bzw. könnte ich einfach den gesamten Frame an die erste Adresse schicken und die SPS weiß das der Rest zu den anderen Adressen gehört?

Ich hatte mir auch überlegt den Frame immer in 2 Zeichen zu splitten und dann diesen einfach an die jeweilige Adresse zu schicken.

Die Rückmeldung kommt dann genauso in diesem Frame zurück und die Antwort liegt dann in Byte 6-21...

Ich habe auch ein Beispiel in C in der Doku gefunden, damit kann ich aber nun garnix mit anfangen :D

Code:
Payload Definition sowie CRC Berechnung in C
Implementation of Payload in C

typedef union _PAYLOAD{
 int data_i[4];
 char data_c[16];
 short data_s[8];
 float data_f[4];
 
 unsigned long long data_ull[2];
 double data_d[2];
}PAYLOAD;

CRC polynom

𝑥𝑥16 + 𝑥𝑥15 + 𝑥𝑥2 + 1 (0xA001)

CRC calculation implementation (C implementation)

unsigned short crc16(unsigned short crc, unsigned char a)
{
    int i=0;
 
    crc&=0x0000FFFF;
    crc^=a;
    for(i=0;i<8;++i)
    {
        if(crc&1)
            crc=(crc>>1)^0xA001;
      
else
            crc=(crc>>1);
    }
    return crc;
}


CRC Frame enryption (C implementation – calling „crc16“ function) 
#define VAC_FRAME_SIZE 24 
#define CRC_16_SIZE 2 
 
unsigned short crc_calc_16(char *buffer) 
{ 
    int i=0; 
    unsigned short crc_next=0xFFFF; 
 
    for(i=0;i<VAC_FRAME_SIZE-CRC_16_SIZE;i++) 
    { 
       crc_next=crc16(crc_next, buffer[i]); 
    } 
    return crc_next; 
}
 
Hallo,
  • Adresse 50-63 sind aber 14 Bytes, da stimmt schon mal was nicht.
  • Sind diese Parameter zum Senden und Empfangen (beide gleiche Größe)?
Bei einer Siemens S7-1200 bzw. 1500 und TIA (du hast leider nicht verraten welche Steuerung und welche Software) könnte man das so aufbauen:

Als erstes würde einen Datentyp erstellen, dann wird alles etwas einfacher / übersichtlicher:
1681805103529.png

Dann kannst du diesen Datentype bei deiner Adresse in den PLC Variablen angeben.
Wenn Sende/Empfang gleiche Größe/Aufbau hat, würde das dann so aussehen:
1681805244240.png
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo Peter,

sorry ja Glaskugel ist immer doof :D Es geht um eine S7 1200 Tia Portal 15.1 U8. Stimmt da hatte ich mich vertan das letzte Byte ist die 73. Das Sende & Empfangs Frame sind gleich groß beim Empfangen wird der Paylod 6...21 bloß verschieden groß.

1681805519031.png
Da weiß ich auch noch nicht wie ich das realisieren soll.

Empfangen:
1681805646738.png

Senden:
1681805967591.png
 
Zuletzt bearbeitet:
So sieht ein Beispiel in der Doku aus... Oben das Sendeframe in Hex für die Anfrage des Gerätenamens und unten dann die Antwort.

1681805759588.png
 
Ja, dann hast du doch schon deine Bereiche, ich würde die jedoch vorschlagen, einen Datentyp zu erstellen und in diesem die Payload als array zu definieren:
1681806795785.png

und wie schon geschrieben, setzt du in deiner PLC Variablentabelle dann nur jeweils bei den Empfang bzw. Sendedaten das erste Bit mit Datentyp eintragen: (nur die markieren Stellen eintragen der Rest wird vom Datentype übernommen)
1681807080055.png
 
Danke habe ich jetzt auch so gemacht die Datentypen hatte ich gar nicht auf dem schirm :D

Jetzt muss ich nur noch herausfinden wie ich den Frame jetzt aufsplitten kann und das mit der Checksumme muss ich auch noch herausfinden :D

Der Frame wird als Hex zurückgegeben wenn ich das richtig verstehe
 
Danke habe ich jetzt auch so gemacht die Datentypen hatte ich gar nicht auf dem schirm :D

Jetzt muss ich nur noch herausfinden wie ich den Frame jetzt aufsplitten kann und das mit der Checksumme muss ich auch noch herausfinden :D

Der Frame wird als Hex zurückgegeben wenn ich das richtig verstehe
Hex ist nur eine Darstellungsform, Char ist eine andere, der Byteinhalt ist der selbe.

Das mit dem Aufsplitten ist einfacher, wenn die Payload-Daten wie in meinem Beispiel als Array z.B.: (Array[6..21] of Char) vorliegen.
 
Das kommt auf die Daten an, die in dem Payload liegen, z.B. kannst du in einem Array die einzelnen Zeichen direkt ansprechen (oder das ganze Array), weiterhin kannst du relativ einfach aus deinem Char Array einen String erzeugen (String Aufbau beachten!).

Du weißt, welche Daten du erhältst (bzw. erwartest) und welche Daten du senden willst, danach musst du dann die Auswertung / Sendedaten anpassen, bei deinem Beispiel bekommst du z.B. den Text "NOVION" zurück, da würde ein Array of Char mit evtl. Weiterverwendung als String sinnvoll sein.
 
Wie findet man das denn raus?
Was willst Du denn herausfinden? Das hier?
Der Frame wird als Hex zurückgegeben wenn ich das richtig verstehe
Die Hex-Darstellung wird gerne in Dokumentationen verwendet, weil sie eindeutig, platzsparend und gut lesbar/schreibbar ist. Nicht alle BitMuster lassen sich als z.B. ASCII-Zeichen darstellen/deuten.
Warum geraten immer alle in Panik, wenn es um das Hex-Format geht (so, wie ich immer in Panik gerate, wenn es um das Oct-Format geht ;o) ???
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Was willst Du denn herausfinden? Das hier?
Das ging auf die Frage von Peter zurück bezüglich ob der Payload in Klartext ist oder nicht.

Die Hex-Darstellung wird gerne in Dokumentationen verwendet, weil sie eindeutig, platzsparend und gut lesbar/schreibbar ist. Nicht alle BitMuster lassen sich als z.B. ASCII-Zeichen darstellen/deuten.
Warum geraten immer alle in Panik, wenn es um das Hex-Format geht (so, wie ich immer in Panik gerate, wenn es um das Oct-Format geht ;o) ???
Ich gerate nicht in Panik :D Wenn ich die Kommandos in Hex im ganzen übergeben könnte wäre ich froh :ROFLMAO: dann müsste ich nix aufsplitten.

Leider weiß ich nicht wie ich das für google umschreiben soll was ich da vor habe um was sinnvolles zu diesem Thema zu finde...
 
Wenn ich die Kommandos in Hex im ganzen übergeben könnte wäre ich froh :ROFLMAO: dann müsste ich nix aufsplitten.

Dann mach das doch einfach.

  1. In einem DB oder FB-Static eine Struktur oder ein Array mit der Größe der Payload anlegen.
  2. Dort die gewünschten Daten zusammenstellen
  3. wenn fertig, diese Array zum Array der SendePayload übertragen
1681816315197.png
 
Könnte man jetzt nicht einfach den ganzen Hexcode an den erstellten Datentyp schicken und dieser gibt es an die richtigen Adressen weiter?
 
Du kannst die kompletten Daten an den durch den Datentyp beschriebenen Ausgangsbereich schicken, siehe #15
1681820454690.png

Weil ich nicht weiß, ob die Daten gleichzeitig komplett gesendet werden müssen/sollen, stellst du die Daten erst in einem eigen Bereich (DB oder FB-Static) zusammen und dann kopierst du diese Daten in den zu deinem durch den DT beschriebenen Ausgangsbereich.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Es muss der gesamte Datentyp gesendet werden. z.B. A5 50 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 69 EF dies ist der Befehl für gebe mir den Gerätenamen zurück.

Ein anderes Kommando wäre wenn ich das richtig verstehe A5 40 00 00 81 11 0000 0010 0000 0000 69 EF dieser gibt an das der Spektrum Anfang bei 200 liegen soll.
1681822551844.png

Da sich der Paylod ja nachdem ändert welches Typ es ist muss sich da ja auch was ändern :(
 
Zuletzt bearbeitet:
Das ist mir schon klar, deshalb habe ich ja auch geschrieben, zuerst die Daten in einem DB oder in FB-static zusammenstellen und dann den gesamten Bereich zu deinem, durch den DT definierten, Ausgangsbereich übertragen.

1681823617219.png

Hier im Beispiel habe ich nur 4 Bytes gesetzt. Wenn du alles innerhalb eines SPS-Zyklus machst, kannst du natürlich auch direkt in die Ausgangsbytes schreiben.

Wenn du nur wenige Befehle (z.B.: 3) zum senden hast, kannst du natürlich auch in einem DB 3 Datenbereiche mit deinem Datentyp anlegen, dort Konstanten eintragen, und diese Bereiche bedarfsmäßig zu deinem, durch den DT definierten, Ausgangsbereich übertragen.
 
Zuletzt bearbeitet:
Zurück
Oben