# Beckhoff Date and Time an S7



## dr1101 (1 Juli 2011)

hallo zusammen,

ich habe ein problem. ich soll eine produktdatenverfolgung programmieren. die daten werden von eine Beckhoff an eine S7 geschickt, dort verarbeitet, und später wieder zurück geschrieben. funktioniert soweit. nur die date and time- variable von beckhoff nach S7 kommt nicht im richtigen format an, so dass ich sie problemlos in wincc anzeigen kann.
wie kann ich im beckhoff-system die date and time- variable so konvertieren, das ich sie in S7 lesen kann? gibt es hier eine bestimmte konverterfunktion?
vielen dank für antworten.

gruß dr1101.


----------



## uncle_tom (1 Juli 2011)

Servus,

Step7 speichert den Datentyp Date-and-Time BCD codiert in 8 Byte - der genaue Byte-Aufbau ist in der Step 7 Online Hilfe sehr gut beschrieben.

Codesys bzw. Twincat speichert den Datentyp Date-and-Time in 4 Byte. Der Aufbau entspricht dabei Sekunden seit dem 01.01.1970 00:00:00 Uhr.

Mit diesen Infos sollten sich eigentlich entsprechende Umwandlungsfunktionen realisieren lassen.

Fertige FB´s oder FC´s sind mir auch keine bekannt. Vielleicht gibt ja die Oscat.lib etwas her http://www.oscat.de/

Mfg
uncle_tom


----------



## uncle_tom (3 Juli 2011)

Hallo nochmal,

das DT-Format bei Codesys bzw. Twincat entspricht *Sekunden* seit dem 01.01.1970 und nicht Millisekunden - ich habs jetzt ausgebessert.

Somit entspricht dieses Format der Unixzeit. Wobei Codesys keine negativen Werte und somit keine Datumsangaben vor dem 01.01.1970 kennt - dafür reichen dann aber die 32-Bit bis zum 06.02.2106 wärend bei der normalen vorzeichenbehafteten 32-Bit Unixzeit am 19.01.2038 Schluss ist - Jahr 2038 Problem.

Bzgl. der Umwandlung des S7-Zeitstempels (8-Byte) zum 4-Byte Unix-Zeitstempel gibt´s hier im Forum bereits eine Lösungsmöglichkeit
von argv_user Link. Wenn du diesen, so in Step7 erzeugten Zeitstempel, jetzt einer Beckhoff vorsetzt, dann hast du allerdings derzeit eine Differenz von 2 Stunden, da die Unixzeit von UTC ausgeht und wir ja derzeit Sommerzeit (UTC+2) haben.

Die Retour-Funktion also Unix-Zeitstempel nach S7-Zeitstempel wandeln funktioniert in Anlehung an den Code von argv_user ähnlich - Rechnung rückwärts.

In der Step7 Variante der Ocat-Lib findest du diesbezgl. im Ordner xxS7 auch die Funktionen FC399 und FC400 (DT_DINT und DINT_DT) - die sollten dir auch weiterhelfen.

Du könntest natürlich auch auf der Beckhoff-Seite den Siemens Date_and_Time Datentyp nachbilden, dann musst du aber jeweils 8-Byte von Beckhoff zu Siemens übertragen. Somit ist es vermutlich effizienter wenn du die 4-Byte DT´s von Beckhoff in die S7 überträgst und dort umrechnest.

Evtl. (kenn mich mit WinCC jetzt nicht so aus) - unterstützt WinCC auch direkt den Unix-Zeitstempel von Beckhoff. WinCCflexible kann es nicht - vielleicht kann es aber das grosse WinCC.

Wenn du dennoch deine Zeitstempel gleich auf der Beckhoff-Seite in S7-kompatible Zeitstempel umwandeln willst, dann hilft dir vielleicht folgender FC weiter:


```
FUNCTION F_DT_TO_DT8BSIE : ARRAY [1..8] OF BYTE    (*DateTime im 8-Byte Siemens Format*)
VAR_INPUT
    DT_In :             DT;        (*DateTime im Beckhoff-/Codesys Format*)
END_VAR
VAR
    stTimeStruct :         TIMESTRUCT;
    uZehner:             BYTE;
    uEiner:             BYTE;
    uJahr :             BYTE;
    uJahrZehnt :         BYTE;
    uTemp :             WORD;
    uHunderter:         BYTE;

END_VAR


(*DateTime in Timestruct umwandeln*)
stTimeStruct := DT_TO_SYSTEMTIME(DT_In);

(*DateTime 8-Byte Siemens zusammenstellen*)

(*Jahr*)
uJahrZehnt := WORD_TO_BYTE(stTimeStruct.wYear MOD 100);
uZehner := uJahrZehnt / 10;
uEiner := uJahrZehnt MOD 10;
F_DT_TO_DT8BSIE[1] := (uZehner * 16) + uEiner;

(*Monat*)
uZehner := WORD_TO_BYTE(stTimeStruct.wMonth) / 10;
uEiner := WORD_TO_BYTE(stTimeStruct.wMonth) MOD 10;
F_DT_TO_DT8BSIE[2] := (uZehner * 16) + uEiner;

(*Tag*)
uZehner := WORD_TO_BYTE(stTimeStruct.wDay) / 10;
uEiner := WORD_TO_BYTE(stTimeStruct.wDay) MOD 10;
F_DT_TO_DT8BSIE[3] := (uZehner * 16) + uEiner;

(*Stunde*)
uZehner := WORD_TO_BYTE(stTimeStruct.wHour) / 10;
uEiner := WORD_TO_BYTE(stTimeStruct.wHour) MOD 10;
F_DT_TO_DT8BSIE[4] := (uZehner * 16) + uEiner;

(*Minute*)
uZehner := WORD_TO_BYTE(stTimeStruct.wMinute) / 10;
uEiner := WORD_TO_BYTE(stTimeStruct.wMinute) MOD 10;
F_DT_TO_DT8BSIE[5] := (uZehner * 16) + uEiner;

(*Sekunde*)
uZehner := WORD_TO_BYTE(stTimeStruct.wSecond) / 10;
uEiner := WORD_TO_BYTE(stTimeStruct.wSecond) MOD 10;
F_DT_TO_DT8BSIE[6] := (uZehner * 16) + uEiner;

(*Millisekunden (Hunderter/Zehner)*)
uTemp := stTimeStruct.wMilliseconds / 10;
uEiner := WORD_TO_BYTE(stTimeStruct.wMilliseconds) MOD 10;
uZehner := WORD_TO_BYTE(uTemp) MOD 10;
uHunderter := WORD_TO_BYTE(uTemp) / 10;
F_DT_TO_DT8BSIE[7] := (uHunderter * 16) + uZehner;

(*Millisekunden (Einer)*)
F_DT_TO_DT8BSIE[8] := SHL(uEiner,4);

(*Wochentag umlegen (Wochentag bei Beckhoff --> 0=Montag - 6=Sonntag) (Wochentag bei Siemens --> 1= Sonntag ... 7=Samstag)*)
CASE stTimeStruct.wDayOfWeek OF
    0: (*Montag*) F_DT_TO_DT8BSIE[8] := F_DT_TO_DT8BSIE[8] + 2;
    1: (*Dienstag*) F_DT_TO_DT8BSIE[8] := F_DT_TO_DT8BSIE[8] + 3;
    2: (*Mittwoch*) F_DT_TO_DT8BSIE[8] := F_DT_TO_DT8BSIE[8] + 4;
    3: (*Donnerstag*) F_DT_TO_DT8BSIE[8] := F_DT_TO_DT8BSIE[8] + 5;
    4: (*Freitag*) F_DT_TO_DT8BSIE[8] := F_DT_TO_DT8BSIE[8] + 6;
    5: (*Samstag*) F_DT_TO_DT8BSIE[8] := F_DT_TO_DT8BSIE[8] + 7;
    6: (*Sonntag*) F_DT_TO_DT8BSIE[8] := F_DT_TO_DT8BSIE[8] + 1;
END_CASE
```
Ich hab den FC jetzt nicht auf Herz und Nieren geprüft - sollte aber soweit funktionieren. Die verwendete Funktion DT_TO_SYSTEMTIME findest du in der TcUtilities.lib von Beckhoff.

Mfg
uncle_tom


----------



## dr1101 (4 Juli 2011)

hallo,

danke für die antworten. ich habe mir, wie auch beschrieben die S7 date and time struktur schon im beckhoff-system konvertiert. die milisekunden habe ich einfach fest auf 0 geschrieben (war für meine zwecke nicht relevant). ich wollte den wochentag auch auf 0 schreiben, nur akzeptiert das s7 anscheinend nicht. s7 erwartet für das datum den entsprechenden wochentag.

gruß


----------



## thomas187 (8 November 2013)

Hallo Uncle_Tom,
erst mal vielen Dank für den geposteten FC: F_DT_TO_DT8BSIE. 
Ich schreibe mit TwinCat 2.11 einen Kommunikationsbaustein, welcher Telegramme mit einer S7 austauscht. Zum Versenden des Zeitstempels aus Beckhoff zu Siemens hat mir Ihr FC sehr weitergeholfen. Allerdings muss ich auch die Antwort der S7 mit Beckhoff auswerten und muss dazu den S7 Timestamp auf Beckhoff-Seite wieder zurück in 4Byte konvertieren. Vielleicht können Sie mir auch dabei weiterhelfen?
Besten Dank im Voraus
mfg
Thomas


----------



## uncle_tom (8 November 2013)

Hallo,

das ist jetzt zwar schon eine Weile her - ich hab´ aber auch die Umkehrfunktion (8-Byte Siemens DT nach Beckhoff DT) in der Schublade.

Probier es mal damit:


```
FUNCTION F_DT8BSIE_TO_DT : DT                (*DateTime im Beckhoff-/Codesys Format*)
VAR_INPUT
    DT8BSIE :         ARRAY[1..8] OF BYTE;        (*DateTime im 8-Byte Siemens Format*)
END_VAR
VAR
    stTimeStruct :         TIMESTRUCT;
    uZehner:             BYTE;
    uEiner:             BYTE;
END_VAR


(*TimeStruct aus 8-Byte Siemens DateTime zusammenstellen*)

(*Jahr (0-99 entspricht bei Siemens 1990 - 2089)*)
uEiner := DT8BSIE[1] MOD 16;
uZehner := DT8BSIE[1] / 16;

IF DT8BSIE[1] < 9 THEN
    stTimeStruct.wYear := 1990 +  (BYTE_TO_WORD((uZehner * 10) + uEiner));
ELSE
    stTimeStruct.wYear := (2000 +  (BYTE_TO_WORD((uZehner * 10) + uEiner)) - 10);
END_IF

(*Monat*)
uEiner := DT8BSIE[2] MOD 16;
uZehner := DT8BSIE[2] / 16;
stTimeStruct.wMonth := BYTE_TO_WORD((uZehner * 10) + uEiner);

(*Tag*)
uEiner := DT8BSIE[3] MOD 16;
uZehner := DT8BSIE[3] / 16;
stTimeStruct.wDay := BYTE_TO_WORD((uZehner * 10) + uEiner);

(*Stunde*)
uEiner := DT8BSIE[4] MOD 16;
uZehner := DT8BSIE[4] / 16;
stTimeStruct.wHour := BYTE_TO_WORD((uZehner * 10) + uEiner);

(*Minute*)
uEiner := DT8BSIE[5] MOD 16;
uZehner := DT8BSIE[5] / 16;
stTimeStruct.wMinute := BYTE_TO_WORD((uZehner * 10) + uEiner);

(*Sekunde*)
uEiner := DT8BSIE[6] MOD 16;
uZehner := DT8BSIE[6] / 16;
stTimeStruct.wSecond := BYTE_TO_WORD((uZehner * 10) + uEiner);

(*Millisekunde*)
uEiner := DT8BSIE[7] MOD 16;
uZehner := DT8BSIE[7] / 16;

stTimeStruct.wMilliseconds := BYTE_TO_WORD((uZehner * 10) + uEiner);

(*Wochentag umlegen (Wochentag bei Siemens --> 1= Sonntag ... 7=Samstag) (Wochentag bei Beckhoff --> 0=Montag - 6=Sonntag)*)
CASE DT8BSIE[8] OF

    1:  (*Sonntag*) stTimeStruct.wDayOfWeek := 6;
    2: (*Montag*) stTimeStruct.wDayOfWeek := 0;
    3: (*Dienstag*) stTimeStruct.wDayOfWeek := 1;
    4: (*Mittwoch*) stTimeStruct.wDayOfWeek := 2;
    5: (*Donnerstag*) stTimeStruct.wDayOfWeek := 3;
    6: (*Freitag*) stTimeStruct.wDayOfWeek := 4;
    7: (*Samstag*) stTimeStruct.wDayOfWeek := 5;

END_CASE


(*TimeStruct String in DateTime wandeln*)
F_DT8BSIE_TO_DT := SYSTEMTIME_TO_DT(stTimeStruct);
END_FUNCTION
```

die Funktion SYSTEMTIME_TO_DT sollte wieder in der TcUtilities.lib zu finden sein.

Das ganze aber wieder ohne Gewähr - ich hab die beiden FC´s selber auch nicht im produktiven Einsatz - die FC´s sind nur aus Spielerei entstanden


----------



## tomatensaft (13 November 2013)

*Verbindung Beckhoff -> S7*

Hallo, ich weiß das passt jetzt nicht zum Thema, aber wie hast du denn die Verbindung zur S7 gelöst?
 Muss demnächst auch Daten von einer Beckhoff auf eine S7 schieben und umgekehrt. Kannst du mir da schon mal einen Tipp im Voraus geben ?


----------



## uncle_tom (14 November 2013)

Hallo tomatensaft,

bzgl. Kommunikation zwischen Beckhoff- und Siemens-Welt gibt es mehrere Möglichkeiten.

Du solltest erstmal die Physik festlegen.
Da bietet sich dann z.B. Ethernet oder Profibus an.

Ich würde Ethernet vorziehen, da diese Schnittstelle bei Beckhoff zu 95% bereits vorhanden ist.
Bei Siemens kommen bei neuen Steuerung ja auch meist Profinet-CPU´s zum Einsatz, somit ist da also Ethernet auch meist schon vorhanden.

Profibus wäre dann bei Siemens in der Regel schon vorhanden - auf Beckhoffseite bräuchtest du dann aber u.U. teure zusätzliche Hardware (Profibus-Karte, Onboard-Profibus CX, Ethercat-Klemme, etc.).


Bleiben wir bei Ethernet, dann muss als 2te Frage das Protokoll geklärt werden.

Bei Profinet-fähiger Siemens-CPU bietet sich evtl. auch Profinet auf Beckhoff-Seite an - hierfür wird dann bei Beckhoff ein kostenpflichtiges Supplement benötigt.

Als weitere Möglichkeit gibt es dann noch softwareseitige Protokolle über Ethernet, wobei hier dann vermutlich "Modbus-TCP" die erste Wahl ist.
Für Modbus-TCP benötigst du auf Beckhoff-Seite ein kostenpflichtiges Supplement und auf der Siemens-Seite u.U. auch einen kostenpflichtigen Treiber (zumindest bei S7 300/400).

Man könnte auch eine reine offene Ethernetkommunikation ohne Protokoll zwischen Beckhoff und Siemens aufbauen, bei der dann nur Rohdaten hin- und hergeschickt werden.
Hierfür braucht man bei Siemens keine weitere Lizenz - das ist mit Standardbausteinen realisierbar. Bei Beckhoff benötigst du hierfür wieder ein kostenpflichtiges Supplement, da sonst keinerlei Socket-Verbindungen gehandelt werden können.

Es gibt bei Beckhoff dann auch noch eine Speziallösung:
Hierzu gibt es ein kostenpflichtiges Supplement, mit dem man softwareseitig über einen Net-Link (IBH, Deltalogic, etc.), mit einer Siemens-Steuerung kommunizieren kann.


Wenn du ganz ohne Lizenzkosten auskommen willst, dann könntest du auch das Beckhoff-ADS Protokoll in der Siemens-Steuerung umsetzen.


Die Auswahl des richtigen Kommunikationsweges hängt also von vielen Faktoren ab.
Ich würde dir Modbus-TCP empfehlen.


----------



## tomatensaft (15 November 2013)

Hallo,

danke für die Antwort. Ja Profibus kommt für mich da nicht in Frage. Der Kommunikationsweg soll Ethernet sein.
Das mit Modbus-Tcp klingt eigentlich ganz gut - hast du das bei dir mit Modbus realisiert ?


----------



## uncle_tom (15 November 2013)

tomatensaft schrieb:


> Hallo,
> 
> Das mit Modbus-Tcp klingt eigentlich ganz gut - hast du das bei dir mit Modbus realisiert ?



Nein, ich habe die "billige" Variante genommen, und habe auf S7 300/400 Basis einen ADS-Treiber aufgesetzt.
Die S7 kann damit per ADSREAD, ADSWRITE mit Beckhoff-Steuerungen plaudern.
Weiterhin können Beckhoff-Steuerungen auch per ADSREAD, ADSWRITE mit der S7 plaudern.

Ich habe aber sowohl bei S7 300/400 als auch bei Beckhoff schon mit Modbus-TCP gearbeitet - das funktioniert schon.


----------

