Step 7 Daten in DB nach einander speichern und FirstInLastOut wieder ablesen

kruz_007

Level-1
Beiträge
31
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo Leute,

Folgende Herausforderung habe ich, und zwar ich soll Daten einlesen (Date _and _Time, String, Strom, Spannung ) und in einem DB speichern, diese Daten werden über OPC Router abgeholt und in einem SQL Datenbank gespeichert. Wenn die Daten aufgrund ein Netzwerkproblem vom OPC Router nicht von dem DB abgeholt werden können, müssen diese unter einander oder einfach weiter gespeichert werden, und sobald die Kommunikation wieder steht werden die Daten sehr wichtig (FirstInLastOut) abgeholt werden. Ich habe mit SFC20 probiert und Daten immer wenn neue Daten vorhanden sind ein Bereich nach unten geschoben, läuft wunderbar aber mit dem FirstInLastOut ging leider nicht beim Daten-abhollen da ich wieder Daten nach oben verschiebe.

bzp:

0.0 zeit1 DATE_AND_TIME
8.0 ID1 String [10]
20.0 Spannung1 Dint
24.0 Strom1 Dint

28.0 zeit2 DATE_AND_TIME
36.0 ID2 String [10]
48.0 Spannung2 Dint
52.0 Strom2 Dint


Ich glaube mit indirekte Adressierung Pointer bestimmt Eleganter lösung gibt. Habe leider keine Erfahrung damit.

Danke im Voraus.
 
Bist Du Dir sicher, daß Du das FILO-Prinzip ("FirstInLastOut") verwenden mußt - also die Daten in umgekehrter Reihenfolge aus dem Puffer zurückholen mußt?
(Das korrekte Fachwort heißt übrigens LIFO (Last-In-First-Out) - hilfreich beim googlen und bei der Suche nach fertigen Lösungen hier im Forum ...)

Normalerweise wird ein LIFO nicht umgespeichert. Es werden nur Datensätze oben auf den Stapelspeicher gepackt (Push) und von oben wieder heruntergenommen (Pop) und sich gemerkt, wie hoch der Puffer gefüllt ist. Warum speicherst Du um?

Falls Du jedoch die Daten in der selben Reihenfolge herausnehmen willst wie sie in den Puffer geschrieben wurden - Du also einen FIFO (First-In-First-Out) meinst - den kann man als Ringpuffer realisieren und muß dann ebenfalls nicht umspeichern.

Harald
 
Egal ob LIFO oder FIFO - den wirst Du in FUP oder KOP nicht realisieren können, weil in FUP/KOP keine indirekte Adressierung möglich ist (man kann höchstens mit riesigem Aufwand ANY-Pointer für SFC20 basteln).

Für die Implementation eines LIFO/FIFO mußt Du AWL oder besser SCL benutzen.

Harald
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo,
Die Daten müssen im umgekehrter Reihenfolge aus dem Puffer zurückgeholt werden. deshalb ist die Lösung mit SFC 20 nicht viel hilfreich beim zurückholen der Daten.

Danke im Voraus.
 
mit AWL kann ich mir vorstellen das zu realisieren aber mit SCL habe leider keine Erfahrung.
Gibt s vorschläge mit AWL ?
 
Zuletzt bearbeitet:
Also rein von der Theorie her musst du den DB einfach nur von Oben nach Unten vollschreiben und merkst dir dabei wo du bist.
Wenn die Kommunikation wieder hergestellt ist fängst du von dem Punkt an wieder auszugeben wo zu letzt gespeichert hast und zählst rückwärts.

Hab leider keine Zeit jetzt einen Vorschlag zusammen zu knöppeln. Kann ich aber am Wochenende mal machen.
 
Hallo Martin,

hast du Volkommen recht, das was ich auch jetzt versuche zu machen. aber da die Daten unterschiedliche Daten Typen haben macht die Sache Schwieriger.
 
Du musst ja nur wissen wie lang ein Datensatz ist. Der Offset für die jeweiligen Teilvariablen bleibt ja gleich (Siehe dein Beispiel oben) und somit musst du nur die Startadresse variieren.

[Datensatz 1, Startadresse 0]
0.0 zeit1 DATE_AND_TIME
8.0 ID1 String [10]
20.0 Spannung1 Dint
24.0 Strom1 Dint
[Datensatz 2, Startadresse 28]
0.0 zeit2 DATE_AND_TIME
8.0 ID2 String [10]
20.0 Spannung2 Dint
24.0 Strom2 Dint
[Datensatz 3, Startadresse 56]
0.0 zeit2 DATE_AND_TIME
8.0 ID2 String [10]
20.0 Spannung2 Dint
24.0 Strom2 Dint

Und immer so weiter. Leg dir am einfachsten für einen Datensatz einen UDT an. Und falls du verschiedene Datensätze hast dann je Datensatz-Typ einen DB um alles sortiert zu haben.

Noch als Tipp hinterher:
Ich würde die Zähler nicht in Klar-Adresse laufen lassen (sprich 0, 28, 56, 84, ...) sondern quasi als Datensatz-Zähler und dann den Faktor (Datensatzlänge) an zweiter Stelle dazurechnen, einfach für die Übersicht- und Verständlichkeit.
Grade Programme mit Zeigern neigen dazu später schwer nachvollziehbar zu sein ;)
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Danke Martin für dein tipp!

ich habe auch in diese Richtung auch mal gedanken gemacht, und zwar ich erzeuge einen extra DB wo ich die Daten kopiere die aktuel abgeholt werden sollen. Die Datensätze werden weiterhin mit SFC 20 kopiert, an SFC 20 hänge ich eine Zähler. diese multipliziere ich mit 28 und so weiss ich wie gross meine Datensatz ist.
Das Problem:
ich weiss nicht wie ich eine Dynamische Pointer erzeugen kann, den ich an SFC 20 hängen kann ?

habe mir das so gedacht, ist das überhaupt machbar, und wenn ja wie ?

U(
U M 15.5
FP M 50.6
SPBNB _005
L MD 100
L L#1
-D
T MD 100
UN OV
SAVE
CLR
_005: U BIE
)
SPBNB _006
L MD 100
SLD 3
LAR1
AUF DB 17

CALL "BLKMOV"
SRCBLK := DBX [AR1,P#0.0]
RET_VAL:=#retval_i_3
DSTBLK :=P#DB15.DBX0.0 BYTE 30
_006: NOP 0




Programmabschnit2.jpg

Danke im Voraus !
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo Volker,

habe ich das richtig verstanden ?


L B#16#10
T LB 0
L B#16#02
T LB 1
L 30
T LW 2
L 15
T LW 4
L MD 100 ////// hier meine Zähler
SLD 3
T LD 6
L B#16#84
T LB

LAR1 P##myZeiger ///Sprich P#DB15.dbx (MD100).0 Byte 30

CALL "BLKMOV"
SRCBLK := #myZeiger
RET_VAL:=#retval_i_3
DSTBLK :=P#DB15.DBX0.0 BYTE 30
_006: NOP 0





Danke im Voraus !
 
Zuletzt bearbeitet:
Zählt Dein Zähler direkt 30, 60, 90 ...??? oder vielleicht 1, 2, 3 ...?
Der vom Zähler adressierte Datensatz of myStruct beginnt bei DB15.DBB(Zähler * Länge_myStruct + Anfangsadresse des Arrays im DB15)

Wenn Du ein ARRAY OF myStruct hast und myStruct 30 Byte größ ist:
Code:
//*** ANY für BLKMOV.SRCBLK erstellen:
      LAR1  P##aSRCBLK                  // Adresse der ANY-Variable aSRCBLK in TEMP

      L     W#16#1002                   // Kennung S7 (16#10) + Datentyp BYTE (16#02)
      T     W [AR1,P#0.0]               // ANY: Kennung S7 + Datentyp BYTE

      L     15                          // DB15
      T     W [AR1,P#4.0]               // ANY: DB-Nummer

      L     30                          // Sizeof(myStruct) = 30 Byte
      T     W [AR1,P#2.0]               // ANY: Wiederholfaktor

      L     MD   100                    // der Zähler 1, 2, 3 ...
      *D                                // --> Zähler*Size
      SLD   3                           // --> P#(Zähler*Size).0
      L     P#DBX 0.0                   // Bereichskennung "DB" + ggf. Anfangsadresse des Array in DB15 
      +D    
      T     D [AR1,P#6.0]               // ANY: Speicherbereich + Adresse

//*** Eintrag von ARRAY[Zähler] zum Anfang des DB15 (ARRAY[0] ?) kopieren:
      CALL  "BLKMOV"
       SRCBLK :=#aSRCBLK
       RET_VAL:=#iTEMP_INT
       DSTBLK :=P#DB15.DBX 0.0 BYTE 30

Harald
 
Zurück
Oben