TIA TIA V16 gewollte Dateninkonsistenz im Zeitgesteuerten OB (30) ???

Lerne ja gerne was dazu, was soll den beim Auskommentieren passieren???:

Na wenn der alteAstrobaustein das Problem sein soll, müsste ja durch auskommentieren des Astrobausteins das Problem weg sein?

Entweder hab ich jetzt nen Knoten im Kopf, ich habs so verstanden, dass der Astrobaustein den "Akt".LocalZeit beschreibt, warum und wie auch immer.

Schau halt mal in den Astrobaustein rein was der macht. Evtl. läuft der über mehrere Zyklen und oder pointert azf den "Akt".Localzeit

Ich würd drüber schlafen ;)

Gruß
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Was ich nicht ganz verstehe bzw. habe ich etwas überlesen, im Beitrag #1 ging es doch einfach um die Systemfunktionen RD_LOC_T und die Übergabe mittels Temp-Variable. Jetzt dreht es sich auf einmal um Astrofunktionen aus irgendwelchen alten Bibliotheken....

:confused:
 
Was ich nicht ganz verstehe bzw. habe ich etwas überlesen, im Beitrag #1 ging es doch einfach um die Systemfunktionen RD_LOC_T und die Übergabe mittels Temp-Variable.


Entfernter Aufruf: "LGF_Astro_DB"(modeDMS:=TRUE, actLocalTime=>"Akt".Localzeit);

so wie ich das sehe wird"Akt".Localzeit als Ausgang von LGF_Astro_DB beschrieben

Im Ursprungsthread sah das noch so aus:
#RETURNVALUE := RD_LOC_T("Akt".Localzeit);

"Akt".Uhrzeit := DTL_TO_TOD("Akt".Localzeit);
 
Und nicht anderes wird gemacht. Es wird die Systemzeit in eine DTL geladen.

Das Problem geschieht später!!! IM OB1 !!! Hier wird die Uhrzeit aus dem DTL extrahiert. Hier und nur Hier wird Akt.Uhrzeit beschrieben.

IM OB1 IST DIESE Uhrzeit ZU KEINEM ZEITPUNKT NULL !!! IM OB 30 in ca. 26 von 600 Aufrufen.

Was hat das bitte schön noch damit zu tun woher der DTL kommt???

Sorry wenn ich das etwas vereinfacht dargestellt habe.

Wo sind wir denn jetzt? Siemens die sagen das Temp-Variablen nicht zu trauen ist wenn ein Interupt kommt. (Setze viel Motion-Funktionen ein, das ist ein FIASKO!!!)
Siemens die sagen Bausteinaufrufe funktionieren nicht alles im OB1 (Keine Strukturen keine Temp-Variablen und was noch???)

Also ich persönlich habe jetzt mehr Angst als vorher, oder wie seht ihr das?
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Auch wenn die Programmbeispiele aus der LGF immer mit besonderer Vorsicht zu verwenden sind: der LGF_Astroirgendwas ist hier nicht für das Problem verantwortlich. Auch wenn der Siemens (?) Support das erstmal so darstellt. Die haben das Problem gar nicht begriffen, und offensichtlich auch nicht genug getestet... und erstmal die Standard-Abwimmel-Antwort: "Sie verwenden eine veraltete Version!" Der dann gegebene Lösungsvorschlag ist untauglich, weil er genau die Problemursache beibehält.

Eigentlich hatte ich die Lösung und die Erklärung schon vor 3 Tagen gepostet, doch anscheinend wurde mein Lösungsvorschlag nicht ausprobiert ... und die zweite schreibende Verwendung von "Akt".Localzeit wurde uns trotz Nachfrage erst heute offenbart.

Also nochmal kurz zusammenfassen mit roten und blauen Markierungen von mir:
Ich lese im OB1 (Zyklisch) die Lokalzeit aus und weise diese als Uhrzeit einer TIME Variablen zu.

Code:
#RETURNVALUE := RD_LOC_T([COLOR="#FF0000"]"Akt".Localzeit[/COLOR]);

"Akt".Uhrzeit := DTL_TO_TOD("Akt".Localzeit);
Multitasking-geeigneter würde ich das so machen:
Code:
VAR_TEMP
  OB1_Localzeit : DTL;
  RETURNVALUE : INT;
END_VAR

#RETURNVALUE := RD_LOC_T([COLOR="#0000FF"]#OB1_Localzeit[/COLOR]);
"Akt".Localzeit := #OB1_Localzeit;
"Akt".Uhrzeit := TOD_TO_TIME(DTL_TO_TOD(#OB1_Localzeit));
Multitasking-geeigneter würde ich das so machen:
Und warum ist das "Multitasking geigneter?
Der RD_LOC_T kann unterbrochen werden, während er in Deiner Programmierung "Akt".Localzeit beschreibt, und während der Unterbrechung könnte "Akt".Localzeit überschrieben werden --> Inkonsistent! In meiner Variante mit der TEMP-Variable kann die TEMP-Variable während der Unterbrechung nicht verändert werden.

(Eigentlich wollte ich in meinem Beitrag #15 noch fragen, ob "Akt".Localzeit noch irgendwo beschrieben wird. Irgendwie ist die Frage beim Beitrag formulieren verloren gegangen...)
"Akt".Localzeit wird nicht weiter beschrieben.
soso...!!
Und schon ist Antwort da...

Hier die vollständige Meldung:
wenn Sie den Aufruf des LGF Bibliothek-Anweisung entfernen und die folgende Anweisung einfügen wird die lokale Zeit korrekt im OB30 angezeigt, ohne auf 0 zurückgesetzt zu werden:
(...)
Entfernter Aufruf: "LGF_Astro_DB"(modeDMS:=TRUE, actLocalTime=>"Akt".Localzeit);

"Tag_1":= RD_LOC_T("Akt".Localzeit);

"Akt".Uhrzeit := TOD_TO_TIME(DTL_TO_TOD("Akt".Localzeit));

Der verwendete LGF-Baustein entstammt aus der V14 SP1. Für die V16 ist bereits eine neuere Version verfügbar V5.0 verfügbar -> https://support.industry.siemens.com...view/109479728

In Ihrem Projekt müsste der LGF_Astro durch LGF_AstroClock ersetzt werden.
Also ruhig bleiben, Entwarnung, es ist ein ganz gewöhnlicher Anwenderfehler und kein Bug in der Verantwortung von Siemens. Spekulationen über womöglich überlappende Verwendung von TEMP-Speicher durch verschiedene Tasks entbehren jeder Grundlage. Wenn so etwas tatsächlich existieren würde, dann würde uns das dauernd um die Ohren fliegen, und nicht nur gelegentlich..

Das sollte man sich wirklich hinter die Ohren schreiben: In verschiedenen Interrupt-Ebenen (Multitasking!) darf man nicht die selben globalen Variablen beschreiben! (Wenn doch unbedingt nötig, dann muß man Semaphore und andere Techniken anwenden.)

Harald
 
Sorry aber WEIT daneben. Der Schwachsinn mit
"Tag_1":= RD_LOC_T("Akt".Localzeit);
ist eine Idee von Siemens und nicht in meinem Programm !!!

Habe noch was rumprobiert:

Weise ich "Akt".Localzeit einen konstanten Wert zu ist alles iO.

Lösche ich die Nannosekunden in "Akt".Localzeit ab bleibt der Fehler.

Änder ich die Zuweisung
"Akt".Uhrzeit := TOD_TO_TIME(DTL_TO_TOD("Akt".Localzeit));
in
"Akt".Uhrzeit := TOD_TO_TIME(DTL_TO_TOD("Akt".Localzeit_alt));
so bleibt der Fehler !!! obwohl "Akt".Localzeit_alt nur im OB1 "Zeile1" mit dem Wert aus "Akt".Localzeit beschrieben wird.

Also wenn das ein Anwenderfehler ist bin ich reif für die Rente...
 
Puhh, jetzt gehts glaub ziemlich durcheinander...
In welchem OB wird der Astrobaustein aufgerufen? OB1 oder OB30?

Denke man bräuchte das Projekt um durchzublicken.

Ich tippe auf einen unbekannten Anwenderfehler im Projekt oder im Astrobaustein. Gibts noch Visuzugriffe auf die Variablen?

An ein Problem mit den Tempvariablen glaub ich auch nicht. Eher noch ein Compilerproblem mit dem DTL_TO_TOD...

Gruß
 
Sorry aber WEIT daneben. Der Schwachsinn mit
"Tag_1":= RD_LOC_T("Akt".Localzeit);
ist eine Idee von Siemens und nicht in meinem Programm !!!
Das habe ich auch so verstanden. Ich habe es markiert, weil der Vorschlag genauso falsch ist wie Deine Programmzeile.

Die mehrmalige Verwendung von "Akt".Localzeit mit RD_LOC_T ist auf jeden Fall ein Fehler (wo Du zur Abstellung bei jedem RD_LOC_T am besten TEMP-Variablen verwenden solltest), das erklärt aber noch nicht, wieso "Akt".Uhrzeit in Deinem OB30 manchmal T#0s ist. Was machst Du sonst noch so mit "Akt".Uhrzeit und "Akt".Localzeit?

Oder doch Siemens? Ist womöglich RD_LOC_T nicht korrekt reentrant implementiert? Glaube ich aber nicht dran. Könnte man aber umgehen, indem man nicht mehrfach RD_LOC_T und RD_SYS_T aufruft. Eigentlich sollte es sowieso ausreichen, überhaupt nur am Anfang des OB1 die Uhrzeit abzufragen und global zur Verfügung zu stellen.
Ist da vielleicht ein Problem mit dem Daten-Schreib-Cache der CPU bei Schreibzugriffen auf die selbe Variable in verschiedenen Tasks? Das mag ich auch nicht glauben.

Vielleicht zeigst Du uns auch mal Deinen LGF_Astro-Quellcode? Ich vermute, Du verwendest V1.1.3 oder V1.1.4 (diese Versionen habe ich leider nicht, ich habe nur V1.1.5). Ich kann mir aber nicht vorstellen, was der LGF_Astro so anstellen könnte, um Dein Problem zu erzeugen. Allerdings hat der LGF_Astro bis zur V3.0.0 für TIA V15.1/V16 schon ein paar Bugfixes und komplett-Überarbeitungen hinter sich.

Harald

PS: Falls es jemanden interessiert, hier der LGF_Astro V1.1.5:
Code:
FUNCTION_BLOCK "LGF_Astro"
{ S7_Optimized_Access := 'TRUE' }
   VAR_INPUT 
      latitudeDD : Real;   // latitude decimal degrees; North = positive; South = negative; [-90.0..90.0]
      longitudeDD : Real;   // longitude decimal degrees; East=Positive; West = negative; [-180.0..180.0]
      modeDMS : Bool;   // "1" = ModeDegMinSec, "0" = Mode DecDeg
      latitudeDMS : "LGF_typeAstroDMS";   // latitudeDegMinSec; North = positive; South = negative
      longitudeDMS : "LGF_typeAstroDMS";   // longitude DegMinSec; East=Positive; West = negative
      offsetSunrise : Time;   // offset to sunrise
      offsetSunset : Time;   // offset to sunset
   END_VAR

   VAR_OUTPUT 
      sunrise {InstructionName := 'DTL'; LibVersion := '1.0'} : DTL;   // sunrise (localtime)
      sunset {InstructionName := 'DTL'; LibVersion := '1.0'} : DTL;   // sunset (localtime)
      daytime : Bool;   // time between OffsetSunrise and OffesetSunset
      actSystemTime {InstructionName := 'DTL'; LibVersion := '1.0'} : DTL;   // current systemt ime
      actLocalTime {InstructionName := 'DTL'; LibVersion := '1.0'} : DTL;   // current local time
      error : Bool;   // "0" = no error; "1" = error
      statusID : UInt;   // Error destination: "1" = LGF_Astro; "2" = RD_SYS_T; "3" = RD_LOC_T
      status : Word;   // status and error codes
   END_VAR

   VAR_TEMP 
      tempSysTime {InstructionName := 'DTL'; LibVersion := '1.0'} : DTL;   // actual system time UTC
      tempOfficLocTime {InstructionName := 'DTL'; LibVersion := '1.0'} : DTL;   // official actual local time
      tempTimeZone : Real;   // official local time zone
      tempDayOfYear : Real;   // day of  the year
      templngHour : Real;   // unit = hours;  East=Positive; West = negative
      tempLatitudeRad : Real;   // unit = radian; North = positive; South = negative
      tempAppRiseTime : Real;   // approximate Sun Rising time
      tempRiseMeanAnomaly : Real;   // sun's rising time mean anomaly
      tempRiseMeanRad : Real;   // sun's rising time mean anomaly in radian
      tempRiseLongitude : Real;   // sun's rising true longitude
      tempRiseLonRad : Real;   // sun's rising true longitude in radian
      tempRiseAscension : Real;   // sun's rising rigth ascension
      tempRiseAscensRad : Real;   // sun's rising rigth ascension in radian
      tempSinDeclination : Real;   // sin of Sun's declination
      tempCosDeclination : Real;   // cos of Sun's declination
      tempCosLocHourAngle : Real;   // cos Sun's local hour angle
      tempLocHourAngle : Real;   // Sun's local hour angle
      tempLocalMeamTime : Real;   // local mean time of rising / setting
      tempUTC : Real;   // UTC time of rising / setting
      tempLocalTime : Real;   // local time of rising / setting
      tempRetval : Int;   // status of the used instructions
      tempIntSunrise {InstructionName := 'DTL'; LibVersion := '1.0'} : DTL;   // calculation int Sunrise
      tempIntSunset {InstructionName := 'DTL'; LibVersion := '1.0'} : DTL;   // calculation int Sunset
      tempIntLatDD : Real;   // latitude decimal degrees; North = positive; South = negative
      tempIntLonDD : Real;   // longitude decimal degrees; East=Positive; West = negative
      tempLatAuxDMS : Real;   // latitude in decimal degrees
      tempLatAuxMinDMS : Real;   // minutes in decimal degrees
      tempLatAuxSecDMS : Real;   // seconds in decimal degrees
      tempLonAuxDMS : Real;   // longitude in decimal degrees
      tempLonAuxMinDMS : Real;   // minutes in decimal degrees
      tempLonAuxSecDMS : Real;   // seconds in decimal degrees
      tempDate1Jan {InstructionName := 'DTL'; LibVersion := '1.0'} : DTL;
   END_VAR

   VAR CONSTANT 
      NORTH1 : Char := 'n';   // north
      NORTH2 : Char := 'N';   // North
      SOUTH1 : Char := 's';   // south
      SOUTH2 : Char := 'S';   // South
      EAST1 : Char := 'e';   // east
      EAST2 : Char := 'E';   // East
      WEST1 : Char := 'w';   // west
      WEST2 : Char := 'W';   // West
      PI : Real := 3.141593;   // Mathmatical constant 4*ATN(1)
      DEGREE_TO_RADIAN_0_0174 : Real := 0.01745329;   // multiply factor to get radian from degree
      RADIAN_TO_DEGREE_57_2957 : Real := 57.29578;   // multiply factor to get degree from radian
      ZENIT_1_58534 : LReal := 1.58534073722818;   // Sun's zenith for sunrise/sunset (in radian units)
      "0_0_DEG" : Real := 0.0;   // 0.0 degrees
      "15_0_DEG" : Real := 15.0;   // 15.0 degrees
      "90_0_DEG" : Real := 90.0;   // 90.0 degrees
      "180_0_DEG" : Real := 180.0;   // 180.0 degrees
      "360_0_DEG" : Real := 360.0;   // 360.0 degrees
      "59_MIN_OR_SEC" : UInt := 59;   // 59 minutes/seconds
      SECONDS_PER_HOUR : Real := 3600.0;   // conversion factor seconds to hour
      MINUTES_PER_HOUR : Real := 60.0;   // conversion factor minutes to hour
      HOURS_PER_DAY : Real := 24.0;   // 24 hours
      MS_PER_HOUR : Real := 3600000.0;
      TIME_ZERO {InstructionName := 'DTL'; LibVersion := '1.0'} : DTL;   // output hours, minutes, seconds to zero
      APPROXIMATE_TIME_6 : Int := 6;   // approximate time 6 hours
      APPROXIMATE_TIME_18 : Int := 18;   // approximate time 18 hours
      SUN_MEAN_ANOMALY_0_9856 : Real := 0.9856;   // sun mean anomaly 0.9856
      SUN_MEAN_ANOMALY_3_289 : Real := 3.289;   // sun mean anomaly 3.289
      SUN_TRUE_LONGITUDE_0_02 : Real := 0.02;   // sun true longitude 0.02
      SUN_TRUE_LONGITUDE_1_916 : Real := 1.916;   // sun true longitude 1.916
      SUN_TRUE_LONGITUDE_2_0 : Real := 2.0;   // sun true longitude 2.0
      SUN_TRUE_LONGITUDE_282_634 : Real := 282.634;   // sun true longitude 282.634
      SUN_RIGHT_ASCENSION_0_91764 : Real := 0.91764;   // sun right ascension 0.91764
      SUN_RIGHT_ASCENSION_2_0 : Real := 2.0;   // sun right ascension 2.0
      SUN_DECLINATION_0_39782 : Real := 0.39782;   // sun declination 0.39782
      SUM_LOCAL_HOUR_ANGLE : Int := 1;   // summ local hour angle
      LOCAL_MEAN_TIME_0_06571 : Real := 0.06571;   // -
      LOCAL_MEAN_TIME_6_622 : Real := 6.622;   // -
      NO_ERROR : Word := 16#0000;   // -
      NO_CURRENT_JOBS : Word := 16#7000;   // -
      ERROR_LAT_DMS_DIR : Word := 16#8200;   // error Latitude DMS direction
      ERROR_LAT_DMS_VAL : Word := 16#8201;   // error Latitude DMS value
      ERROR_LON_DMS_DIR : Word := 16#8202;   // error Longitude DMS direction
      ERROR_LON_DMS_VAL : Word := 16#8203;   // error Longitude DMS value
      ERROR_LAT_DD_VAL : Word := 16#8204;   // error Latitude DD value
      ERROR_LON_DD_VAL : Word := 16#8205;   // error Longitude DD value
      ERROR_IN_THIS_BLOCK : UInt := 1;   // error in this block
      ERROR_RD_SYS_T : UInt := 2;   // error instruction RD_SYS_T
      ERROR_RD_LOC_T : UInt := 3;   // error instruction RD_LOC_T
   END_VAR


BEGIN
	//=============================================================================
	// SIEMENS AG
	// (c)Copyright 2017 
	//-----------------------------------------------------------------------------
	// Library:       LGF (Library General Functions)
	// Tested with:   CPU1212C DC/DC/DC FW:V4.2
	// Engineering:   TIA Portal V14 Update 1
	// Restrictions:  -
	// Requirements:  PLC (S7-1200 / S7-1500)
	// Functionality: Astronomical clock, optional offset, input format DMS or DD
	//-----------------------------------------------------------------------------
	// Change log table:
	// Version Date        In charge / Changes applied
	// 01.00.00 19.08.2015 Siemens Industry Online Support
	//                     First released version
	// 01.00.01 01.10.2015 Siemens Industry Online Support
	//                     T_ADD instruction is replaced with "+"
	// 01.00.02 16.11.2015 Siemens Industry Online Support
	//                     "offsetSunrise", "offsetSunset" is calculated in
	//                     "daytime"
	//                     Bug fix at "Adjust back TO UTC"
	// 01.01.00 07.06.2015 Siemens Industry Online Support
	//                     Add output actSystemTime and actLocalTime
	// 01.01.01 15.06.2015 Siemens Industry Online Support
	//                     Add comments
	// 01.01.02 04.01.2017 Siemens Industry Online Support
	//                     Bug fix at calculation sunrise and sunset
	// 01.01.03 20.01.2017 Siemens Industry Online Support
	//                     Upgrade: TIA V14 Update 1
	// 01.01.04 22.02.2017 Siemens Industry Online Support
	//                     Code optimization
	// 01.01.05 09.07.2018 Siemens Industry Online Support
	//                     Initialize #tempIntSunrise, #tempIntSunset,#tempDate1Jan 
	//=============================================================================
	// Function:
	// Your position may be entered at LatitudeDD/LongitudeDD, ModeDMS = 0
	// Format signed degree(decimal)
	// or
	// your position may be entered at LatitudeDMS/LongitudeDMS, ModeDMS = 1
	// Format direction, degree, minute, second
	// 
	// OffsetSunrise is added to Latitude and output at Sunrise
	// OffsetSunset is added to Longitude and output at Sunset
	// 
	// daytime is set when the actual time is inbetween Sunrise and Sunset
	// ============================================================================
	// Advice:
	// please take care that the system time is permanently synchronizes anyhow
	// ============================================================================
	// Abbreviations
	// lon: Longitude
	// lat: Latitude
	// dir: direction (valid characters: n, N, s, S, e, E, w, W)
	// DD: decimal degrees (type Real)
	// DMS: degrees, minutes, seconds (all types UINT)
	//=============================================================================
	// If a faulty value is entered at LatitudeDD and ModeDMS = 0
	// then the value of Sunrise is set to zero
	// and the value of Sunset is set to zero
	// and daytime is set to zero
	// 
	// If a faulty value is entered at LatitudeDMS and ModeDMS = 1
	// then the value of Sunrise ist set to zero
	// and the value of Sunset is set to zero 
	// and daytime is set to zero
	//=============================================================================
	
	// Set "No current job" status
	#error := false;
	#statusID := #ERROR_IN_THIS_BLOCK;
	#status := #NO_CURRENT_JOBS;
	
	// Initialization
	#sunrise := #TIME_ZERO;
	#sunset := #TIME_ZERO;
	#tempIntSunrise := #TIME_ZERO;
	#tempIntSunset := #TIME_ZERO;
	#tempDate1Jan := #TIME_ZERO;
	
	REGION System time, local time, time zone
	  // Reading system and local time ==============================================
	  #tempRetval := RD_SYS_T(#tempSysTime); // Reading system time UTC
	  #actSystemTime := #tempSysTime; // Output system time UTC
	  
	  IF (#tempRetval > 1)
	  THEN
	    #error := true;
	    #statusID := #ERROR_RD_SYS_T;
	    #status := INT_TO_WORD(#tempRetval);
	    RETURN;
	  END_IF;
	  
	  #tempRetval := RD_LOC_T(#tempOfficLocTime); // Reading official actual local time
	  #actLocalTime := #tempOfficLocTime; // Output official actual local time
	  
	  IF (#tempRetval > 1)
	  THEN
	    #error := true;
	    #statusID := #ERROR_RD_LOC_T;
	    #status := INT_TO_WORD(#tempRetval);
	    RETURN;
	  END_IF;
	  
	  // Calculation of time difference #tempSysTime - #tempOfficLocTime ============
	  #tempTimeZone := DINT_TO_REAL(TIME_TO_DINT(T_DIFF(IN1 := #tempSysTime, IN2 := #tempOfficLocTime))) / #MS_PER_HOUR;
	END_REGION //System time, local time, time zone
	
	REGION DMS input value check and convert to DD
	  // DMS input value check and convert to DD ====================================
	  IF (#modeDMS = 1)
	  THEN
	    // Latitude =================================================================
	    // Convert seconds to decimal degrees
	    #tempLatAuxSecDMS := UINT_TO_REAL(#latitudeDMS.sec)
	    / #SECONDS_PER_HOUR;
	    
	    // Convert minutes to decimal degrees
	    #tempLatAuxMinDMS := UINT_TO_REAL(#latitudeDMS.min)
	    / #MINUTES_PER_HOUR;
	    
	    // Sum of decimal degrees, minutes and seconds
	    #tempLatAuxDMS := #latitudeDMS.deg + #tempLatAuxMinDMS + #tempLatAuxSecDMS;
	    
	    IF (#latitudeDMS.dir = #SOUTH1)
	    THEN
	      #tempLatAuxDMS := - (#tempLatAuxDMS); // Negate value if south 's'
	      
	    ELSIF (#latitudeDMS.dir = #SOUTH2)
	    THEN
	      #tempLatAuxDMS := - (#tempLatAuxDMS); // Negate value if south 'S'
	      
	    ELSIF (#latitudeDMS.dir = #NORTH1)
	    THEN
	      ;                                     // Positive value if north 'n'
	      
	    ELSIF (#latitudeDMS.dir = #NORTH2)
	    THEN
	      ;                                     // Positive value if north 'N'
	      
	    ELSE                                    // ErrorLatDMS: direction
	      #error := true;
	      #statusID := #ERROR_IN_THIS_BLOCK;
	      #status := #ERROR_LAT_DMS_DIR;
	    END_IF;
	    
	    // Sum input latitude decimal degrees, minutes & seconds > 90°, set fault
	    IF (ABS(#tempLatAuxDMS) > #"90_0_DEG")
	    THEN
	      #error := true;
	      #statusID := #ERROR_IN_THIS_BLOCK;
	      #status := #ERROR_LAT_DMS_VAL;
	    END_IF;
	    
	    // Check value input limits, latitude minutes > 59, set fault
	    IF (#latitudeDMS.min > #"59_MIN_OR_SEC")
	    THEN
	      #error := true;
	      #statusID := #ERROR_IN_THIS_BLOCK;
	      #status := #ERROR_LAT_DMS_VAL;
	      RETURN;
	    END_IF;
	    
	    // Check value limits input, latitude seconds > 59, set fault
	    IF (#latitudeDMS.sec > #"59_MIN_OR_SEC")
	    THEN
	      #error := true;
	      #statusID := #ERROR_IN_THIS_BLOCK;
	      #status := #ERROR_LAT_DMS_VAL;
	    END_IF;
	    
	    // Longitude ================================================================
	    // Convert seconds TO decimal degrees
	    #tempLonAuxSecDMS := UINT_TO_REAL(#longitudeDMS.sec)
	    / #SECONDS_PER_HOUR;
	    
	    // Convert minutes to decimal degrees
	    #tempLonAuxMinDMS := UINT_TO_REAL(#longitudeDMS.min)
	    / #MINUTES_PER_HOUR;
	    
	    // Sum of decimal degrees, minutes and seconds 
	    #tempLonAuxDMS := #longitudeDMS.deg + #tempLonAuxMinDMS + #tempLonAuxSecDMS;
	    
	    IF (#longitudeDMS.dir = #WEST1)
	    THEN
	      #tempLonAuxDMS := - (#tempLonAuxDMS);  // Negate value if west 'w'
	      
	    ELSIF (#longitudeDMS.dir = #WEST2)
	    THEN
	      #tempLonAuxDMS := - (#tempLonAuxDMS);  // Negate value if west 'W'
	      
	    ELSIF (#longitudeDMS.dir = #EAST1)
	    THEN
	      ;                                    // Positive value if east 'e'
	      
	    ELSIF (#longitudeDMS.dir = #EAST2)
	    THEN
	      ;                                    // Positive value if east 'E'
	      
	    ELSE                                   // ErrorLonDMS: direction
	      #error := true;
	      #statusID := #ERROR_IN_THIS_BLOCK;
	      #status := #ERROR_LON_DMS_DIR;
	    END_IF;
	    
	    // Sum of longitude decimal degrees, minutes and seconds > 180°
	    IF (ABS(#tempLonAuxDMS) > #"180_0_DEG")
	    THEN
	      #error := true;
	      #statusID := #ERROR_IN_THIS_BLOCK;
	      #status := #ERROR_LON_DMS_VAL;
	    END_IF;
	    
	    // Check value limits input, longitude minutes > 59, set fault
	    IF (#longitudeDMS.min > #"59_MIN_OR_SEC")
	    THEN
	      #error := true;
	      #statusID := #ERROR_IN_THIS_BLOCK;
	      #status := #ERROR_LON_DMS_VAL;
	    END_IF;
	    
	    // Check value limits input,  longitude seconds > 59, set fault
	    IF (#longitudeDMS.sec > #"59_MIN_OR_SEC")
	    THEN
	      #error := true;
	      #statusID := #ERROR_IN_THIS_BLOCK;
	      #status := #ERROR_LON_DMS_VAL;
	    END_IF;
	    
	    // Case of wrong DMS input 
	    IF (#error = true)
	    THEN
	      #tempLatAuxDMS := #"0_0_DEG"; // Set value latitude to zero
	      #tempLonAuxDMS := #"0_0_DEG"; // Set value longitude to zero
	      RETURN;
	    END_IF;
	    
	    // Copy DMS values to work variables
	    #tempIntLatDD := #tempLatAuxDMS;
	    #tempIntLonDD := #tempLonAuxDMS;
	  END_IF;
	END_REGION // DMS input value check and convert to DD
	
	REGION DD input value check
	  // DD input value check =======================================================
	  IF (#modeDMS = 0)
	  THEN
	    // input latitude DD > 90°, set fault
	    IF (ABS(#latitudeDD) > #"90_0_DEG")
	    THEN
	      #error := true;
	      #statusID := #ERROR_IN_THIS_BLOCK;
	      #status := #ERROR_LAT_DD_VAL;
	    END_IF;
	    
	    // input longitude DD > 180°, set fault
	    IF (ABS(#longitudeDD) > #"180_0_DEG")
	    THEN
	      #error := true;
	      #statusID := #ERROR_IN_THIS_BLOCK;
	      #status := #ERROR_LON_DD_VAL;
	    END_IF;
	    
	    // Case of wrong DD input
	    IF (#error = true) THEN
	      #tempIntLatDD := #"0_0_DEG"; // Set value latitude to zero
	      #tempIntLonDD := #"0_0_DEG"; // Set value longitude to zero
	      RETURN;
	    END_IF;
	    
	    // Copy DD values to work variables
	    #tempIntLatDD := #latitudeDD;
	    #tempIntLonDD := #longitudeDD;
	  END_IF;
	  
	  // Converting the input values to work units ==================================
	  #tempLatitudeRad := #tempIntLatDD * #DEGREE_TO_RADIAN_0_0174;
	  
	  // Longitude [hours] = longitude [degrees]  * 24/360 = longitude [degrees] /15
	  #templngHour := #tempIntLonDD / #"15_0_DEG";
	END_REGION // DD input value check
	
	REGION Day of  the year
	  // Day of  the year
	  #tempDate1Jan.YEAR := #tempOfficLocTime.YEAR;
	  #tempDate1Jan.MONTH := 1;
	  #tempDate1Jan.DAY := 1;
	  #tempDayOfYear := UDINT_TO_REAL(DATE_TO_UDINT(DTL_TO_DATE(#tempOfficLocTime))
	                                  - DATE_TO_UDINT(DTL_TO_DATE(#tempDate1Jan)) + 1);
	END_REGION // Day of  the year
	
	REGION Calculate Sunrise
	  // Calculate Sunrise ========================================================== 
	  // Aproximate time 
	  #tempAppRiseTime := #tempDayOfYear + (#APPROXIMATE_TIME_6 - #templngHour)
	                      / #HOURS_PER_DAY;
	  
	  // Sun's mean anomaly
	  #tempRiseMeanAnomaly := #SUN_MEAN_ANOMALY_0_9856 * #tempAppRiseTime
	                          - #SUN_MEAN_ANOMALY_3_289;
	  
	  #tempRiseMeanRad := #tempRiseMeanAnomaly * #DEGREE_TO_RADIAN_0_0174;
	  
	  // Sun's true longitude
	  #tempRiseLongitude := #tempRiseMeanAnomaly
	                        + #SUN_TRUE_LONGITUDE_1_916 * SIN(#tempRiseMeanRad)
	                        + #SUN_TRUE_LONGITUDE_0_02 * SIN(#SUN_TRUE_LONGITUDE_2_0
	                        * #tempRiseMeanRad)
	                        + #SUN_TRUE_LONGITUDE_282_634;
	  
	  WHILE #tempRiseLongitude > #"360_0_DEG" DO
	    #tempRiseLongitude := #tempRiseLongitude - #"360_0_DEG";
	  END_WHILE;
	  
	  WHILE #tempRiseLongitude < #"0_0_DEG" DO
	    #tempRiseLongitude := #tempRiseLongitude + #"360_0_DEG";
	  END_WHILE;
	  
	  #tempRiseLonRad := #tempRiseLongitude * #DEGREE_TO_RADIAN_0_0174;
	  
	  // Sun's right ascension
	  #tempRiseAscensRad := ATAN(#SUN_RIGHT_ASCENSION_0_91764
	                             * TAN(#tempRiseLonRad));
	  
	  WHILE #tempRiseAscensRad > #SUN_RIGHT_ASCENSION_2_0 * #PI DO
	    #tempRiseAscensRad := #tempRiseAscensRad - #SUN_RIGHT_ASCENSION_2_0 * #PI;
	  END_WHILE;
	  
	  WHILE #tempRiseAscensRad < #"0_0_DEG" DO
	    #tempRiseAscensRad := #tempRiseAscensRad + #SUN_RIGHT_ASCENSION_2_0 * #PI;
	  END_WHILE;
	  
	  #tempRiseAscension := #tempRiseAscensRad * #RADIAN_TO_DEGREE_57_2957;
	  #tempRiseAscension := (#tempRiseAscension
	                        + DINT_TO_REAL(FLOOR(#tempRiseLongitude / #"90_0_DEG"))
	                        * #"90_0_DEG"
	                        - DINT_TO_REAL(FLOOR(#tempRiseAscension / #"90_0_DEG"))
	                        * #"90_0_DEG")
	                        / #"15_0_DEG";
	  
	  // Sun's declination
	  #tempSinDeclination := #SUN_DECLINATION_0_39782 * SIN(#tempRiseLonRad);
	  #tempCosDeclination := COS(ASIN(#tempSinDeclination));
	  
	  // Sun's local hour angle angle
	  #tempCosLocHourAngle := LREAL_TO_REAL((COS(#ZENIT_1_58534)
	                          - REAL_TO_LREAL(#tempSinDeclination
	                          * SIN(#tempLatitudeRad)))
	                          / (#tempCosDeclination * COS(#tempLatitudeRad)));
	  
	  IF (#tempCosLocHourAngle > #SUM_LOCAL_HOUR_ANGLE)
	  THEN
	    #tempCosLocHourAngle := #SUM_LOCAL_HOUR_ANGLE;
	  END_IF;
	  
	  IF (#tempCosLocHourAngle < - #SUM_LOCAL_HOUR_ANGLE)
	  THEN
	    #tempCosLocHourAngle := - #SUM_LOCAL_HOUR_ANGLE;
	  END_IF;
	  
	  // Calculate local hour angle for sunrise
	  #tempLocHourAngle := #"360_0_DEG" - ACOS(#tempCosLocHourAngle)
	                       * #RADIAN_TO_DEGREE_57_2957;
	  #tempLocHourAngle := #tempLocHourAngle / #"15_0_DEG";
	  
	  // Local mean time of rising/setting
	  #tempLocalMeamTime := #tempLocHourAngle + #tempRiseAscension
	                        - (#LOCAL_MEAN_TIME_0_06571 * #tempAppRiseTime)
	                        - #LOCAL_MEAN_TIME_6_622;
	  
	  // Adjust back TO UTC
	  #tempUTC := #tempLocalMeamTime - #templngHour;
	  
	  IF (#tempUTC > #HOURS_PER_DAY)
	  THEN
	    #tempUTC := #tempUTC - #HOURS_PER_DAY;
	  END_IF;
	  
	  IF (#tempUTC < 0)
	  THEN
	    #tempUTC := #tempUTC + #HOURS_PER_DAY;
	  END_IF;
	  
	  #tempLocalTime := #tempUTC - (#tempTimeZone);
	  
	  IF (#tempLocalTime >= #HOURS_PER_DAY)
	  THEN
	    #tempLocalTime := #tempLocalTime - DINT_TO_REAL(TRUNC(#tempLocalTime / #HOURS_PER_DAY) * 24);
	  END_IF;
	  
	  IF (#tempLocalTime < 0)
	  THEN
	    #tempLocalTime := #tempLocalTime + #HOURS_PER_DAY;
	  END_IF;
	  
	  // Convert #tempLocalTime to DTL (#tempIntSunrise)
	  #tempIntSunrise.YEAR := #tempOfficLocTime.YEAR;
	  #tempIntSunrise.MONTH := #tempOfficLocTime.MONTH;
	  #tempIntSunrise.DAY := #tempOfficLocTime.DAY;
	  #tempIntSunrise := #tempIntSunrise + UDINT_TO_TIME(REAL_TO_UDINT(#tempLocalTime * #MS_PER_HOUR));
	  #tempIntSunrise.NANOSECOND := 0;
	  
	END_REGION // Calculate Sunrise
	
	REGION Calculate Sunset
	  // Calculate Sunset ===========================================================
	  // Aproximate time 
	  #tempAppRiseTime := #tempDayOfYear + (#APPROXIMATE_TIME_18 - #templngHour)
	                      / #HOURS_PER_DAY;
	  
	  // Sun's mean anomaly
	  #tempRiseMeanAnomaly := #SUN_MEAN_ANOMALY_0_9856 * #tempAppRiseTime
	                          - #SUN_MEAN_ANOMALY_3_289;
	  
	  #tempRiseMeanRad := #tempRiseMeanAnomaly * #DEGREE_TO_RADIAN_0_0174;
	  
	  // Sun's true longitude
	  #tempRiseLongitude := #tempRiseMeanAnomaly
	                        + #SUN_TRUE_LONGITUDE_1_916 * SIN(#tempRiseMeanRad)
	                        + #SUN_TRUE_LONGITUDE_0_02 * SIN(#SUN_TRUE_LONGITUDE_2_0
	                        * #tempRiseMeanRad)
	                        + #SUN_TRUE_LONGITUDE_282_634;
	  
	  WHILE #tempRiseLongitude > #"360_0_DEG" DO
	    #tempRiseLongitude := #tempRiseLongitude - #"360_0_DEG";
	  END_WHILE;
	  
	  WHILE #tempRiseLongitude < #"0_0_DEG" DO
	    #tempRiseLongitude := #tempRiseLongitude + #"360_0_DEG";
	  END_WHILE;
	  
	  #tempRiseLonRad := #tempRiseLongitude * #DEGREE_TO_RADIAN_0_0174;
	  
	  // Sun's right ascension
	  #tempRiseAscensRad := ATAN(#SUN_RIGHT_ASCENSION_0_91764
	                             * TAN(#tempRiseLonRad));
	  
	  WHILE #tempRiseAscensRad > #SUN_RIGHT_ASCENSION_2_0 * #PI DO
	    #tempRiseAscensRad := #tempRiseAscensRad - #SUN_RIGHT_ASCENSION_2_0 * #PI;
	  END_WHILE;
	  
	  WHILE #tempRiseAscensRad < #"0_0_DEG" DO
	    #tempRiseAscensRad := #tempRiseAscensRad + #SUN_RIGHT_ASCENSION_2_0 * #PI;
	  END_WHILE;
	  
	  #tempRiseAscension := #tempRiseAscensRad * #RADIAN_TO_DEGREE_57_2957;
	  #tempRiseAscension := (#tempRiseAscension
	                        + DINT_TO_REAL(FLOOR(#tempRiseLongitude / #"90_0_DEG"))
	                        * #"90_0_DEG"
	                        - DINT_TO_REAL(FLOOR(#tempRiseAscension / #"90_0_DEG"))
	                        * #"90_0_DEG")
	                        / #"15_0_DEG";
	  
	  // Sun's declination
	  #tempSinDeclination := #SUN_DECLINATION_0_39782 * SIN(#tempRiseLonRad);
	  #tempCosDeclination := COS(ASIN(#tempSinDeclination));
	  
	  // Sun's local hour angle
	  #tempCosLocHourAngle := LREAL_TO_REAL((COS(#ZENIT_1_58534)
	                          - REAL_TO_LREAL(#tempSinDeclination
	                          * SIN(#tempLatitudeRad)))
	                          / (#tempCosDeclination * COS(#tempLatitudeRad)));
	  
	  IF (#tempCosLocHourAngle > #SUM_LOCAL_HOUR_ANGLE)
	  THEN
	    #tempCosLocHourAngle := #SUM_LOCAL_HOUR_ANGLE;
	  END_IF;
	  
	  IF (#tempCosLocHourAngle < - #SUM_LOCAL_HOUR_ANGLE)
	  THEN
	    #tempCosLocHourAngle := - #SUM_LOCAL_HOUR_ANGLE;
	  END_IF;
	  
	  // Calculation local hour angle for sunset
	  #tempLocHourAngle := ACOS(#tempCosLocHourAngle) * #RADIAN_TO_DEGREE_57_2957;
	  #tempLocHourAngle := #tempLocHourAngle / #"15_0_DEG";
	  
	  // Local mean time of rising/setting
	  #tempLocalMeamTime := #tempLocHourAngle + #tempRiseAscension
	                        - (#LOCAL_MEAN_TIME_0_06571 * #tempAppRiseTime)
	                        - #LOCAL_MEAN_TIME_6_622;
	  
	  // Adjust back TO UTC
	  #tempUTC := #tempLocalMeamTime - #templngHour;
	  
	  IF (#tempUTC > #HOURS_PER_DAY)
	  THEN
	    #tempUTC := #tempUTC - #HOURS_PER_DAY;
	  END_IF;
	  
	  IF (#tempUTC < 0)
	  THEN
	    #tempUTC := #tempUTC + #HOURS_PER_DAY;
	  END_IF;
	  
	  #tempLocalTime := #tempUTC - (#tempTimeZone);
	  
	  IF (#tempLocalTime >= #HOURS_PER_DAY)
	  THEN
	    #tempLocalTime := #tempLocalTime - DINT_TO_REAL(TRUNC(#tempLocalTime / #HOURS_PER_DAY) * 24);
	  END_IF;
	  
	  IF (#tempLocalTime < 0)
	  THEN
	    #tempLocalTime := #tempLocalTime + #HOURS_PER_DAY;
	  END_IF;
	  
	  // Convert #tempLocalTime to DTL (#tempIntSunset)
	  #tempIntSunset.YEAR := #tempOfficLocTime.YEAR;
	  #tempIntSunset.MONTH := #tempOfficLocTime.MONTH;
	  #tempIntSunset.DAY := #tempOfficLocTime.DAY;
	  #tempIntSunset := #tempIntSunset + UDINT_TO_TIME(REAL_TO_UDINT(#tempLocalTime * #MS_PER_HOUR));
	  #tempIntSunset.NANOSECOND := 0;
	  
	END_REGION // Calculate Sunset
	
	REGION Write output (sunrise, sunset, daytime)
	  // Considering offset and write output ========================================
	  // Sunrise 
	  #tempIntSunrise := #tempIntSunrise + #offsetSunrise;
	  #sunrise := #tempIntSunrise;
	  
	  // Sunset 
	  #tempIntSunset := #tempIntSunset + #offsetSunset;
	  #sunset := #tempIntSunset;
	  
	  // Evaluate Day (between Sunrise and Sunset) ==================================
	  IF (#tempOfficLocTime >= #tempIntSunrise)
	    AND (#tempOfficLocTime <= #tempIntSunset)
	  THEN
	    #daytime := TRUE;
	  ELSE
	    #daytime := FALSE;
	  END_IF;
	END_REGION // Write output
	
	// No errors
	#status := #NO_ERROR;
END_FUNCTION_BLOCK
 
Harald, warum glaubst Du, dass der RD_LOC_T falsch unterbrochen wird?
Sieht für mich doch auch eher so aus, dass der DTL_TO_TOD falsch unterbrochen wird?

Im Astrobaustein siehts jetzt auf den ersten Blick nicht so aus, dass da Schweinereien passieren...
 
Das blöde an den Interrupts ist doch, dass der Maschinencode der letztendlich auf der CPU ausgeführt wird (ganz) anders aussieht, als der SCL Code... Da weiss doch niemand, was da genau wann unterbrochen wird...
 
Nach einer Nacht drüber schlafen, entstehen doch ein paar mehr Fragen als gelöst wurden.

Das fehlerhafte Beschreiben einer globalen Variable in verschiedenen Task ist wohl nicht der einzige Fehler. Dadurch würde nicht eine gesamte Variable auf 0 bzw. T#0s gehen. (Da würden höchstens mal falsche Zeiten mit Rückwärts-Sprüngen auftauchen.) Die T#0s können auch von der Konvertierung DTL_TO_TOD und impliziter Konvertierung TOD_TO_TIME kommen oder durch Kommunikation von außerhalb der CPU. Oder gibt es noch weiteren Code wo "nicht" auf globale Variablen geschrieben wird? Vielleicht bringt auch mittlerweise der hier nicht gezeigte verzweifelte Test/Hilfscode auch noch Fehler mit? Leider drückt sich der TE auch so ungenau formuliert aus, daß das Problem schwer einzugrenzen ist.

Ist das wirklich sooo schwer, mal konzentriert zu suchen und zu testen, wo genau was da falsch läuft? Vor allem wenn der Fehler doch ziemlich häufig passiert ("IM OB 30 in ca. 26 von 600 Aufrufen." - also etwa 26 mal in 1 Minute)? Ich verwende TIA V16 noch nicht. Ich kann bei der Analyse des Projektes zur Zeit leider nur theoretisch helfen.

Harald
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Harald, warum glaubst Du, dass der RD_LOC_T falsch unterbrochen wird?
Sieht für mich doch auch eher so aus, dass der DTL_TO_TOD falsch unterbrochen wird?
Es kann beides sein, und auch andere Gründe haben. Diese Stelle im OB1 soll "hoch und heilig" die einzige Stelle sein wo auf "Akt".Uhrzeit geschrieben wird:
Code:
#RETURNVALUE := RD_LOC_T("Akt".Localzeit);

"Akt".Uhrzeit := DTL_TO_TOD("Akt".Localzeit);
Wenn in diesem Code am Ende "Akt".Uhrzeit = T#0s ist, dann wurde entweder "Akt".Localzeit irgendwie auf T#0s geschrieben oder DTL_TO_TOD hat das T#0s irgendwie erzeugt. Oder "Akt".Uhrzeit wurde in einer Unterbrechung während oder nach der Zuweisung auf T#0s überschrieben, vielleicht auch gar nicht an dieser Stelle im OB1... Wo genau stellt der TE fest, daß "Akt".Uhrzeit = T#0s ist ???

Harald
 
Da man den erzeugten echten Maschinencode nicht kennt, wird man eh Probleme haben, interne Fehler herauszufinden.
Ich erinnere mich an enen ähnlichen Fehler mit einer 318, da leuchtete ab und an die Fehlerlampe der Anage (sonst hätte das keiner mitbekommen) und ich konnte partout nicht herausfinden, wo der Ausgang auf True geschrieben wurde. Er wurde nut einmal im Programm zugewiesen und da passierte das nicht. Schlußendlich war es entweder ebenfalls ein Interrupt oder eine indirekte Adressierung, die auf einen zu großen Bereich erfolgte und so "über das Ziel hinaus" ging. Das hat die S7 damals gar nicht mitbekommen.

Insofern kann ich mit gut vorstellen, dass die Konvertierung oder ein Interrupt die Ursache sein können, aber auch ein Firmware- oder Compilerfehler würde mcih mal so gar nicht wundern.

Man könnte hier evtl. mal die ganz alte Methode versuchen und nach und nach Codeteile vom Programm ausschließen.

PS: TIA ins Atomkraftwerk würde ich empfehlen!
 
Zuletzt bearbeitet:
Zurück
Oben