TIME OF DAY <> WinCC V7

FinnAh

Level-1
Beiträge
47
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo zusammen,

ich möchte zwei Zeitangaben, welche von der SPS als TIME_OF_DAY an WinCC v7 (Vorzeichenloser 32-Bit Wert) gehen, anzeigen und ändern können.
Bisher habe ich diesen Post gefunden, jedoch habe ich Probleme mit der Einbindung in die E/A-Felder.

Könnt ihr mir da helfen?

Grüße
Finn
 
Mit meiner Funktion die du verlinkt hast sollte es so in der Art funktionieren:
Code:
unsigned long tod;
char *tod_string = SysMalloc(13);

tod = GetTagDWord("DeinTimeOfDayTag");
TimeOfDayToString(tod, tod_string);
return tod_string;
Das Skript musst du an den Ausgabwert deines EA-Feld anhängen, das sollte als Rückgabewert ein Zeiger auf ein char erwarten (char*).
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Danke schon mal für die Antwort, jedoch stehe ich etwas auf'm Schlauch.

Ich habe versucht diesen Code bei Eingabewert einzufügen, bekam leider da Fehler heraus. Wo definiere ich dann die Variable?
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
    );
}

Muss ich bei Ausgabewert nur diesen einfügen?
Code:
unsigned long tod;
char *tod_string = SysMalloc(13);

tod = GetTagDWord("DeinTimeOfDayTag");
TimeOfDayToString(tod, tod_string);
return tod_string


Du hattest ja in dem anderen Thread geschrieben, dass die String zu TOD nochmal die Eingabe überprüft und eventuelle Fehler nicht mit übernimmt.




TimeOfDayToString.PNGStringToTimeOfDay.PNG
 
Zuletzt bearbeitet:
Die Funktion TimeOfDayToString musst du als Global-Script einfügen und übersetzen, die andere auch wenn du sie benötigst.
In deinem EA-Feld wird dann die Funktion mit dem von mir gezeigten Code aufgerufen.

Wenn das EA-Feld Ein- und Ausgabe sein soll, dann musst du das eine Skript bei Eingabe, und das andere bei Ausgabe einfügen. Die Trigger musst du dementsprechend setzen, d.h. Ausgabeskript bei Änderung der TOD-Variable, das Eingabeskript wenn jemand eine Eingabe getätigt hat.
 
TimeOfDayString habe ich als Global-Script angelegt, aber kriege dort die Meldungen (siehe Bild im vorherigen Post) und dementsprechend nicht integriert.

Was muss in Eingabewert und was in Ausgabewert des E/A-Felds rein?
 
Funktioniert leider nicht bzw. es kommen wieder die selben errors.
TimeOfDayString muss doch als Global Script angelegt werden oder nicht?

Was muss gemacht werden, wenn die Variable, z.B. geändert, wieder zurück an die SPS gehen soll?
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Ersetze mal in meinen Funktionen hinter den Konstanten das "ul" durch ein einfaches "u" (ohne Anführungszeichen). Kann sein dass der WinCC C Übersetzer den ul Suffix noch nicht kennt, andernfalls könntest du auch einen (unsigned long) vor die Konstanten schreiben.
 
Perfekt vielen Dank, es funktioniert nun.

Habe das selbe bei dem Global Script StringToTimeOfDay gemacht. Muss ich das hier dann in den Eingabewert als C-Aktion eintragen, damit ich dies an die SPS bekomme? Bzw. wie muss es dann richtig heißen?
Code:
unsigned long tod;
char *string_tod = SysMalloc(13);

StringToTimeOfDay(tod, string_tod);

tod = SetTagDWord("DeinTimeOfDayTag");
 
Wenn das funktioniert hätte es eine allgemeine Veröffentlichung verdient FinnAH.
Bitte dann die vollständigen Skripte mal veröffentlichen.Das interessiert mich auch.:)
 
Wenn du bei einem EA-Feld ein C-Script beim Ereignis "Eingabewert Änderung" einfügst, sollte es so funktionieren:
Code:
void OnPropertyChanged(char* lpszPictureName, char* lpszObjectName, char* lpszPropertyName, char* value)
{
unsigned long tod;
int error;

tod = StringToTimeOfDay(value, &error);
if (error == 0) {
  SetTagDWord("DeineTimeOfDayVariable", tod);
}
}
Wenn eine falsche Zeit eingegeben wird, wird nichts geschrieben. Bei Bedarf könnte man das um eine Meldung ergänzen, dass die Eingabe nicht korrekt war.
 
Ich habe die Funktionen zur Vereinfachung der Verwendung in WinCC mal etwas angepasst.

Zuerst werden die beiden folgenden Global-Scripts angelegt:

SetTagDWordTimeOfDay:
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
// Rückgabe TRUE wenn ohne Fehler, FALSE wenn ein Fehler aufgetreten ist
BOOL SetTagDWordTimeOfDay(Tag Tag_Name, char *value)
{
    int error;
    unsigned long time_of_day;
    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 (value == NULL) {
        return FALSE;
    }
    if (strlen(value) > 12) {
        error = ERR_STRING_ZU_LANG;
        return FALSE;
    }
    stage = 0;
    j = 0;
    for (i = 0; i < strlen(value); i++) {
        if (value[i] >= '0' && value[i] <= '9') {
            sVal[stage][j] = value[i];
            if (stage < 3 && j >= 2) {
                error = ERR_STELLENANZ_H_M_S;
                return FALSE;
            } else if (j >= 3) {
                error = ERR_STELLENANZ_MS;
                return FALSE;
            }
            j++;
        } else if (value[i] == ':') {
            sVal[stage][j] = '\0';
            stage++;
            j = 0;
        // Millisekunden sind nur erlaubt nach allen drei vorherigen Stufen
        } else if (stage == 2 && value[i] == '.') {
            sVal[stage][j] = '\0';
            stage = 3;
            j = 0;
        } else {
            error = ERR_UNGUELTIGES_ZEICHEN;
            return FALSE;
        }
    }
    // 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 FALSE;
    }
    // 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 FALSE;
        }
        switch (i){
            case 0:
                h = atoi(sVal[i]);
                if (h > 23) {
                    error = ERR_WERTUEBERSCHR_H;
                    return FALSE;
                }
                break;
            case 1:
                m = atoi(sVal[i]);
                if (m > 59) {
                    error = ERR_WERTUEBERSCHR_M;
                    return FALSE;
                }
                break;
            case 2:
                s = atoi(sVal[i]);
                if (s > 59) {
                    error = ERR_WERTUEBERSCHR_S;
                    return FALSE;
                }
                break;
        }
    }
    if (strlen(sVal[3]) > 0) {
        ms = atoi(sVal[3]);
        if (ms > 999) {
            error = ERR_WERTUEBERSCHR_MS;
            return FALSE;
        }
    }
    time_of_day = (h * 3600000u + m * 60000u + s * 1000u + ms);
    SetTagDWord(Tag_Name, time_of_day);
    return TRUE;
}

und GetTagDWordTimeOfDay:
Code:
char *GetTagDWordTimeOfDay(Tag Tag_Name)
{
    unsigned long time_of_day;
    char *str = SysMalloc(13);

    time_of_day = GetTagDWord(Tag_Name);
    if (time_of_day > 86399999u) {
        time_of_day = 86399999u;
    }
    sprintf(str, "%02lu:%02lu:%02lu.%03lu",
           (time_of_day / 3600000u), 
	     (time_of_day % 3600000u) / 60000u, 
           ((time_of_day % 3600000u) % 60000u) / 1000u,
           ((time_of_day % 3600000u) % 60000u) % 1000u
    );
    return str;
}

Verwendung der Funktionen bei einem EA-Feld:

Ausgabewert Eigenschaften -> Ausgabe/Eingabe -> Ausgabewert: C-Skript einfügen, Variablentrigger auf die TimeOfDay-Variable einstellen.
Code:
#include "apdefap.h"
 char* _main(char* lpszPictureName, char* lpszObjectName, char* lpszPropertyName)
{
    // WINCC:TAGNAME_SECTION_START
    #define TIMEOFDAY_VARIABLE "tod1"
    // next TagID : 1
    // WINCC:TAGNAME_SECTION_END
    return GetTagDWordTimeOfDay(TIMEOFDAY_VARIABLE);
}

und

Ereignis -> Propertythemen -> Ausgabe/Eingabe -> Eingabewert: Änderung: C-Skript einfügen
Code:
#include "apdefap.h"
void OnPropertyChanged(char* lpszPictureName, char* lpszObjectName, char* lpszPropertyName,  char*  value)
{
    // WINCC:TAGNAME_SECTION_START
    #define TIMEOFDAY_VARIABLE "tod1"
    // next TagID : 1
    // WINCC:TAGNAME_SECTION_END

    SetTagDWordTimeOfDay(TIMEOFDAY_VARIABLE, value);
}

Bisher muss bei der Eingabe der TimeOfDay-Variable die komplette Syntax eingehalten werden, d.h. immer Stunden, Minuten, Sekunden und Millisekunden. Bei Bedarf könnte man sich das noch so anpassen, dass auch eine Eingabe wie 12:30 dann automatisch als 12:30:00.000 angenommen wird.
 
Hallo,
es ist schön, dass du dich hier beteiligst ... schau aber bei den Beiträgen, zu denen du schreibst bitte auch auf den letzten Zeitstempel. Der ist hier fast 5 Jahre alt ...

Gruß
Larry
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Von Siemens gibt es hierzu auch ein Beispiel: https://support.industry.siemens.co...c-angezeigt-werden-?dti=0&pnid=14855&lc=de-DE

Kann die Ausgabe formatiert werden so dass die Anzeige zweistellig ist. zb. 07 : 05 nicht 7 : 5

Die Siemens Funktion ist für den Datentyp TIME, hier im Thread ging es um Time_of_Day. Die Funktion die ich oben gezeigt hatte gibt die Zeit mit führenden Nullen aus.
Wenn du das im Siemens Code für TIME haben möchtest, musst du die dort gelieferte sprintf() Funktion anpassen. Dort wo %i steht müsstest du %02i eingeben wenn du immer zwei Stellen haben möchtest.
 
Thomas vielen Dank für die schnelle Antwort.

Herr Laffer das Beispiel von Siemens ist noch viel älter. Ab wann darf man zu einem Thema keine Fragen mehr stellen?
 
Sorry ... ich hatte deine unterschwellige Frage in dem Beitrag nicht gesehen ... sondern nur gesehen, das es eine Ergänzung zu einem bereits alten Beitrag gegeben hat ...
Grundsätzlich gibt es keine zeitliche Limitierung in irgendwelchen Themen ...
 
Zurück
Oben