Mit SCL Zeiten vergleichen aus UTD

emilio20

Level-1
Beiträge
835
Reaktionspunkte
20
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo ich benötige wiedermal eure Hilfe in SCL

Ich möchte bei meiner Heizungssteuerung Zeiten vergleichen, die in einem DB34 als Zeiten Schaltuhr liegen, verweis auf UTD1 Tage Sonntag bis Sammstag verweis auf UTD 2 Heizung EIN, Heizung AUS, Absenkung EIN, Absenkung ;AUS; siehe Bilder.

Die Wochentage bekomme ich als Zahl von 1-7.

Jetzt mochte ich in SCL am Sonntag einen Bit ausgeben vom Zeitraum Heizung EIN und Heizung aus.
Desweiterne soll ein Bit von Absenkung EIN und Absenkung Aus ausgegeben werden. Dies soll für jeden Wochentag geschehen

Als erstes habe ich mal versucht mit einer For schleife nur die die DB adressen von Sonntag in einer Variable zu Speichern
z.b
siehe Bild Da stimmt aber garnichts sage ich gleich mal




Kann mir da jemand weiterhelfen ?
 

Anhänge

  • DB34.JPG
    DB34.JPG
    24 KB · Aufrufe: 24
  • UDT1.JPG
    UDT1.JPG
    47,4 KB · Aufrufe: 26
  • UTD2.JPG
    UTD2.JPG
    41,2 KB · Aufrufe: 21
  • scl.JPG
    scl.JPG
    29,9 KB · Aufrufe: 48
Hallo,
aus deinen Anhängen kann ich keine Beziehung zu deiner beschriebenen Aufgabenstellung herstellen.
Ist aber nicht schlimm - das kriegen wir sicherlich noch ... ;)

Erstmal ein paar Fragen von mir :
1.) du erstellst dir einen FB ?
2.) woher erhältst du die Information des Wochentages ?
3.) warum arbeitest du bezüglich der Zeiten mit einem externen DB und nicht mit IN-Parametern des FB's ? Das hielte ich für praktikabler und du brauchst dir den Kram nicht in den Baustein kopieren ...

Gruß
Larry
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Um aber die Sachen in dein Array zu bekommen würde ich so vorgehen :
Code:
for i := 0 to 1 by 1 do
   Zeit_Heiz[i] := DWORD_to_TOD(DB34.DBD[i*4]) ;
   Zeit_Absenk[i] := DWORD_to_TOD(DB34.DBD[(i+2)*4]) ;
end_for ;

Nachsatz :
Die absoluten DB-Zugriffe werden nur in der Grundform der Variablen durchgeführt (also BIT, Byte, Word, DWord). Wird ein anderes Format benötigt muß dann erst eine Typ-Umwandlung erfolgen (auch ein Grund, warum ich es so nicht machen würde).
Ich hoffe, dass es den Befehl DWord_to_TOD gibt (ich kann es gerade nicht nachschauen). Ansonsten müßtest du hier zu deinem deklarierten Array noch eine AT_Sicht im Format DWord machen ...

Gruß
Larry
 
Zuletzt bearbeitet:
Die information des wochentage erhalte ich von einem anderen FC wo ich den Wochentag aus der SPS Zeit Extrahiere. Dieser ist von 1-7.

Die Zahl steh in einen anderen DB.

Der Externe DB ist dafür da um die Zeiten in Panel Darzustellen.

Danke schon mal für die Hilfe ich versuche mal mein glück.
 
Vielleicht mal so zur Anregung um die absolute Adressierung rauszuwerfen:

Wenn du deine Wochenschaltuhr im Datenbaustein umstrukturierst, und nicht so wie du es jetzt hast als einzelne Tage sondern als Array anlegst, also:
Code:
STRUCT 	
   SCHALTUHR : ARRAY  [1 .. 7 ] OF UDT 2;	
END_STRUCT ;
dann stehen Array Index 1 dabei für Sonntag, 2 für Montag usf.

Dann kannst du in Scl ganz einfach auf die Daten des aktuellen Wochentages zugreifen.
Als Eingabeparameter für einen FC z.B.
Code:
VAR_INPUT
    Wochentag : INT; // 1=So, 2=Mo, ...
    Wochenschalt : ARRAY[1..7] OF udt 2; // 1=So, 2=Mo, ...
END_VAR

(Wenn du einen FB anstelle eines FC verwenden willst, würde ich "Wochenschalt " als VAR_IN_OUT anlegen, weil ansonsten die Werte per Wert übergeben werden, was im späteren Instanz-DB nochmal den gleichen Speicherplatz benötigt.)

Auf die Daten der Wochenschaltuhr kannst du dann einfach mit:
Code:
ZEIT_HEIZ := Wochenschalt[Wochentag].HEIZUNG_EIN;
ZEIT_ABSENK := Wochenschalt[Wochentag].ABSENKTEMPERATUR_EIN;
zugreifen.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Habe es jetzt mal so versucht, das der wert aus der entsprechenden Variable in die aktuelle Variable geschrieben wird. Geht aber nicht, kommen nur fehler beim SCl


Code:
FUNCTION FC34 : INT

(*********************************************************
  Adresierung
 ***********************************************************)


VAR_INPUT
  Wochentag : INT;
    
END_VAR

VAR_OUTPUT
    
    
END_VAR

VAR
    // Zeit Heizung Ein / Aus Aktuelle
  Z_HEIZ_EIN_AKT : DWORD;
  Z_HEIZ_AUS_AKT : DWORD;
    // Zeit Absenkung Ein / Aus Aktuell
  Z_ABSE_EIN_AKT : DWORD;
  Z_ABSE_AUS_AKT : DWORD; 
  
  i : INT;

END_VAR 

BEGIN


   i := (Wochentag-1)*16
   
   Z_HEIZ_EIN_AKT := DWORD_to_TOD(DB34.DBD[0+i]) ;
   Z_HEIZ_AUS_AKT := DWORD_to_TOD(DB34.DBD[4+i]) ;
   Z_ABSE_EIN_AKT := DWORD_to_TOD(DB34.DBD[8+i]) ;
   Z_ABSE_AUS_AKT := DWORD_to_TOD(DB34.DBD[12+i]) ;
   
   
   
   

FC34 := 100;

END_FUNCTION
Fehler
 

Anhänge

  • Fehler.JPG
    Fehler.JPG
    79,6 KB · Aufrufe: 16
Zuletzt bearbeitet:
Hallo Thomas das versuche ich auch mal Danke Aber wich berechne ich da die Adresse so wie in meinem Beispiel ?
 
Zuletzt bearbeitet:
Hi,

Habe es jetzt mal so versucht, das der wert aus der entsprechenden Variable in die aktuelle Variable geschrieben wird. Geht aber nicht, kommen nur fehler beim SCl...

Strichpunkt vergessen, sollte das nicht * 32 sein wegen DWORD.
Code:
i := (Wochentag-1)*16;
und DWORD_TO_TOD ist auch Käse deine Variable ist ja schon vom Typ DWORD.

Gruss Daniel
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Zu deinem anderen Beispiel: Warum legst du die Variablen denn als DWORD an wenn im Datenbaustein ein TIME_OF_DAY steht?
Für die Konvertierung eines DWORD in TIME_OF_DAY musst du noch einen Zwischenschritt über ein DINT einfügen.

DINT_TO_TOD(DWORD_TO_DINT(...))

Es gibt aber noch andere Möglichkeiten um sich diese absolute Adressierung zu ersparen. Du könntest z.B. auch die UDT1 als Parameter anlegen, und dann mit einem Case je nach Wochentag auf die Daten zugreifen. Dann hast du keine Magic-numbers im Programm und die ganzen Konvertierungen fallen auch weg.
 
Hallo Ich möcht TIME_OF_DAY vergleichen dachte das geht nicht.

Ich möchte einfach die werte des Aktuellen Tages in die Variablen Akuell verschieben und Ausgeben. Dann kann ich mit FUP die Verte vergleichen und einen Bit schalten.

Ich habe keine großen SCL erfahrungen.
 
Zu deinem anderen Beispiel: Warum legst du die Variablen denn als DWORD an wenn im Datenbaustein ein TIME_OF_DAY steht?
Für die Konvertierung eines DWORD in TIME_OF_DAY musst du noch einen Zwischenschritt über ein DINT einfügen.

DINT_TO_TOD(DWORD_TO_DINT(...))

Es gibt aber noch andere Möglichkeiten um sich diese absolute Adressierung zu ersparen. Du könntest z.B. auch die UDT1 als Parameter anlegen, und dann mit einem Case je nach Wochentag auf die Daten zugreifen. Dann hast du keine Magic-numbers im Programm und die ganzen Konvertierungen fallen auch weg.

Kannst du mir ein Beispiel zeigen wie das geht ?
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Kannst du mir ein Beispiel zeigen wie das geht ?
Code:
VAR_INPUT
    Wochentag : INT;
    Wochenschalt : udt1;    
END_VAR

VAR_TEMP
    ZEIT_HEIZ : TIME_OF_DAY;
    ZEIT_ABSENK : TIME_OF_DAY;
END_VAR

BEGIN
    CASE Wochentag OF
        1: 
            ZEIT_HEIZ := Wochenschalt.SONNTAG.HEIZUNG_EIN;
            ZEIT_ABSENK := Wochenschalt.SONNTAG.ABSENKTEMPERATUR_EIN;
        2: 
            ZEIT_HEIZ := Wochenschalt.MONTAG.HEIZUNG_EIN;
            ZEIT_ABSENK := Wochenschalt.MONTAG.ABSENKTEMPERATUR_EIN;
        3: 
            ZEIT_HEIZ := Wochenschalt.DIENSTAG.HEIZUNG_EIN;
            ZEIT_ABSENK := Wochenschalt.DIENSTAG.ABSENKTEMPERATUR_EIN;
        4: 
            ZEIT_HEIZ := Wochenschalt.MITTWOCH.HEIZUNG_EIN;
            ZEIT_ABSENK := Wochenschalt.MITTWOCH.ABSENKTEMPERATUR_EIN;
        5: 
            ZEIT_HEIZ := Wochenschalt.DONNERSTAG.HEIZUNG_EIN;
            ZEIT_ABSENK := Wochenschalt.DONNERSTAG.ABSENKTEMPERATUR_EIN;
        6: 
            ZEIT_HEIZ := Wochenschalt.FREITAG.HEIZUNG_EIN;
            ZEIT_ABSENK := Wochenschalt.FREITAG.ABSENKTEMPERATUR_EIN;
        7: 
            ZEIT_HEIZ := Wochenschalt.SAMSTAG.HEIZUNG_EIN;
            ZEIT_ABSENK := Wochenschalt.SAMSTAG.ABSENKTEMPERATUR_EIN;
    END_CASE;

Mach den Zeitvergleich doch auch gleich in SCL. Da ist das doch alles viel einfacher.
 
Danke schon mal für das Beispiel.

1.Da muss man ja alles eingeben. Das muss doch auch mit einer Berechnung der Adresse gehen, ohne das mann alles eingeben muss.

2 Wie vergleiche ich 2 Zeiten in SCL ?

Habe es jetzt so geht aber ach nicht Ist was an der Addresierung falsch ?

Code:
FUNCTION FC34 : INT

(*********************************************************
  Adresierung
 ***********************************************************)


VAR_INPUT
      Wochentag : INT; // 1=So, 2=Mo, ...
          
END_VAR

VAR_OUTPUT
    
    
END_VAR

VAR
    // Zeit Heizung Ein / Aus Aktuelle
  Z_HEIZ_EIN_AKT : TOD;
  Z_HEIZ_AUS_AKT : TOD;
    // Zeit Absenkung Ein / Aus Aktuell
  Z_ABSE_EIN_AKT : TOD;
  Z_ABSE_AUS_AKT : TOD;
  
  i : INT;

END_VAR 

BEGIN


   i := (Wochentag-1)*16;
   
   Z_HEIZ_EIN_AKT := (DB34.DBD[0+i]);
   Z_HEIZ_AUS_AKT := (DB34.DBD[4+i]);
   Z_ABSE_EIN_AKT := (DB34.DBD[8+i]);
   Z_ABSE_AUS_AKT := (DB34.DBD[12+i]);
      
   
   
   

FC34 := 100;

END_FUNCTION
 

Anhänge

  • DB34offen.JPG
    DB34offen.JPG
    199,3 KB · Aufrufe: 8
Hi,

Code:
TYPE UDT1
  STRUCT
    HEIZUNG_EIN : TOD;
    HEIZUNG_AUS : TOD;
    ABSENK_EIN : TOD;
    ABSENK_AUS : TOD;
  END_STRUCT
END_TYPE


DATA_BLOCK DB1
  STRUCT
    SCHALTUHR : ARRAY[1..7] OF UDT1;  
  END_STRUCT
BEGIN

END_DATA_BLOCK


FUNCTION FC34 : VOID

VAR_INPUT
  Wochentag : INT;
END_VAR

VAR_IN_OUT
  SCHALTUHR : ARRAY[1..7] OF UDT1;  
END_VAR
  
VAR_OUTPUT
  // Zeit Heizung Ein / Aus Aktuelle
  Z_HEIZ_EIN_AKT : TOD;
  Z_HEIZ_AUS_AKT : TOD;
  // Zeit Absenkung Ein / Aus Aktuell
  Z_ABSE_EIN_AKT : TOD;
  Z_ABSE_AUS_AKT : TOD; 
END_VAR
  
BEGIN

  Z_HEIZ_EIN_AKT := SCHALTUHR[Wochentag].HEIZUNG_EIN;
  Z_HEIZ_AUS_AKT := SCHALTUHR[Wochentag].HEIZUNG_AUS;
  Z_ABSE_EIN_AKT := SCHALTUHR[Wochentag].ABSENK_EIN;
  Z_ABSE_AUS_AKT := SCHALTUHR[Wochentag].ABSENK_AUS;

END_FUNCTION

;)

Gruss Daniel
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Code:
      CALL  FC    34
       Wochentag     :=MW0
       Z_HEIZ_EIN_AKT:=MD2
       Z_HEIZ_AUS_AKT:=MD6
       Z_ABSE_EIN_AKT:=MD10
       Z_ABSE_AUS_AKT:=MD14
       SCHALTUHR     :=DB1.SCHALTUHR

Gruss Daniel
 
Danke Dalbi

Mich interesiert trotzdem was ich an der Adresierung in meinem Beispiel falsch mache. Es muss doch möglich sein eine Adresse zu berechnen und den Wert in eine Variable zu speichern
 
Code:
FUNCTION FC34 : VOID

VAR_INPUT
  Wochentag : INT; // 1=So, 2=Mo, ...
END_VAR

VAR_OUTPUT
  // Zeit Heizung Ein / Aus Aktuelle
  Z_HEIZ_EIN_AKT : TOD;
  Z_HEIZ_AUS_AKT : TOD;
  // Zeit Absenkung Ein / Aus Aktuell
  Z_ABSE_EIN_AKT : TOD;
  Z_ABSE_AUS_AKT : TOD;
END_VAR

VAR
  i : INT;
END_VAR 

BEGIN

  i := (Wochentag-1)*16;  // Hab mich vertippt nicht 128 sondern 16
  
  Z_HEIZ_EIN_AKT := DINT_TO_TOD(DWORD_TO_DINT(DB34.DBD[0+i]));
  Z_HEIZ_AUS_AKT := DINT_TO_TOD(DWORD_TO_DINT(DB34.DBD[4+i]));
  Z_ABSE_EIN_AKT := DINT_TO_TOD(DWORD_TO_DINT(DB34.DBD[8+i]));
  Z_ABSE_AUS_AKT := DINT_TO_TOD(DWORD_TO_DINT(DB34.DBD[12+i]));

END_FUNCTION
Gruss Daniel
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Code:
FUNCTION FC34 : VOID

VAR_INPUT
  Wochentag : INT; // 1=So, 2=Mo, ...
END_VAR

VAR_OUTPUT
  // Zeit Heizung Ein / Aus Aktuelle
  Z_HEIZ_EIN_AKT : TOD;
  Z_HEIZ_AUS_AKT : TOD;
  // Zeit Absenkung Ein / Aus Aktuell
  Z_ABSE_EIN_AKT : TOD;
  Z_ABSE_AUS_AKT : TOD;
END_VAR

VAR
  i : INT;
END_VAR 

BEGIN

  i := (Wochentag-1)[COLOR=Red]*128;[/COLOR]
  
  Z_HEIZ_EIN_AKT := DINT_TO_TOD(DWORD_TO_DINT(DB34.DBD[0+i]));
  Z_HEIZ_AUS_AKT := DINT_TO_TOD(DWORD_TO_DINT(DB34.DBD[4+i]));
  Z_ABSE_EIN_AKT := DINT_TO_TOD(DWORD_TO_DINT(DB34.DBD[8+i]));
  Z_ABSE_AUS_AKT := DINT_TO_TOD(DWORD_TO_DINT(DB34.DBD[12+i]));

END_FUNCTION
Gruss Daniel

Warum 128 ? der abstand ist doch 16 oder ?
 

Anhänge

  • DB34offen.JPG
    DB34offen.JPG
    199,3 KB · Aufrufe: 2
1. Frage.
Warum muss ich die Variablen DB34.DBD[X+i] umwandeln von DWORD in TOD ? Dieser wert müsste doch in TOD schon sein.

Habe doch einen DB in TOD angelegt

2. Frage

Wie funktionier das ? Rot ? Zusammensetzung ?

Code:
TYPE UDT1
  STRUCT
    HEIZUNG_EIN : TOD;
    HEIZUNG_AUS : TOD;
    ABSENK_EIN : TOD;
    ABSENK_AUS : TOD;
  END_STRUCT
END_TYPE


DATA_BLOCK DB1
  STRUCT
    SCHALTUHR : ARRAY[1..7] OF UDT1;  
  END_STRUCT
BEGIN

END_DATA_BLOCK


FUNCTION FC34 : VOID

VAR_INPUT
  Wochentag : INT;
END_VAR

VAR_IN_OUT
  SCHALTUHR : ARRAY[1..7] OF UDT1;  
END_VAR
  
VAR_OUTPUT
  // Zeit Heizung Ein / Aus Aktuelle
  Z_HEIZ_EIN_AKT : TOD;
  Z_HEIZ_AUS_AKT : TOD;
  // Zeit Absenkung Ein / Aus Aktuell
  Z_ABSE_EIN_AKT : TOD;
  Z_ABSE_AUS_AKT : TOD; 
END_VAR
  
BEGIN

  Z_HEIZ_EIN_AKT := [COLOR=Red]SCHALTUHR[Wochentag].HEIZUNG_EIN;[/COLOR]
  Z_HEIZ_AUS_AKT := [COLOR=Red]SCHALTUHR[Wochentag].HEIZUNG_AUS;[/COLOR]
  Z_ABSE_EIN_AKT := [COLOR=Red]SCHALTUHR[Wochentag].ABSENK_EIN;[/COLOR]
  Z_ABSE_AUS_AKT := [COLOR=Red]SCHALTUHR[Wochentag].ABSENK_AUS;
[/COLOR]
END_FUNCTION
 
Zurück
Oben