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

Seite 1 von 5 123 ... LetzteLetzte
Ergebnis 1 bis 10 von 45

Thema: Auswertung Array of Char

  1. #1
    Registriert seit
    11.12.2009
    Beiträge
    2.113
    Danke
    388
    Erhielt 390 Danke für 271 Beiträge

    Standard


    Zuviel Werbung?
    -> Hier kostenlos registrieren
    Hallo Leute,

    ich stehe vor folgender Aufgabe:

    Ein Teilnehmer wird mittels TCP/IP Kommunikation abgefragt.
    Ich habe alles am Laufen, es funktioniert alles zufriedenstellend, ABER:

    mein Bautein hat in SCL 1200 Zeilen, und auf einer IM151-8F PN/DP eine Zykluszeit von 21ms.

    Was wird dort gemacht, bzw. was ist die Bremse?

    Ganz einfach:

    Ich werte ein Array of Char aus, in dem 4000 Chars kommen.
    Die ersten 280 Char werden nicht angeguckt, da sie unwichtige Header-Infos enthalten.
    Die Daten die danach kommen, sehen etwa so aus:

    Code:
    Variable1=123456.123456,Variable2=4321.1,Variable3=123
    Wenn nun Variable 1 nicht 123456 ist, sonder nur 1.0 dann verschieben sich die Positionen von Variable 2-n natürlich in meinem Array.

    Wie ist mein vorgehen bisher:

    Ich weis wo meine Daten ungefähr ankommen.
    Dann füge ich eine FOR-Schleife ein, die an dieser Position +-20 Zeichen eine Bestimmte zeichenkette sucht, das ende der Variable sucht, die Variable in einen String kopiert und dann in ein passendes Datenformat konvertiert... etwa so:


    (Wichtige Info: Code ist grad aus dem Kopf runtergetippt, muss nicht 100% korrekt sein, es geht ums Prinzip)
    Code:
    // Suchen nach Variable 1
    FOR I:=280 TO 320 DO
    
    // Finden der Zeichenfolge
    IF CHARARRAY(i) = 'V' AND
    CHARARRAY(i+1) = 'A' AND
    CHARARRAY(i+2) = 'R' AND
    CHARARRAY(i+3) = '1' AND
    CHARARRAY(i+4) = '=' 
    
    THEN
    
    // Ich weis wo meine Variable anfängt (nach dem "=")
    TMP_FOUND:=i+5;
    
    END_IF;
    
    // Wenn der Anfang der Variablen gefunden wurde...
    IF_TMP_FOUND > 0 THEN
    
    // Die Variable bis zum Punkt auslesen und in einen String kopieren(vereinfacht, eigentlich suche ich an dieser Stelle von i ab 
    //nach dem Punkt oder Komma, je nachdem ob ich Nachkommastellen brauche oder nicht)
    
    TMP_EXIT:=FALSE;
    TMP_STRING:=' ';
    FOR J:=i TO i+6 DO
    
    TMP_STRING:=CONCAT(IN1:=TMP_STRING, IN2:=CHARARRAY(J);
    
    END_FOR;
    
    // Nach dem erstellen des String den String in DINT wandeln
    
    MY_DINT:= STRING_TO_DINT(TMP_STRING);
    
    TMP_EXIT:=TRUE;
    EXIT; // Spart nen Haufen Zykluszeit
    END_IF;
    
    IF TMP_EXIT:=TRUE THEN
    EXIT; // Nach verlassen der ersten FOR-Schleife auch die Verschachlte verlassen)
    END_IF;
    
    END_FOR;

    Dieser ganze Code ist

    1. Total aufgebläht und meiner Meinung nach recht "unschön" und schwer verständlich
    2. Frisst er abartig Zykluszeit, weil ich durch diverste Schleifen renne

    Diesen Code führe ich für etwa 20 Variablen durch, entsprechend erhöht sich die Zykluszeit.

    Jetzt wäre es für mich interessant zu wissen wie ihr sowas löst! Ich denke, dass ich nicht der Einzige sein kann der eine recht große Menge von CHARS sinnvoll auslesen muss. Ich denke bei einem IPC würde mich das nicht interessieren, da fällt mir die Zykluszeit vermutlich nicht mal auf, bei der kleinen Muckelkiste von IM-CPU ist es aber relevant (und bevor jemand es vorschlägt: NEIN, ich kann keine andere CPU verwenden!)

    Ich freue mich auf eure Ideen und Vorschläge! Ich habe von puzzlefreak schon einmal ein paar Ansätze bekommen, und habe die Zykluszeit von 58ms auf 21ms senken können, ich hoffe nun das noch mehr geht. (ich brauche hier keine 2ms Zykluszeit, aber je schneller der Code wird, desto mehr Abfragen könnte ich noch machen)

    Grüße

    Marcel
    Zitieren Zitieren Auswertung Array of Char  

  2. #2
    Registriert seit
    22.06.2009
    Ort
    Sassnitz
    Beiträge
    11.186
    Danke
    923
    Erhielt 3.291 Danke für 2.660 Beiträge

    Standard

    Auf die Schnelle... probiere mal diese Änderung:
    Code:
    // Suchen nach Variable 1
    FOR I:=280 TO 320 DO
    // Finden der Zeichenfolge
    IF CHARARRAY(i) = 'V' THEN
    * IF CHARARRAY(i+1) = 'A' THEN
    ** *IF*CHARARRAY(i+2) = 'R' THEN
    ** * *IF*CHARARRAY(i+3) = '1' THEN
    ** * * *IF CHARARRAY(i+4)*= '='*THEN
    ** * * * *// Ich weis wo meine Variable anfängt (nach dem "=")
    ** * * * *TMP_FOUND:=i+5;
    ** * * *END_IF;
    ** * *END_IF;
    ** *END_IF;
    **END_IF;
    END_IF;
    Weiters: Warum beginnt Deine j-Schleife mit i und nicht mit TMP_FOUND? Kommt das vom Tippen aus dem Gedächtnis?

    Harald's Galaxy Tab

    PS: Die Programmierer von Android müsste man alle erschlagen oder zwingen, mal selber einen einfachen Text wie diesen zu erstellen.....
    Und die eigenmächtigen Textmanipulationen des Beitragseditors sind auch idiotisch. Ignoriere die * die sind nicht von mir. Ich gebs auf.
    Geändert von PN/DP (09.06.2013 um 02:54 Uhr)
    Es ist immer wieder überraschend, wie etwas plötzlich funktioniert, sobald man alles richtig macht.

    FAQ: Linkliste SIMATIC-Kommunikation über Ethernet

  3. Folgender Benutzer sagt Danke zu PN/DP für den nützlichen Beitrag:

    Matze001 (09.06.2013)

  4. #3
    Registriert seit
    22.06.2009
    Ort
    Sassnitz
    Beiträge
    11.186
    Danke
    923
    Erhielt 3.291 Danke für 2.660 Beiträge

    Standard

    Wichtig: probiere Deinen Code auch mit Text aus, der garantiert NICHT enthält was Du suchst, damit alle Schleifen maximal durchlaufen werden, und schau dann mal auf die Zykluszeit.

    Harald
    Es ist immer wieder überraschend, wie etwas plötzlich funktioniert, sobald man alles richtig macht.

    FAQ: Linkliste SIMATIC-Kommunikation über Ethernet

  5. Folgender Benutzer sagt Danke zu PN/DP für den nützlichen Beitrag:

    Matze001 (09.06.2013)

  6. #4
    Registriert seit
    30.11.2008
    Ort
    Baesweiler
    Beiträge
    830
    Danke
    255
    Erhielt 120 Danke für 87 Beiträge

    Standard

    Wichtig zu wissen wären erstmal ein paar Eckdaten wie der auszuwertende Code denn nun wirklich aussieht:

    1. Ist der aufbau immer konsistent? D.h. kommt nach deinen 280 Bytes immer ein VAR1= ? Oder was könnte da sonst stehen? Vielleicht kannst du uns ja mal ein typisches schnipsel geben...
    2. Max. und Min. Anzahl an Vor- und Nachkommastellen bitte nennen.

    Ich denke, der Ansatz vom pn/dp ist schon eine ecke schneller, da er schon aus der ersten Schleife springt, wenn das v nicht findet. Seiner wertet quasi ja noch 4 stellen mehr aus... 4 zeilen mehr Code= länge Zykluszeit...

    Da ich deinen weiteren Code jetzt nicht kenne, würde ich pn/dps Ansatz erstmal nehmen, nach einer gefundenen Variable aber mir den Offset zur nächsten VAR merken, und damit dann den auszuwertenden Code kleiner machen...

    Andere frage: Muss das Zyklusgenau sein? Hast die Daten doch eh im Puffer stehen... wenn du jetzt davon ausgehst, dass du eine max Anzahl von Variablen x hast, könntest du bei jedem Zyklus nach einem var[x] in deinem Puffer suchen, und nach dem durchlauf inkrementieren... dies nur als Beispiel zur asynchronen abarbeitung...
    Geändert von mnuesser (09.06.2013 um 08:12 Uhr)
    gruss Markus

  7. Folgender Benutzer sagt Danke zu mnuesser für den nützlichen Beitrag:

    Matze001 (09.06.2013)

  8. #5
    Matze001 ist offline Erfahrener Benutzer
    Themenstarter
    Registriert seit
    11.12.2009
    Beiträge
    2.113
    Danke
    388
    Erhielt 390 Danke für 271 Beiträge

    Standard

    Hallo Ihr zwei,

    danke für eure Antworten:

    PN/DP
    1. ja die zweite For-Schleife beginnt eigentlich mit TMP_FOUND und endet mit TMP_FOUND + n.
    2. Die verschiedenen IF-Abfragen sind gut -> Danke wird umgesetzt

    Mnuesser


    1. Eckdaten: Die erste Variable kommt immer an der Gleichen stelle, und dann ist es halt abhängig davon wie die Variablen ankommen, wie weit die dahinter verschoben sind. d.h. ist VAR1 sehr groß, ist Var2 ca. 2-5 CHARS weiter hinten, ist VAR2 auch sehr groß, ich Var3 weiter hinten etc.
    2. es sind max. 6 stellen vor, und 6 Stellen nach dem Komma möglich (es gibt auch Sonderdinger, da steht was anderes drin, die beachte ich aber erstmal nicht)
    3. nen Groben Aufbau habt ihr ja, es kommen hintereinander die verschiedenen variablen, mehr nicht.

    4. Muss es Zyklusgenau sein: Jein. Meine Funktion ist z.Zt. so:

    Wenn neue Daten ankommen (T_RECV.NDR) wird der Puffer ausgewertet und alles weggeschrieben.
    So habe ich sichergestellt, das ich nichts verpasse.

    Ich müsste mal nen Counter einbauen, wie viele Zyklen keine neuen Daten kommen. Wenn das ausreichend viele sind kann ich mir auch vorstellen das auswerten auf mehrere SPS-Zyklen zu legen. Das hatte ich schon im Hinterkopf, hatte es aber zunächst nicht umgesetzt, weil ich mir noch nicht sicher bin ob ich mir dadurch vielleicht Probleme ins Haus hole. Wenn z.B. nur alle 5-10 SPS-Zyklen neue Daten kommen, dann kann ich ruhig die Auswertung auf 2-3 Zyklen legen. Mein Ansatz hierfür wäre aber ein anderer:


    Vorweg zum Beispiel: Mir ist klar das in dieser "Schrittkette" auch alle Schritte in einem Zyklus abgearbeitet werden, müsste sie halt verdreht aufbauen, oder noch ein Bit zum Sperren des nächsten Schritts einbauen.
    Code:
    IF NDR THEN
    
    // Auslesen von 5 Variablen
    SK_NR:=10;
    
    END_IF;
    
    IF SK_NR = 10 THEN
    
    // Auslesen der nächsten 5 Variablen
    
    SK_NR:=20;
    
    END_IF;
    
    ETC!


    Ich danke euch beiden schonmal für die Ansätze, ich werde mal berichten wie sich die Änderungen ausgewirkt haben!

    Grüße

    Marcel

  9. #6
    Registriert seit
    29.03.2004
    Beiträge
    5.735
    Danke
    143
    Erhielt 1.685 Danke für 1.225 Beiträge

    Standard

    Wenn das Programm auch auch ungültige Datensätze erkennen und behandeln können soll, ist womöglich ein anderer Ansatz erforderlich.

    Was soll das Programm beispielsweise machen, wenn ein Satz wie:
    Variable1=1Variable2=4321.1

    oder
    Variable1=1x2,Variable2=4321.1

    hereinkommt?

    Dein jetziges Programm scheint solche Fälle zu ignorieren oder sich womöglich daran zu verhaspeln und ungültige Werte auszugeben.

    Ein etwas theoretischerer Ansatz:
    Um die Sätze auf Korrektheit überprüfen zu können, benötigt man aber ersteinmal eine Syntax-Definition wie ein gültiger Satz aufgebaut sein muss. Für die Beschreibung solcher Dinge gibt es eigene Sprachen, z.B. EBNF (http://de.wikipedia.org/wiki/Erweite...ckus-Naur-Form).

    Anhand deiner Beispielsätze würde diese womöglich so aussehen:

    Code:
    assignmentList = assignment { "," assignment }.
    assignment = identifier "=" ( intNumber | realNumber ).
    identifier = letter { letter } intNumber.
    intNumber = digit { digit }.
    realNumber = digit { digit } "." digit { digit }.
    digit = "0123456789".
    letter = 'A' .. 'Z' + 'a' .. 'z'.
    Dein Zeichenarray das du zugesenden bekommst ist sozusagen eine Aussage in der Sprache "assignmentList".
    Kleine Erläuterung zu den Zeichen: Geschweifte Klammern {} bedeuten, dass das darin enthaltene Symbol optional wiederholt werden kann.

    Anhand der Syntax lässt sich nun ein Parser programmieren.
    Ob dieser Parser der sich dann ergibt schneller als dein jetziger wird lass ich mal dahingestellt, auf jeden Fall wird er bei weitem keine 1200 Zeilen benötigen und zuverlässig Fehler erkennen können.

    PS
    Ein Beispiel wie man so einen Parser programmieren könnte habe ich hier mal gepostet:
    Einfacher Formelparser in SCL

  10. Folgender Benutzer sagt Danke zu Thomas_v2.1 für den nützlichen Beitrag:

    Matze001 (09.06.2013)

  11. #7
    Matze001 ist offline Erfahrener Benutzer
    Themenstarter
    Registriert seit
    11.12.2009
    Beiträge
    2.113
    Danke
    388
    Erhielt 390 Danke für 271 Beiträge

    Standard

    Hallo Thomas,

    danke für deine Antwort!

    Es kann nicht vorkommen, dass solche Fehler passieren wie von dir beschrieben, im Zweifel wird nichts empfangen.
    Mein Partner der mir die Daten sendet ist in der Hinsicht recht gut ausprogrammiert. Wenn es auch in anderer Hinsicht mal so wäre...
    Deshalb bin ich darauf ich nicht näher eingegangen was passiert wenn dieser Fall eintritt, wenn aber z.B. Variable1=Variable2=1 kommen SOLLTE, dann steht in Variable1 nach der Wandlung nach DINT eine 0, dann STRING_TO_DINT() keine Zahl erkennt und 0 ausgibt! Diese Reaktion ist okay für mich.

    Noch zur Info zum 1200 Zeilen "Trümmer" in SCL:

    Die 1200 Zeilen machen nicht nur die Auswerten, dahinter verbirgt sich noch der Aufruf von T_SEND, T_RECV, das aufbereiten von Sendedaten, und ca. 50% der Zeilen machen meine Kommentare aus.

    Grüße

    Marcel

  12. #8
    Registriert seit
    29.04.2012
    Beiträge
    195
    Danke
    13
    Erhielt 42 Danke für 37 Beiträge

    Standard

    Die Variablen kommen doch immer in der gleichen Reihenfolge / es fehlt keine dazwischen oder?

    Wo startet dann deine Suchen nach Var2, wieder bei 280?

    Da ließe sich sparen mit:

    FOR I:=280 + Länge VarBisher TO Ende - Länge VarAktuell DO
    (Wenn nicht schon gemacht)

    Oder die Vergleiche komplett weglassen:
    Einmal über das Array laufen und die Positionen von = . und , abspeichern.(Array of Struct - 3xINT)
    Dann ist klar wo die Werte für Variable 1-x stehen.
    Geht natürlich massiv daneben, wenn eine Variable fehlt.

    Generell:
    TMP_STRING:=' ';
    Unsicher was der Compiler damit macht, evtl. ist es schneller eine 0 an das zweite String-Byte zu schreiben.

    Concat in der Schleife sieht auch nicht besonders performant aus.
    Würde ich vergleichshalber mal einen SFC 20 BLKMOV probieren.

  13. Folgender Benutzer sagt Danke zu Pipboy für den nützlichen Beitrag:

    Matze001 (09.06.2013)

  14. #9
    Matze001 ist offline Erfahrener Benutzer
    Themenstarter
    Registriert seit
    11.12.2009
    Beiträge
    2.113
    Danke
    388
    Erhielt 390 Danke für 271 Beiträge

    Standard

    Hallo Pipboy,

    danke für dein Antwort!

    Reihenfolge ist immer gegeben! Ich fange NICHT immer wieder bei 280 an, sondern ich weis ja wo in etwa die Variablen ankommen (Variable1 bei etwa 280, Variable2 bei etwa 320, Variable3 bei etwa 360, etc...) Diese Positionen +-10 nutze ich für die FOR-Schleifen zum Suchen nach den einzelnen Variablen. Das ist effektiver als eine komplette For-Schleife über das ganze Array zu jagen, und dann wieder mit Schleifen zu suchen.

    TMP_STRING:= ' '; läuft bisher immer sauber! Im zweiten Byte steht die Längeninfo vom String wenn ich mich nicht irre? Wäre auch ne Idee (aber wieder weniger lesbar / nicht symbolisch)

    CONCAT ist nicht performant, ist mir klar. Bisher ist mir nur noch keine sinvollere Operation eingefallen um Strings aneinander zu bauen (Wie ich das mit dem SFC20 machen soll fällt mir adhoc auch nicht ein!)

    Ich versuche so gut es geht auf die Funktionen von Siemens zu verzichten (FIND und DELETE konnte ich z.B. schon ersetzen)

    Grüße

    Marcel

  15. #10
    Registriert seit
    22.06.2009
    Ort
    Sassnitz
    Beiträge
    11.186
    Danke
    923
    Erhielt 3.291 Danke für 2.660 Beiträge

    Standard


    Zuviel Werbung?
    -> Hier kostenlos registrieren
    Hallo,

    ich würde ebenfalls nur einmal von 280 bis zum Ende das Byte-Array durchgehen und nicht erneut die nächste Var. suchen. Höchstwahrscheinlich würde ich sogar direkt die Ziffern in DINT/REAL umwandeln. Mit dem gleichen Aufwand, wie Du den String für STRING_TO_DINT() zusammenstellst, kann man auch gleich rechnen:
    Zwischenwert = Zwischenwert * 10 + ASCIIziffer - '0'
    (ein Algorithmus für die Nachkommastellen würde mir dann auch wieder einfallen )

    Da - wie Du sagst - kein Formatfehler in dem Zeichenstrom enthalten sein kann würde ich beim ersten unerwarteten Zeichen einfach die Konvertierung komplett abbrechen und verwerfen, statt Whitspaces und sonstiges auszuwerten.

    Harald
    Es ist immer wieder überraschend, wie etwas plötzlich funktioniert, sobald man alles richtig macht.

    FAQ: Linkliste SIMATIC-Kommunikation über Ethernet

Ähnliche Themen

  1. Antworten: 9
    Letzter Beitrag: 31.08.2012, 08:55
  2. S7-1200-Array of Char in string
    Von Diplomand11 im Forum Simatic
    Antworten: 1
    Letzter Beitrag: 21.01.2011, 08:44
  3. Integer in Char Array wandeln ?
    Von Power_Pete im Forum Simatic
    Antworten: 11
    Letzter Beitrag: 28.01.2010, 15:26
  4. Array of Char umwandeln?
    Von thomzur im Forum Simatic
    Antworten: 3
    Letzter Beitrag: 25.02.2008, 17:06
  5. Array mit Char an FC übergeben?
    Von Ingo im Forum Simatic
    Antworten: 5
    Letzter Beitrag: 15.12.2007, 16:07

Lesezeichen

Berechtigungen

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