Tagesnummer berechnen?

verona

Level-2
Beiträge
18
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
hi leute

wie kann man unter s7 die genaue tagesnummer berechnen?z. B. 4. januar= 4 tag im jahr. gibt es das irgendwelche formel für. habe bis jetzt nichts vernünftiges gefunden. wer kann mir helfen?

vielen dank schonmal
 
Hallo Verona,

darf's auch SCL sein? Alles ohne Gewähr.


Code:
(************************************************************************************************************************)
FUNCTION "DATUM_TO_JAHRESTAG" : INT
TITLE = 'Jahrestag aus Datum'
(************************************************************************************************************************)
KNOW_HOW_PROTECT
VERSION : '1.0'
AUTHOR  : Onkel Dagobert ;-)
NAME    : DATE
FAMILY  : Entenhausen
(************************************************************************************************************************)

VAR_INPUT
  TAG, MONAT                : INT;
  SCHALTJAHR                : BOOL;
END_VAR

VAR_TEMP
  a                         : INT;
END_VAR

BEGIN
//______________________________________________________________________________
//    Jahrestag aus Datum berechnen
//¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
 a := 2;
 IF SCHALTJAHR THEN
   a := 1;
 END_IF;
 DATUM_TO_JAHRESTAG:=REAL_TO_INT(TRUNC(275*MONAT/9)-a*TRUNC((monat+9)/12)+tag-30);

END_FUNCTION;


Code:
(************************************************************************************************************************)
FUNCTION "SCHALTJAHR" : BOOL
TITLE = 'Schaltjahr'
// Funktion getestet
(************************************************************************************************************************)
KNOW_HOW_PROTECT
VERSION : '1.0'
AUTHOR  : Onkel Dagobert ;-)
NAME    : DATE
FAMILY  : Entenhausen
(************************************************************************************************************************)

VAR_INPUT
  JAHR                      : INT;      // vierstellige Jahreszahl
END_VAR

BEGIN
  SCHALTJAHR := false;
  IF (JAHR MOD 400 = 0) OR
     (JAHR MOD 4   = 0) AND
     (JAHR MOD 100 <> 0)THEN
     SCHALTJAHR := true;
END_IF;

END_FUNCTION;


Code:
(************************************************************************************************************************)
FUNCTION "JAHRESZAHL_VIERSTELLIG" : VOID
TITLE = 'Datum mit vierstelliger Jahreszahl aus Systemdatum ermitteln'
(************************************************************************************************************************)
KNOW_HOW_PROTECT
VERSION : '1.0'
AUTHOR  : Onkel Dagobert ;-)
NAME    : DATE
FAMILY  : Entenhausen
(************************************************************************************************************************)

VAR_OUTPUT
  TAG, MONAT, JAHR          : INT;
END_VAR

VAR
  TEMP_DT                   : DT;
  CDT AT TEMP_DT            : ARRAY[0..7] OF BYTE;
  TEMP_INT                  : INT;
END_VAR
  
//______________________________________________________________________________
//    Datum mit vierstelliger Jahreszahl aus Systemdatum ermitteln
//¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
BEGIN
TEMP_INT := READ_CLK(CDT:=TEMP_DT);
TAG      := WORD_TO_INT(BYTE_TO_WORD(CDT[2])); 
MONAT    := WORD_TO_INT(BYTE_TO_WORD(CDT[1])); 
TEMP_INT := WORD_TO_INT(BYTE_TO_WORD(CDT[0]));
IF TEMP_INT >= 90
   THEN JAHR := TEMP_INT + 1900;
   ELSE JAHR := TEMP_INT + 2000;
END_IF;
END_FUNCTION;



Gruss, Onkel
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo,

da o.g. Berechnung nicht nachvollziehbar ist, hier eine Testumgebung zum Simulieren. Es wird zunächst eine Zahl von 1 bis 365/366 erzeugt. Aus dieser wird mit einer FC das Datum (Tag, Monat) berechnet. Aus diesem Datum wird wiederum mit einer anderen FC der Tag des Jahres berechnet und mit dem ursprünglichen verglichen.

ZUM DOWNLOAD MÜSST IHR EINGELOGGT SEIN!

Funktion JAHRESTAG --> DATUM
Code:
(************************************************************************************************************************)
FUNCTION "JAHRESTAG_TO_DATUM" : VOID
TITLE = 'Datum aus Tag des Jahres'
(************************************************************************************************************************)
KNOW_HOW_PROTECT
VERSION : '1.0'
AUTHOR  : Onkel_D
NAME    : DATE
FAMILY  : Entenh
(************************************************************************************************************************)

VAR_INPUT
  JAHRESTAG                 : INT;
  SCHALTJAHR                : BOOL;
END_VAR

VAR_OUTPUT
  TAG                       : INT;
  MONAT                     : INT;
END_VAR

VAR_TEMP
  mm, dd                    : REAL;
  k                         : INT;      // Korrekturwert Schaltjahr
END_VAR

BEGIN
k := 2;
IF SCHALTJAHR THEN
  k := 1;
END_IF;
mm := TRUNC((9*(k+JAHRESTAG))/275.0+0.98);
IF JAHRESTAG < 32 THEN
   mm := 1;
END_IF;
TAG   := REAL_TO_INT(JAHRESTAG - TRUNC((275*mm)/9) + k*TRUNC((mm+9)/12)+30);
MONAT := REAL_TO_INT(mm);
END_FUNCTION;


Gruß, Onkel
 

Anhänge

  • jahres_1.zip
    408,2 KB · Aufrufe: 115
Die allgemeine und auch verständliche "Normalform"

Hallo,

nicht dass ihr denkt, "der Onkel spinnt doch!" :x . Die allgemeine und auch verständliche "Normalform" sieht ungefähr so aus:

Code:
FUNCTION "JAHRESTAG" : INT
TITLE =
AUTHOR : Onkel_D
FAMILY : Entenh
NAME : 'DATE'
VERSION : 0.1


VAR_INPUT
  TAG : INT ;   
  MONAT : INT ; 
  SCHALTJAHR : BOOL ;   
END_VAR
VAR_TEMP
  TEMP_INT : INT ;  
END_VAR
BEGIN
NETWORK
TITLE =

      SET   ; 
      SAVE  ; 

//*** Tage voller Monate seit Jahresbeginn
      L     #MONAT; 
      DEC   1; // 0..11
      SPL   ERR; // >11
      SPA   JAN; 
      SPA   FEB; 
      SPA   MAE; 
      SPA   APR; 
      SPA   MAI; 
      SPA   JUN; 
      SPA   JUL; 
      SPA   AUG; 
      SPA   SEP; 
      SPA   OKT; 
      SPA   NOV; 
      SPA   DEZ; 

//*** Verlassen mit Fehler
ERR:  L     0; 
      T     #RET_VAL; 
      CLR   ; 
      SAVE  ; 
      BEA   ; 

//*** Tage der abgeschlossenen Monate
//    (Tage vom Vormonat)
JAN:  L     0; 
      SPA   TAGE; 
FEB:  L     31; 
      SPA   TAGE; 
MAE:  L     59; // ohne Schaltjahr
      SPA   TAGE; 
APR:  L     90; 
      SPA   TAGE; 
MAI:  L     120; 
      SPA   TAGE; 
JUN:  L     151; 
      SPA   TAGE; 
JUL:  L     181; 
      SPA   TAGE; 
AUG:  L     212; 
      SPA   TAGE; 
SEP:  L     243; 
      SPA   TAGE; 
OKT:  L     273; 
      SPA   TAGE; 
NOV:  L     304; 
      SPA   TAGE; 
DEZ:  L     334; 
      SPA   TAGE; 

//*** verstrichene Tage vom aktuellen Monat dazu
TAGE: L     #TAG; 
      +I    ; 
      T     #TEMP_INT; 

//*** Korrektur, wenn SCHALTJAHR
      U     #SCHALTJAHR; 
      U(    ; 
      L     #MONAT; 
      L     2; 
      >I    ; 
      )     ; 
      L     #TEMP_INT; 
      SPBN  M001; 
      L     1; 
      +I    ; 

//*** Ausgabe
M001: T     #RET_VAL; 
END_FUNCTION


Gruss, Onkel
 
hallo

hab leider ein problem weil ich nicht weiss wie es funktioniert die uhrzeit und das datum auszulesen. mann muss ja sfc1 im ob1 aufrufen. weiss dann aber nicht wie ich den scf1 parametriere und die uhrzeit und das datum weiterverareibten kann. wer kann mir helfen???
 
Schaltjahr berechnen

Hallo,

der Befehl MOD erzeugt für Schaltjahre z.B. im OB1 ein VKE:
Code:
L LB12    //Jahreszahl zweistellig (1990..2089)
BTI        //BCD nach INT
L 4        //jedes 4. Jahr
MOD      //Divisionsrest ermitteln
L 0        //wenn kein Rest,
==I        //dann ist Schaltjahr
 
Zuviel Werbung?
-> Hier kostenlos registrieren
das ist nicht ganz korrekt

für sps anwendungen sollte das aber meist reichen

WIKIPEDIA schrieb:
  • Ist die Jahreszahl durch 4 teilbar, aber nicht durch 100, dann ist es ein Schaltjahr mit 366 Tagen. Beispiele: 1980, 1972, 1720.
  • Ist die Jahreszahl durch 100 teilbar, aber nicht durch 400, dann ist das Jahr ein gewöhnliches Gemeinjahr und hat nur 365 Tage, z. B. in den Jahren 1700, 1800 und 1900 oder ferner 2100.
  • Ist die Jahreszahl durch 400 teilbar, ist das Jahr ein Schaltjahr. Die Jahre 1600 und 2000 waren – in Übereinstimmung mit der Julianischen Schaltregel – Schaltjahre zu 366 Tagen.
oder mathematisch:
if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) {// schaltjahr}
 
Hall tsp_05,

..kann ich auch die erste Version benutzen und testen ?..
Davon gehe ich erst einmal aus.

Den "spionagesicheren" Code hatte ich damals irgendwo im Internet gefunden. Ich hatte ihn in SCL umgesetzt und ein wenig getestet. Ich denke, er hatte auch funktioniert, zumindest für den heute üblichen Bereich von 1990 bis 2089. Der Haken allerdings ist, dass es keine Herleitung für die Berechnung gibt. Der Algorithmus ist empirisch entstanden, d.h. es hat jemand solange probiert bis es irgendwie funktionierte. Falls einmal Probleme auftreten sollten, hat man keine Chance, den Fehler zu finden! So etwas ist bestenfalls für eine private Hofbeleuchtungssteuerung vertretbar, nicht für industrielle Anwendungen, Krankenhäuser oder öffentliche Gebäude, etc.

Aufgrund von Rundungsfehlern in der Berechnung ist die Schreibweise in SCL von Bedeutung. Wenn du z.Bsp. die Berechnung aufteilst und Zwischenergebnisse bildest, wird es wahrscheinlich schon nicht mehr funktionieren.

Das absolut 100%-ige Testen ist sehr aufwändig. Man müsste in so einem Fall jedes Einzelergebnis handisch überprüfen. Eine annährende Sicherheit kannst du erreichen, wenn du dieselbe Funktion mit verschiedenen Algorithmen berechnetst, und die Ergebnisse vergleichst.

Verwende besser einen "transparenten" Code!


Gruß, Onkel
 
S7-Datum nur bis 2089

für sps anwendungen sollte das aber meist reichen

Hallo,
wer jetzt schon weiß, daß seine S7 das Jahr 2090 nicht im Museum erlebt, sollte sich Gedanken um das ausfallende Schaltjahr im Jahr 2100 (auch 2200 und 2300) machen. Die heutige Generation Simatic-Steuerungen interpretiert Jahreszahlen über 89 als 1990 bis 1999. Ich habe allerdings nicht vor, solange zu programmieren und mache mir deswegen keinen Kopf.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Lösung AWL

Hallo Leute, ich habe jetzt eine Lösung gemacht, in AWL, basiert auf dem Code von oben und beinhaltet gleich die Berechnung des Schaltjahres:

Code:
  IN  0.0
    Tag         Int        0.0
    Monat       Int        2.0
    Jahr        Int        4.0       2-4 stellig
  OUT  0.0
  IN_OUT  0.0
  TEMP  0.0
    TEMP_INT    Int        0.0
    Schaltjahr  Bool       2.0
    MOD4        Bool       2.1       True wenn REST = 0
    MOD400      Bool       2.2       True wenn REST = 0
    MOD100      Bool       2.3       True wenn REST = 0
  RETURN  0.0
    RET_VAL     Int        6.0

------------------------------------------

Beschreibung:
03.03.2011
                              D. Kaserer
 
Beschreibung: In dieser Funktion wird der Tag des aktuellen Jahres berechnet.
              z.B. 01.02. ist der 32. Tag im Jahr
              Dabei wird kontrolliert ob es sich um ein Schaltjahr handelt.
 
Definition Schaltjahr:
* Ist die Jahreszahl durch 4 teilbar, aber nicht durch 100, dann ist es ein 
  Schaltjahr mit 366 Tagen. Beispiele: 1980, 1972, 1720.
* Ist die Jahreszahl durch 100 teilbar, aber nicht durch 400, dann ist das Jahr 
  ein gewöhnliches Gemeinjahr und hat nur 365 Tage, z. B. in den Jahren 1700, 
  1800 und 1900 oder ferner 2100.
* Ist die Jahreszahl durch 400 teilbar, ist das Jahr ein Schaltjahr. Die Jahre 
  1600 und 2000 waren – in Übereinstimmung mit der Julianischen Schaltregel – 
  Schaltjahre zu 366 Tagen.
 
Anschlüsse:
IN:
       Tag             INT      aktueller Tag im Monat
       Monat           INT      aktuelles Monat
       Jahr            INT      aktuelles Jahr zur Schaltjahrberechng
 
OUT:
       RET_VAL         INT      gibt den Tag im Jahr zurück

------------------------------------------

Netzwerk: 1      Schaltjahr berechnen
//*** Ist das Jahr ein Schaltjahr?
      L     #Jahr        //Jahreszahl
      L     4 //jedes 4. Jahr
      MOD    //Divisionsrest ermitteln
      L     0 //wenn kein Rest,
      ==I   
      =     #MOD4        //durch 4 teilbar

      L     #Jahr        //Jahreszahl
      L     400          //duch 400
      MOD   
      L     0 //Rest 0
      ==I   
      =     #MOD400      //durch 400 teilbar

      L     #Jahr        //Jahreszahl
      L     100          //duch 100
      MOD   
      L     0 //Rest 0
      ==I   
      =     #MOD100      //durch 100 teilbar

      O     #MOD4        //Berechnung siehe Beschreibung
      UN    #MOD100
      O     #MOD400
      =     #Schaltjahr

Netzwerk: 2      Tage zählen
//*** Tage voller Monate seit Jahresbeginn
      L     #Monat
      DEC   1          // 0..11
      SPL   ERR        // >11
      SPA   JAN
      SPA   FEB
      SPA   MAE
      SPA   APR
      SPA   MAI
      SPA   JUN
      SPA   JUL
      SPA   AUG
      SPA   SEP
      SPA   OKT
      SPA   NOV
      SPA   DEZ

//*** Verlassen mit Fehler
ERR:  L     0
      T     #RET_VAL
      CLR   
      SAVE  
      BEA  
 
//*** Tage der abgeschlossenen Monate
//    (Tage vom Vormonat)
JAN:  L     0
      SPA   TAGE
FEB:  L     31
      SPA   TAGE
MAE:  L     59         // ohne Schaltjahr
      SPA   TAGE
APR:  L     90
      SPA   TAGE
MAI:  L     120
      SPA   TAGE
JUN:  L     151
      SPA   TAGE
JUL:  L     181
      SPA   TAGE
AUG:  L     212
      SPA   TAGE
SEP:  L     243
      SPA   TAGE
OKT:  L     273
      SPA   TAGE
NOV:  L     304
      SPA   TAGE
DEZ:  L     334
      SPA   TAGE

//*** verstrichene Tage vom aktuellen Monat dazu
TAGE: L     #Tag
      +I    
      T     #TEMP_INT

Netzwerk: 3      Korrektur und Ausgabe
//*** Korrektur, wenn SCHALTJAHR und Monat > Februar
      U     #Schaltjahr
      U(    
      L     #Monat
      L     2
      >I    
      )     
      L     #TEMP_INT
      SPBN  M001
      L     1
      +I    

//*** Ausgabe
M001: T     #RET_VAL

bei Fehlern bitte Informieren

lg dkaserer
 
Monatsletzter in AWL

Da ich heute vor einem ähnlichen Problem stand und dkaserer den Thread vor gar nicht allzu langer Zeit mal ausgebuddelt hat,
wollte ich noch schnell meine Lösung für die Findung des Monatsletzten hier posten, da das sonst nur über Weckalarme
möglich ist und ich in meinem Anwendungsfall auf keinen Fall die Produktion stoppen kann.


Code:
[FONT=Courier New][SIZE=2]
Beschreibung:
TITLE:           Berechnung Monatsletzter
DATE:            08.09.2011
AUTHOR:          EliteGurke

Beschreibung: In dieser Funktion wird der Monatsletzte berechnet.[/SIZE][/FONT][FONT=Courier New][SIZE=2]
z.B. Februar -> 28, es sei denn es handelt sich um ein Schaltjahr -> 29

Definition Schaltjahr:[/SIZE][/FONT][FONT=Courier New][SIZE=2]
*  Ist die Jahreszahl durch 4 teilbar, aber nicht durch 100, dann ist es  ein Schaltjahr 
   mit 366 Tagen. Beispiele: 1980, 1972, 1720.
* Ist die  Jahreszahl durch 100 teilbar, aber nicht durch 400, dann ist das Jahr 
  ein gewöhnliches Gemeinjahr und hat nur 365 Tage, z. B. in den Jahren  1700, 1800 und 1900 oder ferner 2100.
* Ist die Jahreszahl durch 400  teilbar, ist das Jahr ein Schaltjahr. Die Jahre 1600 und 2000 waren – 
  in  Übereinstimmung mit der Julianischen Schaltregel – Schaltjahre zu 366  Tagen.

Credits to Onkel Dagobert und D. Kaserer[/SIZE][/FONT][FONT=Courier New][SIZE=2]

------------------------------------------[/SIZE][/FONT][FONT=Courier New][SIZE=2]

Variablen: [/SIZE][/FONT] [FONT=Courier New][SIZE=2]

IN[/SIZE][/FONT][FONT=Courier New][SIZE=2]

INOUT[/SIZE][/FONT][FONT=Courier New][SIZE=2]

TEMP[/SIZE][/FONT][FONT=Courier New][SIZE=2]
DateAndTime    0.0        DATE_AND_TIME        
RET_VAL        8.0        RET_VAL          ReturnValue von SFC1
MOD4          10.0        Bool            True wenn REST = 0
MOD400        10.1        Bool            True wenn REST = 0
MOD100        10.2        Bool            True wenn REST = 0
Monat         12.0        INT                    
Jahr          14.0        INT                    

OUT
Schaltjahr     0.0        Bool
Monatsletzter  2.0        Int 

------------------------------------------[/SIZE][/FONT][FONT=Courier New][SIZE=2]

Netzwerk: 1 --- Monat und Jahr auslesen[/SIZE][/FONT][FONT=Courier New][SIZE=2]
CALL SFC1
    RET_VAL    :=    #RET_VAL
    CDT        :=    #DateAndTime
NOP 0

Netzwerk: 2 --- BCD zu INT wandeln[/SIZE][/FONT][FONT=Courier New][SIZE=2]
L LB 0          //Jahr
BTI
T #Jahr

L LB 1          //Monat[/SIZE][/FONT][FONT=Courier New][SIZE=2]
BTI
T #Monat

Netzwerk: 3 --- Schaltjahr berechnen[/SIZE][/FONT][FONT=Courier New][SIZE=2]
//<-- Ist das Jahr ein Schaltjahr?
L #Jahr         //Jahreszahl
L 4             //jedes 4. Jahr
MOD             //Divisionsrest ermitteln
L 0             //wenn kein Rest,
==I
= #MOD4         //durch 4 teilbar

L #Jahr         //Jahreszahl[/SIZE][/FONT][FONT=Courier New][SIZE=2]
L 400           //durch 400
MOD
L 0             //Rest 0
==I
= #MOD400       //durch 400 teilbar

L #Jahr         //Jahreszahl[/SIZE][/FONT][FONT=Courier New][SIZE=2]
L 100           //durch 100
MOD
L 0             //Rest 0
==I
= #MOD100       //durch 100 teilbar

O #MOD4         //Berechnung siehe Beschreibung[/SIZE][/FONT][FONT=Courier New][SIZE=2]
UN #MOD100
O #MOD400
= #Schaltjahr

Netzwerk: 4 --- Tage zählen[/SIZE][/FONT][FONT=Courier New][SIZE=2]
//<-- Tage voller Monate seit Jahresbeginn
L #Monat
DEC 1           // 0..11
SPL ERR         // >11
SPA JAN
SPA FEB
SPA MAE
SPA APR
SPA MAI
SPA JUN
SPA JUL
SPA AUG
SPA SEP
SPA OKT
SPA NOV
SPA DEZ

//<-- Verlassen mit Fehler[/SIZE][/FONT][FONT=Courier New][SIZE=2]
ERR: L 0
T #Monatsletzter
CLR
SAVE
BEA

//<-- Tage der abgeschlossenen Monate[/SIZE][/FONT][FONT=Courier New][SIZE=2]
JAN: L 31
SPA TAGE
FEB: L 28         //ohne Schaltjahr
SPA TAGE
MAE: L 31
SPA TAGE
APR: L 30
SPA TAGE
MAI: L 31
SPA TAGE
JUN: L 30
SPA TAGE
JUL: L 31
SPA TAGE
AUG: L 31
SPA TAGE
SEP: L 30
SPA TAGE
OKT: L 31
SPA TAGE
NOV: L 30
SPA TAGE
DEZ: L 31
SPA TAGE

TAGE: T #Monatsletzter[/SIZE][/FONT][FONT=Courier New][SIZE=2]

Netzwerk: 5 --- Korrektur und Ausgabe[/SIZE][/FONT][FONT=Courier New][SIZE=2]
//<-- Korrektur, wenn Schaltjahr und Monat == Februar
U #Schaltjahr
U(
L #Monat
L 2
==I
)
L #Monatsletzter
SPBN M001
L 1
+I

//<-- Ausgabe[/SIZE][/FONT][FONT=Courier New][SIZE=2]
M001: T #Monatsletzter

SET[/SIZE][/FONT][FONT=Courier New][SIZE=2]
SAVE
[/SIZE][/FONT]


Damit ist es mir nun möglich auch ohne Weckalarme am letzten des Monats um 23:59:59 noch
mit dem alten Datum meine Statistiken wegzuspeichern.

Code muss allerdings noch getestet werden, habe den schnell in N++ zusammen gefriemelt.


mfg EliteGurke
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Habe heute versucht den Code aus Post #3 von Dagobert im TIA zu benutzen, nachdem ich ihn auf TIA schreibweiße umgebaut habe läuft er zwar, gibt mir jedoch wenn überhaupt nur den richtigen Monat aus.

Da ich SCL jedoch nur sehr Oberflächlich kenne habe ich keinerlei Idee was das Problem sein könnte bzw wie es zu lösen ist. Oder gibt es hierzu andere Beispiel-Codes?


Schönen Feiertag und schon mal DANKE für die Hilfe!
 
Zurück
Oben