Step 7 Zeitplanregelung

Wer liest denn den Tag zum Titel? :D
Ich hab manchmal das Gefühl, dass einige Personen nichtmal die Beiträge lesen :D
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Die Arraygroesse DB und SCL Programm müssen dann zusammenpassen.Oder man übergibt die Arraygroesse im DB noch dem SCL baustein.
Das musst du natürlich entsprechend übergeben/abfangen.
Unsere Bausteine sind einfach hartcodiert auf eine gewisse Menge an Datensätzen programmiert & fertig.
Ob man in Classic die Größe des Arrays ermitteln kann? Geht bestimmt irgendwie....spätestens über die DB-Größe

Könnt ihr in eurem Fall dann auch automatisch die Schrittweite/Zeit verändern wenn die Sollwertsprünge unterschiedlich sind?
Es ist so umgesetzt, dass jeder Abschnitt nur aus einem Sollwert, einer Änderungsrate und einer Zeit besteht.
Das deckt Rampenfunktionen soweit ab.
Der "Timer" funktioniert darüber, dass der Code in einem Cyclic Interupt aufgerufen wird & einfach die Aufrufzyklen mitgezählt werden.
Reine Haltephasen werden nicht extra behandelt. Da ist der Sollwert einfach = dem Sollwert-Datensatz davor.

Hat er tatsächlich angegeben :D
Hmm....wer leden kann ist im Vorteil, oder so 💩💩
¯\_(ツ)_/¯
 
Oder man gibt die Rampenzeit einfach auch vor.Müsste eigentlich ausreichen.
Die muss dann halt richtig bemessen sein und ergibt dann eine bestimmte berechnete Schrittweite.
 
Ich hatte das ja mit SCL versucht.Kriege aber die Daten aus einem globalen Datenbaustein nicht in SCL rein.
Will dort quasi ein array aus einer Struktur einlesen und dann mit Schleifen bearbeiten.
In SCL will ich quasi direkt auf den Datenbaustein zugreifen.
Nachdem ich über eine Stunde rumprobiert habe, habe ich abgebrochen.Vielleich kann mir jemand mal so eine Deklaration zeigen.

im DB habe ich ein Array[1..5] vom mit den 3 Variablen (Sollwert,Rampenzeit,Haltezeit)

Jetzt habe ich eine menge Programmcode erzeugt für 5 Datensätze.Alles händisch in FUP.Dort addiere ich Haltezeit und Rampenzeit zusammen.
Alles in Sekunden.Ein Rampengerator zählt mit vorgebbarer Schrittweite und Schrittzeit die Gesamtzeit ab, die ich zusammenaddiert habe.Zwischen den einzelnen Bereichen,schiebe ich dann in dem Fenster den jeweiligen Sollwert raus.

Um die Rampe beim Sollwertsprung variabel zu gestalten, habe ich einen zweiten Rampengenerator genommen der dem Neuwert immer hinter rennt.Der Spass hat mich jetzt ein ganzer Tag und 3 Bausteine gekostet.Was mir allerdings nicht gefällt ist der viele Programmcode den ich in dem Berechnungsbaustein für die absoluten Zeiten benötige wenn ich die Anzahl der Datensätze erhöhe.
Das würde ich gern in SCL machen.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
...im DB habe ich ein Array[1..5] vom mit den 3 Variablen (Sollwert,Rampenzeit,Haltezeit)...
Ein "ARRAY of STRUCT"? Verwende für die Struktur einen eigenen Datentyp (UDT), das macht es etwas übersichtlicher. Diesen UDT kannst du dann als IN_OUT Parameter in deinem FB verwenden. Darüber kannst du im FB auf die Daten in dem globalen DB zugreifen. Wenn ich mich recht entsinne, muss der Index genau übereinstimmen. Also [1..5] muss dann im DB wie auch in der Deklaration des Bausteins übereinstimmen.

...Vielleich kann mir jemand mal so eine Deklaration zeigen...
Ich versuche es mal.

UDT:
Code:
TYPE "SP"
VERSION : 0.1
  STRUCT
   SOLLWERT : REAL ;    //Sollwert neu
   RAMPENZEIT : REAL ;    //Rampenzeit zum Erreichen des neuen Sollwertes [s]
   HALTEZEIT : REAL ;    //Haltezeit nach Ablauf der Rampenzeit [s]
  END_STRUCT ;
END_TYPE

DB:
Code:
DATA_BLOCK "DB_ZEITPLAN"
TITLE =
VERSION : 0.1
  STRUCT
   SP : ARRAY  [1 .. 5 ] OF "SP";
  END_STRUCT ;

Deklaration und Zugriff in SCL
Code:
FUNCTION_BLOCK FB_ZEITPLAN

VAR_IN_OUT
  ZEITPLAN                  : ARRAY[1..5] OF SP;            // Feld mit Sollwerten, Rampenzeiten, etc.
END_VAR

VAR
   SP_AKTUELL : REAL;                                       // Sollwert, aktueller Ausgangspunkt
   N : REAL;                                       // Index
END_VAR

  SP_AKTUELL := ZEITPLAN[N].SOLLWERT;

END_FUNCTION_BLOCK
 
Zuletzt bearbeitet:
Das heisst ich muss den als In_Out Parameter von aussen dranhängen?
Direkt im FB kann ich ihn nicht ansprechen?
Wenn ich ihn an den FB an die Schnittstelle dranhänge wie schreibe ich das dann hin.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Doch, du kannst natürlich auch im FB direkt auf den lokalen Datenbaustein zugreifen. Man muss auch nicht unbedingt einen UDT verwenden. Was ich gezeigt habe, ist eine Möglichkeit von vielen, die ich jedoch bevorzugen würde. Durch die Übergabe des Arrays über Bausteinparameter bist du dem Prädikat "bibliotheksfähig" oder zumindest "wiederverwendbar" einen Schritt näher.

Der Aktualparameter würde dann so aussehen:
Code:
      CALL "FB_ZEITPLAN" , DB    55 (
           ZEITPLAN                 := "DB_ZEITPLAN".SP);

Weitere Parameter, wie ein START-Eingang und die Ausgabe des resultierenden Sollwertes wären auch sinnvoll. Je nachdem, wie du vorgehen möchtest.
 
Nein, das wäre dann so in Ordnung, wobei ich nur lesend draufzugreife.Der aktuelle Sollwert wird ja im Baustein ausgewählt.
Das werde ich so dann probieren.Mir geht es hauptächlich um die Möglichkeiten der Schleifen.
Dort kann ich einfacher addieren.Der Baustein berechnet nur Werte.
Ich lese ja die aktuelle Rampengenrator zeit ein.
Die Rampengeratoren haben Freigaben und kriegen intern Sollwert 0 zugewiesen ohne Freigabe.Ich kann auch die Zählung anhalten.
Die anderen Parameter die ich mitübergebe tauchen ja dann auch mit auf, an der Schnittstelle.
 
Wo ich noch grüble, wo der Vorteil eines UDT gegenüber einem array aus Strukturmitgliedern ist?
Wenn das überhaupt geht.In der Datensicht im DB hat er es mir gezeigt.Dort lies er mich ein array mit 3 Variablen erstellen.
Unter der array Deklaration habe ich direkt die 3 Variablen eingefügt.
Zudem erzeuge ich ja auch wieder einen UDT-Baustein.Ich finde das irgendwie doppelt gemobbelt.
 
Wo ich noch grüble, wo der Vorteil eines UDT gegenüber einem array aus Strukturmitgliedern ist?

Bei späteren Änderungen daran musst du nur an einer Stelle ändern und nicht an mehreren. Jetzt musst du ja mindestens das Ding für die Daten außerhalb des Bausteins anlegen und dann nochmals identisch in der Bausteinschnittstelle.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Das ist was ich nochmals nachfragen wollte.Prinzipiell will ich bei SCL jetzt so vorgehen, dass ich nur Funktionen oder FB's schreiben will,
die ich allgemein verwenden kann.Ich bin keine grosser Anhänger von SCL.Ich weiss jetzt werden einige meckern.Aber dort wo man es gebrauchen kann will ich es einsetzen.
Kann ja jeder auch anderst sehen.
Mein Gedanke ist ein globaler DB mit einer Arraystruktur.Den globalen DB übergeben und intern dann zum Bsp. die Gesamtsumme aus einer der
Strukturvariablen ermitteln.Sowas könnte ich gebrauchen.Ein Anwendungsfall wäre jetzt die Gesamtzeit berechnen, wo ich dann nicht mühsam mit FUP die Einzelwerte zusammenaddieren muss.Das wäre mit Schleifen einfacher.Aus alten zeiten habe ich noch Funktionen wo ich eine datenbausteinadresse angeben kann und dann Start und Stop Adresse.Der Baustein berechnet dann MIN,Max;Durchnitt,Gesamtwert.
Dort muss ich dann aber(so sind die Bausteine jetzt gemacht) pro Datentyp einen eigenen FC aufrufen.Weiis jemand wie es geht?ich habe das noch nicht hinbekommen.irgendie muss man ja die einzelen Strukturvariablen an der Schnittstelle übergeben.Ich will auch nur lesend darauf zugreifen.
EIN FC reicht.Man hat dann sehr viele Freiheiten wenn man mit Array aus Strukturen arbeiten kann.Darum diese Standardfunktionen.
Kann mir jemand so was mal posten.Also das Array quasi als IN-variable.
 
Moin,

@sps_klassik , du hattest mir zwar ne PN bez. wie meien Bausteine arbeiten geschickt.
Da die Antwort aber etwas länger geworden ist + für die Diskussion relevant ist:

Ich hab eben mal in den Baustein der 300er Sollwertrampen rein geschaut.
Das Teil ist tatsächlich komplett fix auf 5 Datensätze programmiert, nicht flexibel wie ich es eigentlich im Kopf hatte.
Kommt allerdings ursprünglich noch aus ner S5 & ist für die Anlagen absolut ausreichend.

-------------------------------------------------------
Grober Ablauf meines Rampen-Bausteins:

Teilfunktion: Index
Hier wird lediglich entsprechend der Zeitvorgabe des Sollwert-Datensatzes gewartet, dann ein Index Hochgezählt, der "Timer" mit dem nächsten Sollwert geladen & wieder von vorn.
Der "Timer" ist im Prinzip nur ein INT, der entsprechend einem Triggerpuls hochgezählt wird (siehe Rampe).
Das wäre wohl deine "Schleife", die sich Datensatz für Datensatz durch dein Array arbeitet.
Technisch gesehen ist das aber eher ein Zustandsautomat.

Teilfunktion: Datenzugriff
Die Datenstruktur der Sollwert-Datensätze wird per "Any" übergeben.
Der eigentliche Zugriff auf die Daten läuft über einen Pointer, der entsprechend dem Datensatz Index und dem Any zusammengebaut und dann in eine interne Datensatz-Variable geladen wird.
Wenn die Datensätze direkt in einem Array liegen, kannst du den Index auch direkt als Zugriffsindex verwenden (siehe #26 von @Onkel Dagobert ).
Der Pointer ist hier lediglich notwendig, da die Sollwert-Datensätze in einer Struktur von INT und nicht in einem Array liegen.
Ob S7-Classic mit Array[*] arbeiten kann, müsstest du klären.
Im Zweifelsfall würde die Übergabe per Any & dann Zugriff per Pointer auch mit einem Array funktionieren.

Teilfunktion: Rampe
Hier wird der Sollwert (in meinem Fall die Temperatur) in einem festen Takt inkrementiert.
Getriggert wird das in diesem Programm über den Aufruf des Bausteins in einem 1s-Weckalarm-OB.
Aufruf in OB1 und Triggern über die Flanke eines Taktmerkerbits würde aber prinzipiell auch gehen.
Wenn beispielsweise 90°C/h Steigung im aktuellen Sollwert-Datensatz vorgegeben wurde, wird der Rampen-Sollwert alle 1s um 1,5°C inkrementiert, solange bis Rampen-Sollwert >= Datensatz-Sollwert ist.
Wichtig ist hier nur eine zykluszeitunabhängige Triggerquelle zu verwenden.
Einen TON oder S_EVERZ im Code zu verwenden kann bei schwankender Zykluszeit zum "Driften" der Rampen-Kennlinie führen.
-------------------------------------------------------

Soweit ich das verstanden habe funktioniert dieses Konzept ähnlich wie dein Entwurf.
Müsstest also lediglich noch ein paar Details ausarbeiten.
Unseren Baustein habe ich mal zur Überarbeitung vorgeschlagen., das Teil ist ein AWL-Frankenstein of Doom 💩
Werde mich also demnächst ebenfalls mal mit dem Thema außeinander setzen dürfen.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Ja das ist bei mir jetzt noch so gelöst das ich einfach eine theoretische Rampenzeit angegeben habe.
Die muss ich auch nochmit dem tatsächlichen Istwert verriegeln, das ich auch das erreicht habe.
Das geht aber gut vom programmcode her.Ich habe mich quasi jetzt nur mal anden theoretischen Zeiten orintiert, was natürlich nicht stimmt.
Das ist schon recht aufwendig.In AWL muss das wirklich grausam sein.Die Rampenzeit könnte ich mit solchen SCL Funktionen auch recht einfach berechnen.Das habe ich jetzt fix, egal welcher Sollwertsprung ich habe.Ich habe das Ganze jetzt quasi erst mal so gemacht das man theoretische Werte vorgibt.

IM SCL heisst das array jetzt:(unter Var_IN)

Datensatz:Array[1..5] of

Struct

Sollwert;
Haltezeit;
Rampenzeit;

End_Struct;

Das gleiche liegt jetzt in einem globalen DB, was ich übergeben will
 
Ich habe es jetzt geschafft den globalen DB im FC zu integrieren.
Ich kann auch auf die Variablen zugreifen obwohl die referenzierung doch recht aufwenig ist.
Er übersetzt den programmcode.PLC Sim läuft.
Das Ergebnis ist ein Laufzeitfehler wenn ich im SCL die Brille anmache und der Wert wird nicht berechnet.Ich breche da ab.Das ist mir zu kompliziert.Der Fehler ist nicht testbar keine DebugInfo.Kraatz?
 
Zurück
Oben