TIA Datenbaustein laufend erweitern und Inhalt abfragen

SPS_Step

Level-2
Beiträge
88
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo Zusammen,

Ich habe dieses Problem:

Ich habe verschiedene Nummern und diesen Nummern wird jeweils ein Wert zugewiesen. Dies soll in einem DB geschehen, ich weiß allerdings nicht wie ich das realisieren soll. Der Ablauf sieht so aus:

1 Barcode Scanner erfasst Nummer 1234567
2 Überprüfung ob Nummer vorhanden
3a wenn NEIN dann Nummer anlegen und wert dazu speichern
3b wenn JA dann Wert auslesen

Gleichzeitig soll der Wert auch über ein HMI durch Eingabe der Nummer änderbar sein.

Habt ihr so etwas schon erstellt? Wie kann ich die Daten in den DB schreiben bzw. diesen immer „erweitern“ und auf die Nummer „abfragen“?

Dankeschön!
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo,

Ich möchte keinen fertigen Code, habe eine S7-1200 und nutze am liebsten SCL.

Das Problem in meinem Verständnis liegt darin, den DB zu erweitern.

Ich hatte gedacht, man könnte jeweils ein Struct erstellen, welches für den Namen die Nummer bekommt den Wert darin. Bei dem ersten Mal kein Problem, ich weiß nur nicht wie ich den 2. Datensatz in den nächsten Speicherbereich bekomme.

Und wie kann ich dir Schleife beibringen, den Speicherbereich auf eine direkte Nummer zu durchsuchen?
Der DB erweitert sich ja mit jeder neuen Nummer.
 
Zuletzt bearbeitet:
Du benötigst ein Array und einen SpeicherPlatz (eine Variable), in der Du Dir merkst, bis zu welchem Index das Array belegt ist.

Wird eine "neue Nummer" angeliefert, musst Du die belegten Plätze im Array damit vergleichen, bis Du die "neue Nummer" im Array findest oder bis Du weisst, dass keiner der belegten Plätze die gesuchte Nummer enthält.

Der DB wird nicht erweitert. Das Array muss lediglich mit genügend Reserve gross genug angelegt werden.
 
Zuletzt bearbeitet:
Wenn du sowas wie ne Liste aus der Hochsprache meinst, die du zur Laufzeit erweitern kannst, muss ich dich leider enttäuschen. Das wird in keiner der mir bekannten SPS'en unterstützt.
Alternativ könnte man sowas allerdings vielleicht mithilfe einer Datenbank realisieren.
Ansonsten bleibt dir nur die Lösung, die dir Heinileini genannt hat.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo,

Hier wäre ein Ansatz. Geht das in die richtige Richtung?

Code:
INPUT

Nummer_IN  :  Int
Aktueller_Wert_IN   : Int
Neue_Nummer_IN  :  Bool

OUTPUT

Wert_OUT  : Int

STATIC

Produktnummer  :  Array[0..10000] of Int
Wert  :   Array[0..10000] of Int
Laufvariable  :   Int
Laufwert  :  Int
Neue_Nummer  :  Bool

IF #Neue_Nummer_IN
THEN
    #Neue_Nummer := TRUE;
END_IF;


IF #Neue_Nummer
THEN
    FOR #Laufvariable := 1 TO #Laufwert BY +1 DO
        
        IF #Produktnummer[#Laufvariable] = #Nummer_IN
        THEN
            #Wert_OUT := #Wert[#Laufvariable];
            #Laufwert := #Laufvariable;
            #Neue_Nummer := FALSE;
        END_IF;
    END_FOR;
    
    IF #Laufvariable = #Laufwert
    THEN
        #Produktnummer[#Laufvariable] := #Nummer_IN;
        #Wert[#Laufvariable] := #Aktueller_Wert_IN;
        #Laufwert := #Laufvariable + 1;
        #Neue_Nummer := FALSE;
    END_IF;
END_IF;
 
Hier wäre ein Ansatz. Geht das in die richtige Richtung?

Hast du es denn mal getestet?

Code:
Produktnummer  :  Array[0..10000] of Int
Wert  :   Array[0..10000] of Int

Hier wäre ein Array of struct sinnvoller

Code:
IF #Neue_Nummer_IN
THEN
    #Neue_Nummer := TRUE;
END_IF;

Geht kürzer:

Code:
#Neue_Nummer := #Neue_Nummer_IN;

Über deine Schleife solltest du dir nochmal ein paar Gedanken machen.
Zum Beispiel, wie eine For-Schleife generell funktioniert, was für Fallstricke es gibt (Index außerhalb der Arraygrenzen, etc) und wie man diese umschifft. Warum fängst du eigentlich bei der Schleife mit 1 an und nicht bei 0?

Als kleine Anregung auf die schnelle...
Code:
for #i := 0 to 9999 do
  #tmpFoundProductNo := (Product[#i].No = #Nummer_IN);
if tmpFoundProductNo then
  exit;
end_if;
end_for;

If tmpFoundProductNo then
  #out := Product[#i].Value;
else
  for #i := 0 to 9999 do
    // naechsten freien Platz suchen und nummer eintragen, danach schleife verlassen
  end_for;
end_if;

Was soll eigentlich passieren, wenn dein Array mal komplett gefüllt ist und trotzdem neue Nummern dazu kommen? Wie soll damit umgegangen werden?
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
INT ist zu klein für 1234567
Zudem wird der Barcodeleser ja wahrscheinlich einen string oder array[0..n] of char liefern und keinen rein numerischen Wert.

Also brauchst Du am besten ein Array[0..n] of Struct. In der Struct ein Array[0..n] of char und ein int.

Theoretisch könnte man bei einer neuen Nummer einen neuen DB erstellen, der groß genug ist. Dann den Inhalt des alten DBs hineinkopieren und den neuen Datensatz hinzufügen. Danach den alten DB löschen. Allerdings geht das m.W. nur mit nicht optimierten DBs und auch nur mit einem (großen) Array[0..n] of byte.
Aber es wäre eine Möglichkeit.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Geht das wirklich, Mario? Bezüglich Anlegen eines neuen DB zur Laufzeit habe ich keine Bedenken, aber einen DB zur Laufzeit per Befehl löschen?
Ja, das geht. Das ging auch schon auf der S7-300/400 ( CREAT_DB / DEL_DB ).
Hier mal die Baustein-Hilfe der 300/400ér:
Beschreibung

Mit der SFC 22 "CREAT_DB" (create data block) erzeugen Sie im Anwenderprogramm einen Datenbaustein, der keine vorbesetzten Werte enthält. Er enthält stattdessen Zufallsdaten. Die SFC erzeugt einen Datenbaustein mit einer Nummer aus einem angegebenen Bereich sowie mit vorgegebener Größe. Aus dem angegebenen Bereich vergibt die SFC die kleinste mögliche Nummer an den DB. Einen DB mit bestimmter Nummer erzeugen Sie, indem Sie der Ober- und Untergrenze des vorzugebenden Bereichs die gleiche Nummer geben. Die Nummern der im Anwenderprogramm bereits enthaltenen DBs können Sie nicht mehr vergeben. Die Länge des DBs müssen Sie in einer geraden Zahl angeben.
Beschreibung

Mit der SFC 23 "DEL_DB" (delete data block) löschen Sie einen im Arbeitsspeicher und gegebenenfalls im Ladespeicher der CPU liegenden Datenbaustein. Der zu löschende DB darf weder in der aktuellen noch in einer niederprioren Ablaufebene aufgeschlagen sein. D. h., er darf weder in einem der beiden DB-Register noch im B-Stack eingetragen sein. Bei Aufruf der SFC 23 startet die CPU sonst den OB 121. Wenn der OB 121 nicht vorhanden ist, wechselt die CPU in STOP; bei S7-300 (Ausnahme: CPU 318) erfolgt das Löschen des DB ohne Aufruf des OB 121.

HinweisDas Löschen von Instanz-DBs mit der SFC 23 "DEL_DB" ist nicht sinnvoll und führt stets zu Programmfehlern. Vermeiden sie daher das Löschen von Instanz-DBs mit der SFC 23!
 
Sowas macht man doch eigentlich über Datenbanken, da kann man dann ganz entspannt eine Anfrage für gescannten Inhalt stellen und bekommt dann einfach nur seine Antwort.

Der DB wird immer größer und die Suche länger und dadurch auch die Zykluszeit..
 
Sowas macht man doch eigentlich über Datenbanken, ...
Na klar. Aber zumindest "winzig kleine" DatenBanken können durchaus in einer SPS realisiert werden.
Der DB wird immer größer und die Suche länger und dadurch auch die Zykluszeit..
Wenn die DatenSätze nach der Grösse des SuchBegriffs sortiert werden können, dann kann man recht schnell "binär" suchen und finden.
Wenn also viele Werte mit der Liste verglichen werden sollen und nur wenige nach und nach in der Liste hinzugefügt oder aus der Liste entfernt werden, dann kann das zeitliche Auslagern des Sortierens Vorteile bringen.
Am einfachsten für die Logik ist es natürlich, wenn man alles in 1 Zyklus erledigen kann. Bei grossen DatenMengen muss man die benötigten Zeiten selbstverständlich im Auge behalten und sich ggfs eine Aufteilung der Aufgabe( n ) auf mehrere Zyklen überlegen.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Was glaube ich bisher noch nicht erwähnt wurde.. das ganze natürlich als remanenten DB, vielleicht lohnt sich ja auch der Aufwand eine csv File zu schreiben und lesen.. dann hat man das ganze nicht auf der Steuerung liegen.. kann aber natürlich dementsprechend wieder jede*r bearbeiten von außen. Ausser man bekommt diese nur von der SPS aus schreibend und von außen aus nur lesend geregelt vom Zugriff her
 
... vielleicht lohnt sich ja auch der Aufwand eine csv File zu schreiben und lesen.. dann hat man das ganze nicht auf der Steuerung liegen..
Du meinst anscheinend nicht, dass Deine "Datenbank" zusätzlich in einer csv-Datei gespeichert werden soll, sondern ausschliesslich in der Datei.
Du könntest dann aber auf nichts direkt in der SPS Verfügbares zugreifen, sondern müsstest für jede Abfrage die Datei von Beginn an neu einlesen.
Dann bräuchtest Du Dir keine Gedanken über die ZyklusZeit zu machen, aber ganz viele Gedanken darüber, wieviele PLC-Zyklen eine Aktion beanspruchen würde.
 
Hab bisher nur mit csv Dateien im HMI gearbeitet (lesen, schreiben, suchen) und das ging eigentlich sehr gut. Wie man sieht gibts einige Möglichkeiten das zu lösen
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hab bisher nur mit csv Dateien im HMI gearbeitet (lesen, schreiben, suchen) und das ging eigentlich sehr gut. Wie man sieht gibts einige Möglichkeiten das zu lösen

Also verbaut ist außerdem ein TP900, kann ich über das ganze vielleicht über die Rezepturverwaltung lösen?

Kann man dort Befehle wie Datensatz suchen nutzen?
 
Zuletzt bearbeitet:
Zudem wird der Barcodeleser ja wahrscheinlich einen string oder array[0..n] of char liefern und keinen rein numerischen Wert.

Also brauchst Du am besten ein Array[0..n] of Struct. In der Struct ein Array[0..n] of char und ein int.

Theoretisch könnte man bei einer neuen Nummer einen neuen DB erstellen, der groß genug ist. Dann den Inhalt des alten DBs hineinkopieren und den neuen Datensatz hinzufügen. Danach den alten DB löschen. Allerdings geht das m.W. nur mit nicht optimierten DBs und auch nur mit einem (großen) Array[0..n] of byte.
Aber es wäre eine Möglichkeit.

Das heißt, ich könnte durch eine Schleife den Datenbaustein durchsuchen und wenn die Nummer vorhanden ist, den Wert nutzen. Falls nicht, kopiere ich den Inhalt des alten DB in einen neuen DB und ergänze die neue Nummer.

Wo liegt hierbei der Unterschied dazu, den Alten DB zu aktualisieren? Damit das Array nicht auf die Bsp. 10000 Plätze begrenzt ist?
 
Wieviele Nummern und Zusatzinformationen soll sich Deine SPS merken können? Hast Du schon mal überschlagen, wieviel Datenspeicherplatz Du dafür brauchen wirst? Hat Deine SPS auch so viel Speicher? Kann die bei Bedarf Daten auslagern und zurückladen? Der Vorteil bei SPS ist, daß man den nötigen Speicherplatz schon beim Anlegen der DB reserviert und schon beim Laden in die SPS sofort sieht, ob der verfügbare Platz reicht, und nicht erst nach vielen Tagen mitten während der Produktion.

Wenn der Platzbedarf geklärt ist und ausreicht, dann als nächstes drüber nachdenken, wieviel Zeit zum Finden und ggf. Hinzufügen eines Datensatzes zur Verfügung steht und wie lange der Vorgang in der SPS tatsächlich dauern wird. Danach richtet sich, ob die Daten sortiert abgelegt werden müssen, damit schnellere Finde-Routinen verwendet werden können.

Harald
 
Zurück
Oben