Step 7 Mit Pointer Array-Element durchsuchen

bmwled

Level-2
Beiträge
58
Reaktionspunkte
2
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo zusammen,

ich hoffe ihr könnt mir etwas weiterhelfen. :)

Folgende Aufgabe:
In einem Array-Element [1..10] sind Durchmesser gespeichert.
Nun wird ein Durchmesser mit einem Sensor gemessen.
Dieser Wert soll nun mit den gespeicherten Werten im Array verglichen werden.
Bei einem Treffer soll die Nummer des Array Feldes ausgegeben werden also eine Zahl zwischen 1 und 10.
Da die Messungen schwanken, wird noch ein Fenster um den geladenen Wert aus dem Array gebildet.

Leider bekomme ich keinen Wert aus der aktuellen Stelle des Pointer heraus (Wert = 0).

Hat jemand eine Idee?

Grüße



Code:
      UN    #oShaftDiaValid             // Überprüfung gemessener Wert gültig...
      SPB   End

      L     #oToolNumberDetected        // Überprüfung Treffer gefunden
      L     0
      <>I   
      SPB   End

      L     L#1                         // Pointer initialisieren
      T     #sPointer

      L     P##iShaftDiaArray           // Array laden
      LAR1 


Star: L     #sPointer                   // Pointer bilden
      L     4                           // 4 wegen DINT im Array
      *I   
      SLD   3
      +AR1 

      L     D [AR1,P#0.0]               // Durchmesser aus Array laden..
      L     #iToleranceShaftMax
      +I   
      T     #tDiaMaxShaftTool           // ...positives Fenster bilden


      L     D [AR1,P#0.0]               // Durchmesser aus Array laden..
      L     #iToleranceShaftMin
      -I   
      T     #tDiaMinShaftTool           // ...negatives Fenster bilden


      L     #sShaftDiaAct               // Gemessenen Durchmesser laden
      L     #tDiaMaxShaftTool           // ...mit positivem Fenster vergleichen
      >I   
      SPB   next                        // Wert außerhalb -> Pointer inkrementieren

      L     #sShaftDiaAct               // Gemessenen Durchmesser laden
      L     #tDiaMinShaftTool           // ...mit negativem Fenster vergleichen
      <I   
      SPB   next                        // Wert außerhalb -> Pointer inkrementieren

      L     #sPointer                   // Wert im Bereich -> Treffer gefunden
      T     #oToolNumberDetected        // Pointer speichern

      SPA   End


next: L     #sPointer                   // Prüfen ob Array Ende erreicht
      L     10
      ==I   
      SPA   End                         // Springe ans Ende

      L     #sPointer                   // Pointer erhöhen
      L     1
      +I   
      T     #sPointer
      SPA   Star                        // Zurück zum Anfang


End:  NOP   0                           // Ende
 
Du erhöhst das AR1 etwas willkürlich... Du addierst ja auf den alten Wert immer den Offset ab Start neu auf ...
Ich würde bei Star:
L #sPointer // Pointer bilden
L 4 // 4 wegen DINT im Array
*I
SLD 3
+AR1

das alles weglassen und da wo den Pointer erhöhst noch
+AR1 P#4.0
einfügen. Ich weiss nicht ob deine Nutzdaten bei Feld 0 oder 1 anfangen. Das wäre noch anzupassen.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
:unsure: Ich gehe mal nicht auf Dein aktuelles Problem der korrekten Adressierung ein, sondern schwenke um zum Thema "Strategie".
Meine Vorstellung wäre:
- Ein sortiertes Array verwenden
- binär suchen
- falls exakte Übereinstimmung gefunden -> Ende der Suche
- falls keine exakte Übereinstimmung:
. für den nächst kleineren Wert die Abweichung zum gesuchten Wert berechnen
. für den nächst gösseren Wert die Abweichung zum gesuchten Wert berechnen
- den Wert mit dem kleineren Betrag der Abweichung wählen
- abschliessend entscheiden, ob diese Abweichung im ToleranzFenster liegt.

Nachtrag:
Ich kenne die Abstände zwischen den Werten in Deinem Array nicht.
Sind die Abstände relativ gleichmässig?
Sind sie so klein, dass mit der vorgegebenen Toleranz immer ein passender Wert gefunden werden kann?
Sind sie evtl. sogar so klein, dass 2 Werte des Arrays als Lösung in Frage kommen können?
 
Zuletzt bearbeitet:
:unsure: Ich gehe mal nicht auf Dein aktuelles Problem der korrekten Adressierung ein, sondern schwenke um zum Thema "Strategie".
Meine Vorstellung wäre:
- Ein sortiertes Array verwenden
- binär suchen
- falls exakte Übereinstimmung gefunden -> Ende der Suche
- falls keine exakte Übereinstimmung:
. für den nächst kleineren Wert die Abweichung zum gesuchten Wert berechnen
. für den nächst gösseren Wert die Abweichung zum gesuchten Wert berechnen
- den Wert mit dem kleineren Betrag der Abweichung wählen
- abschliessend entscheiden, ob diese Abweichung im ToleranzFenster liegt.
Ne oder?
Den exakten Vergleich kann man fast klemmen, der trifft dann in jedem millionsten Fall.
Ich finde deine vorgehndweise sinnlos kompliziert.
So wie er es machen will, paßt die Starategie zur gestellten Aufgabe.
Wo aber sitzt der Fehler, das war die Frage.
 
Erstmal vielen Dank für deinen Tipp Olli! Das hat mir geholfen.
So wie ich es jetzt habe, funktioniert es erstmal wie benötigt!

Das einzige, was jetzt nicht abgefangen wird, worauf Heinileini auch schon gekommen ist, dass wenn zwei gleiche bzw. dicht zusammen liegende Durchmesser nicht eindeutig unterschieden werden können.

Dafür fällt mir aber keine Lösung mit geringem Aufwand ein. Da die Werte nur von "geschultem" Personal editiert werden können, hab ich das jetzt nicht priorisiert.

Trotzdem nochmal vielen Dank für die schnelle Kommunikation hier im Forum!!

Grüße



Code:
     UN    #oShaftDiaValid             // Überprüfung gemessener Wert gültig...
      SPB   End

      U     #oToolDetectedFound         // Überprüfung Abfrage durchgeführt
      O     #oToolDetectedNotFound
      SPB   End

      L     P##iShaftDiaArray           // Array laden
      LAR1 


Star: L     D [AR1,P#0.0]               // Durchmesser aus Array laden..
      L     #iToleranceShaftMax
      +I   
      T     #tDiaMaxShaftTool           // ...positives Fenster bilden


      L     D [AR1,P#0.0]               // Durchmesser aus Array laden..
      L     #iToleranceShaftMin
      -I   
      T     #tDiaMinShaftTool           // ...negatives Fenster bilden


      L     #sShaftDiaAct               // Gemessenen Durchmesser laden
      L     #tDiaMaxShaftTool           // ...mit positivem Fenster vergleichen
      >I   
      SPB   next                        // Wert außerhalb -> Pointer inkrementieren

      L     #sShaftDiaAct               // Gemessenen Durchmesser laden
      L     #tDiaMinShaftTool           // ...mit negativem Fenster vergleichen
      <I   
      SPB   next                        // Wert außerhalb -> Pointer inkrementieren

      L     #sPointer                   // Wert im Bereich -> Treffer gefunden
      T     #oToolNumberDetected        // Pointer speichern
      S     #oToolDetectedFound
      SPA   End


next: L     L#10                        // Prüfen ob Array Ende erreicht
      L     #sPointer
      ==I   
      SPB   Not                         // Kein Werkzeug gefunden

      L     L#1                         // Pointer inkrementieren
      +I   
      T     #sPointer
      +AR1  P#4.0
      SPA   Star                        // Zurück zum Anfang

Not:  S     #oToolDetectedNotFound

End:  NOP   0                           // Ende
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Doch, war durchaus ernst gemeint.
Den exakten Vergleich kann man fast klemmen, der trifft dann in jedem millionsten Fall.
Ausnahmen muss eine Routine auch "erschlagen" können. Mit "fast klemmen" hast Du aber nichts Falsches gesagt.
Ich finde deine vorgehndweise sinnlos kompliziert.
Was genau findest Du kompliziert?
Ich finde die Realisierung in AWL "kompliziert" und habe eher in Richtung SCL gedacht - obwohl ich etliche Jahre fast ausschliesslich in AWL programmiert habe und nie in SCL.
Gut, ich will gerne zugeben, dass Sortieren und Binäres Suchen bei einer überschaubaren Liste von nur 10 Einträgen nach OverKill klingen mag.
Das Suchen in einer sortierten Liste hat zumindest den Vorteil, dass man in 999.999 Fällen von 1.000.000 nicht lange nach dem nächst grösserem und dem nächst kleineren Werten suchen muss (und in dem 1.000.000sten Fall ohnehin gar nicht danach suchen muss).
Wenn ich den AWL-Code überfliege, sehe ich hingegen, dass ...
- bei jedem SchleifenDurchlauf das "Fenster" neu berechnet wird (wenn Ober- und UnterGrenze z.B. in % definiert wäre/ist, würde mich das noch mehr stören)
- die Schleife abgebrochen wird, sobald ein Wert ins Fenster fällt, obwohl noch ein weiterer Wert folgen könnte, der noch besser passt.
So wie er es machen will, paßt die Starategie zur gestellten Aufgabe.
Betreffend die gestellte Aufgabe habe ich mittlerweile noch einen Nachtrag mit Fragen an Beitrag #3 angefügt.
Vielleicht neige ich einfach zu sehr dazu, einen möglichst allgemein anwendbaren Lösungsweg auszubrüten.
Wo aber sitzt der Fehler, das war die Frage.
Dieser Frage war ich bewusst aus dem Wege gegangen.
@Olli_BS ' Antwort in Beitrag #2 erschien mir so plausibel, dass ich mich nicht auch noch in die Pointerei hineinwühlen mochte. ;)
 
Dieser Frage war ich bewusst aus dem Wege gegangen.
@Olli_BS ' Antwort in Beitrag #2 erschien mir so plausibel, dass ich mich nicht auch noch in die Pointerei hineinwühlen mochte. ;)
Das ist durchaus ok, aber oft macht man die Kollegen noch konfuser und sie fangen etwas Neues an, bevor sie wirklich den Fehler haben.

@bmwled
Wenn 2 Durchmesser dicht beieinander liegen gewinnt der Erste gefundene oder?
 
Warum programmierst Du Deine Aufgabe in AWL? Warum nicht im viel einfacherem und verständlicherem SCL? In SCL könntest Du direkt mit dem Array-Index arbeiten und müsstest Dich nicht mit Speicheradressen und Speichergrößen von Datentypen und Bitpointer zu Bytepointer herumschlagen. Das Programm wäre anstatt 45 Zeilen vermutlich nur 15 Zeilen lang und vermutlich müsstest Du nicht hier fragen wo der Fehler in Deiner Pointerrechnung liegt.

Welche SPS programmierst Du mit welcher Entwicklungssoftware?

Harald
 
Zuviel Werbung?
-> Hier kostenlos registrieren
@Ralle
Ja, das ist richtig so. Bei einem gefundenen springe ich aus der Schleife.
@PN/DP
Ehrlich gesagt habe ich bisher noch wenig Erfahrung mit SCL. Bei dem Projekt wird eine S7-317F mit dem Simatic Manager programmiert.
 
Zurück
Oben