Zuviel Werbung? - > Hier kostenlos beim SPS-Forum registrieren

Ergebnis 1 bis 6 von 6

Thema: Eindimensionales Array beschreiben

  1. #1
    Registriert seit
    04.09.2009
    Beiträge
    8
    Danke
    7
    Erhielt 0 Danke für 0 Beiträge

    Standard


    Zuviel Werbung?
    -> Hier kostenlos registrieren
    Hallo,

    Ich habe ein ARRAY[1..2880] vom Typ INT angelegt und möchte dieses Array schrittweise beschreiben.
    Mit einem Minutenimpuls soll ein Messwert hier reingeschrieben werden. Wie bei einem FIFO soll dann der älteste einfach hinten rausfallen.

    Wie realisiere ich es am einfachsten? Ich kann das natürlich händisch mit MOVE machen, ist aber für 2880 Werte sicher keine wirkliche Lösung.

    Vielen Dank im Vorraus.
    Zitieren Zitieren Eindimensionales Array beschreiben  

  2. #2
    Registriert seit
    08.02.2007
    Ort
    A-2320
    Beiträge
    2.255
    Danke
    244
    Erhielt 332 Danke für 303 Beiträge

    Standard

    Mit einem Pointer der jede Minute hinaufzählt.

    Schau mal in die Suchfunktion, da findet sich jede Menge.....

  3. Folgender Benutzer sagt Danke zu borromeus für den nützlichen Beitrag:

    SPS_LB (05.09.2009)

  4. #3
    Registriert seit
    30.03.2005
    Beiträge
    2.096
    Danke
    0
    Erhielt 673 Danke für 541 Beiträge

    Standard

    Zitat Zitat von SPS_LB Beitrag anzeigen
    Ich habe ein ARRAY[1..2880] vom Typ INT angelegt und möchte dieses Array schrittweise beschreiben.
    Mit einem Minutenimpuls soll ein Messwert hier reingeschrieben werden. Wie bei einem FIFO soll dann der älteste einfach hinten rausfallen.
    Hier ist einmal ein kurzes Programmbeispiel für einen FIFO-Speicher:

    Code:
    FUNCTION FC 100 : VOID
    TITLE =FIFO Werte
    AUTHOR : KAI
    FAMILY : SPSFORUM
    NAME : FIFO
    VERSION : 1.0
     
    VAR_INPUT
      DB_Werte : BLOCK_DB ; 
      Anzahl_Werte : INT ; 
      Wert : INT ; 
    END_VAR
    VAR_TEMP
      DB_Register : WORD ; 
      AR1_Register : DWORD ; 
      Zwischenwert : INT ; 
      Schleife : INT ; 
    END_VAR
    BEGIN
    NETWORK
    TITLE =Register sichern
     
          L     DBNO; // DB-Register
          T     #DB_Register; 
     
          TAR1  ; // AR1-Register
          T     #AR1_Register; 
     
    NETWORK
    TITLE =FIFO Werte
     
          AUF   #DB_Werte; // DB-Werte
     
          L     #Wert; // Wert
          T     #Zwischenwert; // Zwischenwert
     
          L     P#0.0; 
          LAR1  ; 
     
          L     #Anzahl_Werte; // Anzahl Werte
    M01:  T     #Schleife; 
     
          L     DBW [AR1,P#0.0]; // Wert
          L     #Zwischenwert; // Zwischenwert
          T     DBW [AR1,P#0.0]; // Zwischenwert -> Wert   
          TAK   ; 
          T     #Zwischenwert; // Wert -> Zwischenwert
     
          L     P#2.0; 
          +AR1  ; 
     
          L     #Schleife; 
          LOOP  M01; 
     
    NETWORK
    TITLE =Register wiederherstellen
     
          AUF   DB [#DB_Register]; // DB-Register
     
          L     #AR1_Register; // AR1-Register
          LAR1  ; 
     
    END_FUNCTION
    Gruß Kai
    Angehängte Dateien Angehängte Dateien

  5. Folgender Benutzer sagt Danke zu Kai für den nützlichen Beitrag:

    SPS_LB (05.09.2009)

  6. #4
    Registriert seit
    30.03.2005
    Beiträge
    2.096
    Danke
    0
    Erhielt 673 Danke für 541 Beiträge

    Standard

    Und noch zwei Bilder aus der Simulation mit PLCSIM.

    Gruß Kai
    Angehängte Grafiken Angehängte Grafiken

  7. #5
    SPS_LB ist offline Neuer Benutzer
    Themenstarter
    Registriert seit
    04.09.2009
    Beiträge
    8
    Danke
    7
    Erhielt 0 Danke für 0 Beiträge

    Standard

    Hallo Kai,

    habe den Baustein ausprobiert, funktioniert super, vielen Dank,

    Grüße

  8. #6
    Registriert seit
    22.06.2009
    Ort
    Sassnitz
    Beiträge
    11.314
    Danke
    932
    Erhielt 3.329 Danke für 2.688 Beiträge

    Standard


    Zuviel Werbung?
    -> Hier kostenlos registrieren
    Hallo SPS_LB,

    ich denke, für Deine Aufgabe mit 2880 INT-Werten ist ein FIFO nicht gut geeignet.
    5758 Byte komplett umspeichern, nur um 2 Byte der Liste hinzuzufügen ... tststs

    Hast Du mal im CPU-Baugruppenzustand auf die Zykluszeiten geschaut?

    Wenn es schon unbedingt ein FIFO sein muß, dann sollte das Einspeichern in den FIFO wenigstens effizient
    programmiert sein.

    Das Beispielprogramm von Kai benötigt dafür auf einer aktuellen CPU 315 immerhin 19,3 ms.
    Wenn man die unnötigen Berechnungen und das Zwischenspeichern aus der Schleife verbannt, dann läßt
    sich die Bearbeitungszeit auf 16,2 ms drücken.
    Wenn man immer gleich 2 INT-Werte auf einmal umspeichert, dann braucht man nur noch 8,7 ms.
    Und mit Einsatz der SFC20 "BLKMOV" sinkt das Ganze auf 2,7 ms.
    (weil SFC20 immer aufsteigend kopiert, ist dann der älteste Wert im FIFO vorn und der neueste hinten)

    Ringpuffer
    Deine Aufgabe beschreibt eigentlich den klassischen Fall, eine Variable (z.B. Meßwert) über 48 Stunden
    mit minütlicher Abtastung in ein Archiv für eine Trendkurve aufzuzeichnen.

    Wenn in dem Archiv nicht zwingend der älteste Wert ganz vorn in Wert[1] stehen muß (wie z.B. bei
    Trendkurven für WinCC flexible), dann ist ein Ringpuffer mit einem Zeiger auf die aktuelle Einfügeposition
    am besten geeignet. Da wird einfach nur der neue Wert an der Zeigerposition eingefügt und der Einfügezeiger
    weitergestellt. Der älteste Wert im Ringpuffer wird überschrieben. Das dauert nur 0,025 ms.

    minütliche Aufzeichnung von Datensätzen in einen Ringpuffer
    Wenn ich so eine Aufzeichnung mache, dann berechne ich die Einfügeposition aus der Uhrzeit:
    1.Tag um 0:00 Uhr in Datensatz[0], um 0:01 Uhr in Datensatz[1] ... 23:59 Uhr in Datensatz[1439]
    2.Tag um 0:00 Uhr in Datensatz[1440] ... 23:59 Uhr in Datensatz[2879]

    Sobald 48 Stunden aufgezeichnet wurden, enthält der Archiv-DB jederzeit die Werte der letzten 48 Stunden.

    Der Archiv-DB enthält außer den Datensätzen noch den Index und den Zeitstempel der letzten Aufzeichnung.
    Mit diesen Angaben kann nach dem Auslesen des Archiv-DB die Trendkurve mit Zeitangaben erstellt werden.

    Zum Auslesen benutze ich Excel/VBA und LibnoDave. Das Excel-Makro bringt die Datensätze in die richtige
    Reihenfolge (anhand Index der letzten Aufzeichnung) und schreibt die Datensätze in eine CSV-Datei.
    Mit Excel kann man auch gleich die Trendkurve in einem Diagramm darstellen.

    Im Anhang die ausführlich kommentierte Quelle eines in der Praxis bewährtes Aufzeichnungsprogramms,
    angepaßt für nur 1 INT-Wert. Hier der Programmcode FC105 (Kommentare und DB105 gekürzt):
    Code:
    FUNCTION FC105 : VOID
    TITLE =jede Minute einen Datensatz in einen Ringpuffer aufzeichnen
    AUTHOR : PN_DP
    
    VAR_TEMP
      act_Time : DATE_AND_TIME ;	
      Temp_Int : INT ;	
      DS_Nr : INT ;	
    END_VAR
    BEGIN
    NETWORK
    TITLE =Trigger
    // aktuelle Uhrzeit holen
          CALL "READ_CLK" (      //SFC1
               RET_VAL := #Temp_Int,
               CDT     := #act_Time);
    
    // Datensatz-Index aus Uhrzeit berechnen
          L     P##act_Time;     //Adresse #act_Time
          LAR1  ; 
          L     LB [AR1,P#3.0];  //aktuelle Stunde BCD
          BTI   ; 
          L     60; 
          *I    ; 
          L     LB [AR1,P#4.0];  //aktuelle Minute BCD
          BTI   ; 
          +I    ; 
          T     #DS_Nr;          //0:00..23:59 -> 0...1439
    
    // Trigger: neue Minute?
          L     "Archiv".DS_Nr;  //Index letzte Aufzeichnung
          L     1440;            //Anzahl Datensätze je Tag
          MOD   ;                //Index letzte Aufzeichnung heute 
          L     #DS_Nr;          //jetzt 0:00..23:59 -> 0...1439
          ==I   ;                //in dieser Minute schon aufgezeichnet?
          BEB   ;                //ja, nicht wieder aufzeichnen
    
    NETWORK
    TITLE =Datensatz-Adresse berechnen
    // Datensatz-Nr aus Uhrzeit: 0:00 Uhr = 0  bis  23:59 Uhr = 1439
          L     B#16#0; 
          L     #DS_Nr;          //0..1439
          <>I   ; 
          SPB   CKDS;            //springe, wenn <> 0:00
    // es ist 0:00 Uhr! -> Tag-Wechsel (und ggf. DB-Wechsel)
          UN    "Archiv".Tag2; 
          =     "Archiv".Tag2; 
    
    CKDS: L     1440;            //-> AKKU1:1440  AKKU2:DS_Nr
          >=D   ;                //darf nur 0..1439
          BEB   ;                //(kommt bei unsachgemäß beobachten vor)    
    
          TAK   ;                //-> AKKU1:DS_Nr AKKU2:1440 
          U     "Archiv".Tag2; 
          SPBN  TPTR; 
          +I    ;                // + 1440 (24*60)
    TPTR: T     "Archiv".DS_Nr;  //0..2879 neue Schreib-DS_Nr
    
    // DB-Pointer aus Datensatz-Nr berechnen (AKKU1:DS_Nr 0..2879)
          L     2;               //Länge eines Datensatzes
          *I    ;                //-> Startadresse des Datensatzes
          SLD   3;               //-> P#0.0..P#5758.0
          LAR1  ;                //-> Pointer DS[DS_Nr]
    
    NETWORK
    TITLE =Datensatz aufzeichnen
          L     MW   102;        //aufzuzeichnender Wert
          AUF   "Archiv"; 
          T     DBW [AR1,P#0.0]; //ins Archiv schreiben
    
    // Zeitstempel
          CALL "BLKMOV" (        //SFC20
               SRCBLK  := #act_Time,
               RET_VAL := #Temp_Int,
               DSTBLK  := "Archiv".DS_TimeStamp);
    END_FUNCTION
    
    //Der DB105 (gekürzt):
    DATA_BLOCK "Archiv"
      STRUCT 
       DS : ARRAY  [0 .. 2879 ] OF      //48-Stunden-Archiv, minütliche Datensätze
       STRUCT 	
        Wert1 : INT ;	
       END_STRUCT ;	
       DS_TimeStamp : DATE_AND_TIME ;   //Zeitstempel zuletzt geschriebener Datensatz
       DS_Nr : INT ;	            //Index zuletzt geschriebener Datensatz
       Tag2 : BOOL ;	            //0=1.Tag / 1=2.Tag
      END_STRUCT ;	
    END_DATA_BLOCK
    btw: Die CPU-Uhr sollte mit einer geeichten Uhr synchronisiert werden, z.B. mit einem NTP-Server.
    Die CPU-Uhr sollte immer auf Winterzeit stehen.

    Gruß
    PN/DP
    Angehängte Dateien Angehängte Dateien
    Zitieren Zitieren jede Minute einen Datensatz aufzeichnen  

Ähnliche Themen

  1. Array von FB Ausgang beschreiben
    Von michal im Forum Programmierstrategien
    Antworten: 6
    Letzter Beitrag: 03.08.2011, 08:58
  2. Array beschreiben
    Von focus81 im Forum Simatic
    Antworten: 2
    Letzter Beitrag: 16.08.2010, 14:25
  3. Array indirekt beschreiben
    Von Airpower im Forum Simatic
    Antworten: 5
    Letzter Beitrag: 22.06.2009, 08:34
  4. Array von Strings beschreiben
    Von Fluffi im Forum Simatic
    Antworten: 5
    Letzter Beitrag: 30.04.2009, 16:48
  5. Array im Script beschreiben
    Von Neuling74 im Forum HMI
    Antworten: 2
    Letzter Beitrag: 16.06.2007, 08:59

Stichworte

Lesezeichen

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •