WinCC V7 - Datentyp TIME OF DAY

RONIN

Level-3
Beiträge
2.538
Reaktionspunkte
776
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo Leute.

Ich hab mich gerade gefragt ob man unter WinCC v7.2 den Datentyp "Time of Day" anzeigen / eingeben kann.
Innerhalb des Forums gibt's leider nur Beiträge zu WinCCflex und das allmächtige Internet hat auch ein schlechten Tag.

Es gibt in WinCC zwar den Datentyp "Vorzeichenloser 32-Bit Wert" mit der Formatanpassung "DwordToSimaticLTimeOfDay".
Jedoch hab ich bei versuchen nix brauchbares damit bekommen:

Hier ein paar Beispiele mit dieser Einstellung: L#41897611 entspricht TOD#11:38:17.611
(Die Fettmarkierung zeigt wo der Wert eingegeben wurde)
Code:
CPU                 Zeit                       WinCC
[B]L#41897611 [/B]         TOD#11:38:17.611           Error
L#9755              TOD#00:00:09.755          [B] 41897611[/B]
leider nicht sonderlich hilfreich. Am E/A-Feld mit dem ich es versucht habe, habe ich alle Dastellungsvarianten (dez, string, hex) durchprobiert.
Auch mit einem Statischen Text (mit dem kann man oft die meisten Werte zumindest irgendwie darstellen) hatte ich keine Erfolg.

Weiß jemand was?
 
Musst mal probieren ob das bei WinCC funktioniert, wenn man an ein EA-Feld bei Eingabe und bei Ausgabe verschiedene C-Skripte anbindet.
Das EA-Feld sollte dann Datentyp string ausgeben. Bei Ausgabe wird der SPS TOD-Wert in dem Skript in ein String gewandelt, und bei Eingabe der String in ein TOD gewandelt und bei korrekter Eingabe in die SPS geschrieben. Evtl. sind dazu zwei EA-Felder notwendig.

Von Time_Of_Day nach String ist ja noch relativ einfach, rückwärts wird es etwas aufwändiger weil die Eingabe auf Gültigkeit geprüft werden muss.

Time_Of_Day nach String z.B. so (in WinCC könnte man den Speicher für den String noch mit SysMalloc anfordern, dann entfällt der Parameter und es gibt den string als Rückgabewert):
Code:
// str muss Speicher für 23:59:59.999 -> min. 13 Stellen besitzen
void TimeOfDayToString(unsigned long time_of_day, char *str)
{
	if (time_of_day > 86399999ul) {
		time_of_day = 86399999ul;
	}
	sprintf(str, "%02lu:%02lu:%02lu.%03lu",
		(time_of_day / 3600000ul), 
		(time_of_day % 3600000ul) / 60000ul, 
		((time_of_day % 3600000ul) % 60000ul) / 1000ul,
		((time_of_day % 3600000ul) % 60000ul) % 1000ul
	);
}

Von String nach Time_Of_Day habe ich es wie folgt gemacht. Ist etwas aufwändig, fängt aber alle Fehleingaben ab. Da mit atoi keine Fehler festgestellt werden können, werden die Zeichen vorher auf Gültigkeit geprüft. Evtl. könnte man das auch mit strtok lösen, aber damit wird es mit einer Prüfung der Eingabe auch nicht viel kürzer.

Stunden, Minuten, Sekunden müssen angegeben werden, Millisekunden sind optional. Wird ein Millisekunden-Punkt angegeben, muss auch ein Wert folgen.
Erlaubt wären "1:2:3" oder "2:3:4.9". Nicht erlaubt sind "1", "1:2" oder "1:2:3.".
Code:
#define ERR_STRING_ZU_LANG       1
#define ERR_UNGUELTIGES_ZEICHEN  2
#define ERR_STELLENANZ_H_M_S     3
#define ERR_STELLENANZ_MS        4
#define ERR_H_M_S_NICHT_VOLLST   5
#define ERR_MS_NICHT_VOLLST      6
#define ERR_WERTUEBERSCHR_H      7
#define ERR_WERTUEBERSCHR_M      8
#define ERR_WERTUEBERSCHR_S      9
#define ERR_WERTUEBERSCHR_MS     10

// Eine Eingabe 0:0:0.1 wird als 00:00:00.001 interpretiert.
unsigned long StringToTimeOfDay(const char *str, int *error)
{
	int i, j;
	int h = 0, m = 0, s = 0, ms = 0;
	char sVal[4][4];
	int stage;
	sVal[0][0] = '\0';
	sVal[1][0] = '\0';
	sVal[2][0] = '\0';
	sVal[3][0] = '\0';

	if (strlen(str) > 12) {
		*error = ERR_STRING_ZU_LANG;
		return 0;
	}
	stage = 0;
	j = 0;
	for (i = 0; i < strlen(str); i++) {
		if (str[i] >= '0' && str[i] <= '9') {
			sVal[stage][j] = str[i];
			if (stage < 3 && j >= 2) {
				*error = ERR_STELLENANZ_H_M_S;
				return 0;
			} else if (j >= 3) {
				*error = ERR_STELLENANZ_MS;
				return 0;
			}
			j++;
		} else if (str[i] == ':') {
			sVal[stage][j] = '\0';
			stage++;
			j = 0;
		// Millisekunden sind nur erlaubt nach allen drei vorherigen Stufen
		} else if (stage == 2 && str[i] == '.') {
			sVal[stage][j] = '\0';
			stage = 3;
			j = 0;
		} else {
			*error = ERR_UNGUELTIGES_ZEICHEN;
			return 0;
		}
	}
	// Wurde ein Punkt angegeben, so muss auch ein Wert für Millisekunden folgen
	if (stage == 3 && strlen(sVal[3]) == 0) {
		*error = ERR_MS_NICHT_VOLLST;
		return 0;
	}
	// Auf Gültigkeit prüfen. Es müssen Stunden, Minuten und Sekunden angegeben sein.
	for (i = 0; i <= 2; i++) {
		if (strlen(sVal[i]) < 1) {
			*error = ERR_H_M_S_NICHT_VOLLST;
			return 0;
		}
		switch (i){
			case 0:
				h = atoi(sVal[i]);
				if (h > 23) {
					*error = ERR_WERTUEBERSCHR_H;
					return 0;
				}
				break;
			case 1:
				m = atoi(sVal[i]);
				if (m > 59) {
					*error = ERR_WERTUEBERSCHR_M;
					return 0;
				}
				break;
			case 2:
				s = atoi(sVal[i]);
				if (s > 59) {
					*error = ERR_WERTUEBERSCHR_S;
					return 0;
				}
				break;
		}
	}
	if (strlen(sVal[3]) > 0) {
		ms = atoi(sVal[3]);
		if (ms > 999) {
			*error = ERR_WERTUEBERSCHR_MS;
			return 0;
		}
	}
	*error = 0;
	return (h * 3600000ul + m * 60000ul + s * 1000ul + ms);
}
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Die Formatanpassung "DwordToSimaticLTimeOfDay" scheint übrigens nur für die S7-1500 zu sein, denn dort gibt es auch einen entsprechenden Datentyp LTime_Of_Day, bzw. LTOD, mit 8 Bytes Länge.
Wäre auch zu schön gewesen, dass WinCC mal endlich mit den elementaren Datentypen der eigenen Steuerungen umgehen könnte.
 
@Thomas: Zuerst mal sorry, für die späte Reaktion auf deine tolle Antwort und gleich mal ein großes WOW :sm7: hinterher.

Als ich den Beitrag verfasst hatte war ich vor allem daran interressiert ob es Siemens mit WinCC v7.2, es endlich mal geschafft hat
mehr Datentypen aus seiner eigenen Steuerung zu supporten, tja wer hofft wird halt auch enttäuscht.

Lustig ist noch dazu, kaum hatte ich den Beitrag abgeschickt kam mir so die Idee im Kopf: "eigentlich könnt man das ja mit Skripten
machen, so mit Doppelpunkten und Zeugs zwischendrin". Dachte mir dann aber:
"Ah, zu aufwändig. Wenn ich das mache und jemand sieht mich dabei dass ich bei einem einfachen Zeit-EA-Feld solchen Aufwand betreibe,
fragt sich der bestimmt ob ich Sie noch alle beisammen habe".
Hatte im Moment auch mit anderem Blödsinn rum-experimentiert.

Und dann kommt doch tatsächlich einer ums Eck und posted eine, dem Aussehen nach, fertige Lösung für meinen "wilden" Gedanken.
Ich hab mich echt am Tisch festhalten müssen. *ROFL*
Rein deswegen muss ich deine Lösung schon ausprobieren. Hattest du das schon so rumliegen?

Die Formatanpassung "DwordToSimaticLTimeOfDay" scheint übrigens nur für die S7-1500 zu sein, denn dort gibt es auch einen entsprechenden Datentyp LTime_Of_Day, bzw. LTOD, mit 8 Bytes Länge.
Wäre auch zu schön gewesen, dass WinCC mal endlich mit den elementaren Datentypen der eigenen Steuerungen umgehen könnte.
Vielen dank und AMEN.
 
Zuletzt bearbeitet:
Zurück
Oben