Step 7 Viele Netzwerke mit Merkern einsparen.

Zuviel Werbung?
-> Hier kostenlos registrieren
Ich habe das heute ausprobiert ein Array of Bool als Output zu deklarieren. Ich konnte dann aber nichts an dem Output dran parametrieren.
Ich wollte den Merkerbereich den für die Visu benutzen. (p#M6352.0 Bool 80) Oder muß man erst einen Pointer für den Output erstellen?

Mit KOP/FUP wird das nichts. Entweder AWL mit Pointer oder elegant mit SCL. Sonst bleibt Dir nur viel Tipparbeit. Das wurde Dir ja hier schon gesagt.
 
Hallo Tigerente1974,

Vielen Dank noch für deine letzten Antworten.

Es war alles umsonst.

Da das System was mir die Schweiß-Nr schickt ist leider untauglich. Ich habe Signal überschneidungen.
Es ist vorgekommen, das wenn der Roboter die Schweißnäht in ganz kurzen Abständen macht z.B. im Sekundentakt, dann kann ich das IO Signal nicht mehr erfassen.
Ich kann also das IO Signal nicht mehr der richtigen Naht zuweisen, weil kein Signalwechsel mehr statt gefunden hat. Das System arbeitet leider nicht im Handshake.
Bei langen Nähten mag es vielleicht funktionieren. Aber wenn dann alle Nähte oder gar keine.

Da dieser Thread also für die Katz war, wäre es wohl Sinnvoll ihn zu löschen weil es braucht ja keiner etwas lesen was zu nichts führt.

Vielen Dank an alle.

Mfg Tommylik
 
Hallo Harald,

Vielen Dank für deine Frage.

Ja natürlich unterbricht der Robi das Schweissen und in dem Moment bekommt er die neue Schweiß-Nr und bei der Naht davor ist die Auswertung.
Während der Auswertung schweißt er schon die nächste Naht. Sind die Nähte lang genug ist das IO Signal wieder abgefallen. Kein Problem.
Aber die kurzen Nähte von 20mm länge macht er in wer weiß wie schnell. Da habe ich keine Chance.

Es sei den du hast für so eine Signalerfassung einen Trick auf Lager.


Vielen Dank nochmal für alles.


Mfg Tommylik
 
Hi,

Wenn ich das jetzt Recht verstehe, kannst du bei einer kurzen Schweißnaht diese nicht zu Ende prüfen?

Und funktioniert das Ganze nacheinander oder auch Mal durcheinander?

Bekommst du jeweils für i.O. und für n.i.O. Signale?

Gruß

Mavorkit

Gesendet von meinem SM-G389F mit Tapatalk
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo Mavorkit,

vielen Dank für deine Antwort.

Wenn ich das jetzt Recht verstehe, kannst du bei einer kurzen Schweißnaht diese nicht zu Ende prüfen?

Ja genau wenn kurze Nähte hintereinander sind dann nicht.
Wenn aber nach einer kurzen Naht eine lange Naht kommt dann funktioniert es, weil bis die lange Naht fertig ist,
ist das IO-Signal von der kurzen Naht davor wieder auf 0.
Es ist halt sehr wichtig das ich die Signale IO oder NIO der richtigen Naht zuweisen kann.
Sonst hat doch diese Visualisierung keine Ausagekraft.

Und funktioniert das Ganze nacheinander oder auch Mal durcheinander?

Der Roboter hat ein festes Programm was er abfährt und das beinhaltet eine Vorgabe in welcher Reihenfolge
die Nähte geschweißt werden müssen.

Bekommst du jeweils für i.O. und für n.i.O. Signale?

Ja, IO und NIO sind unterschiedliche Eingänge.

Vielen Dank nochmal für deine Antwort.

Mfg Tommylik
 
Hallo Tommylik,

es wäre interessant zu wissen, wie schnell "wer weiss wie schnell" ist.
Üblicherweise läuft eine SPS mit einem Zyklus der schneller als 20ms ist.
Ich nehme mal an der Zyklus ist immer noch deutlich schneller als der Roboter mit der Schweißnaht.
Wie wird die Information übergeben? Z.B. mit PN/PN-Koppler?
Werden die Daten konsistent über die ganze Länge übergeben?
Ich vermute dein Problem liegt eher in der Auswertung und nicht im kurzen Zyklus.
 
Ich vermute, dass das Problem nicht die Geschwindigkeit der SPS ist, sondern die Auswertegeschwindigkeit des Kamerasystems nicht hinterher kommt.
Wenn das System 3 Sekunden zur Auswertung braucht, die nächste Schweissnaht aber weniger als 3 Sekunden braucht, dann geht doch diese Naht verloren, bzw kann die Auswertung nicht mehr der richtigen Nahtnumer zugeordnet werden.
Andererseits hat er gesagt, das er den laufenden Prozess auch beobachten kann, aber eine gewisse Verzugszeit wird schon vorhanden sein.
Vielleicht kann man die Auswertung in 2 Instanzen machen die sich abwechseln? Dann übergibt man zu Beginn der Naht die Nummer dem Auswertesystem und nach Auswertende sendet das Auswertesystem die Nummer plus IO oder NIO zurück. Im einfachsten Fall wäre das ja nur ein INT hin und ein INT+1Bit zurück.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Am schnellsten kommt man da mit SCL voran, da ist klar. Nur dort lassen sich Arrays sauber indiziert bearbeiten.

Ich hätte aber auch noch eine KOP/AWL Lösung, so dass man udtArrays in KOP verarbeiten kann.

Du machst dir einen udtNaht.
Code:
TYPE udt_Naht   // UDT 1
    STRUCT
    // Typbeschreibung
       xNIO: Bool ;    //NIO-Flag
       xIO : Bool; // IO-FLAG
       dtDate : DATE_AND_TIME ;    //TimeStamp
    END_STRUCT
END_TYPE

Dann einen DB mit einem Array von udtNaht.
Einträge 0..MaxNaht

Dann verwende ich einen FC, der in der Lage ist UDT_Arrays zu handeln

Code:
FUNCTION "m7b_udtCopyArray" : VOID
TITLE =kopiert einzelne UDT's von UDT-Arrays
//Kopiert UDT's aus Arrays, die Datenlänge des UDT wird automatisch ermittelt. 
//Anpassungen der Datenlänge nach Änderungen an den UDT's entfällt somit.
//
//Achtung Array bzw. Speichergrenzen werden nicht überprüft.
//Gegebenenfalls, Indexangaben vorher auf Korrektheit prüfen bzw. limittieren!
//Bei inkorrekten Indexangaben geht CPU in STOP.
//
//Verwendung: Verwaltung von Datensätzen wie Rezepturen, Betriebsdaten, 
//Positionsdaten usw. in der Steuerung. 
//
//Kopiert wird von/zu: DB, statischen Lokaldaten im Instanz-DB 
//(Multinnstanzfähig, ohne zus. Adresskorrektur, da Step7 bei Verwendung von 
//Instanzdaten bei UDT's automatisch als Quelle [#84] DB und Nr. mit korrekter 
//Adress angibt statt nur DI [#85])
//
//Nicht kopiert wrid von/zu lokalen Daten (TEMP), da vor- vorherige Lokaldaten 
//benötigt werden (S7 aber nur vorherige Lokaldaten unterstützt)
//
//[IN]
//srcUdtArray : Anypointer auf den ersten UDT im Quell-Array
//srcIndex    : Index des Quell-UDT im Array, beginnend bei 0
//destUdtArray: Anypointer auf den ersten UDT im Ziel-Array
//destIndex   : Index des Ziel-UDT im Array, beginnend mit 0
//
//DATUM: 10/2007
//
//AENDERUNGSVERMERKE:
//--------------------------------------------------------------------------------
//DATUM        NAME       AENDERUNG
//--------------------------------------------------------------------------------
//20.03.2017   S.Maag     Verwendung von AR2 entfernt und Abfrage auf
//                        Daten Speicherbereich #87 vorheriger Lokaldatenstack
//                        hinzugefügt, da Daten aus vorherigem Stack nicht
//                        kopiert werden können, da BLKMOVE neuen L-Stack anlegt
//--------------------------------------------------------------------------------
//
AUTHOR : 'S.Maag'
FAMILY : Maagic7
VERSION : 0.1


VAR_INPUT
  srcUdtArray : ANY ;    
  srcIndex : INT ;    
  destUdtArray : ANY ;    
  destIndex : INT ;    
END_VAR
VAR_OUTPUT
  BLKMOV_RetVal : INT ;    //Return Value der Blockmovefunktion
END_VAR
VAR_TEMP
  pSRC : ANY ;    //mit Indexdaten modifizierter Quellpointer für BlockMove-Funktion
  pDEST : ANY ;    //mit Indexdaten modifizierter Zielpointer für BlockMove-Funktion
  dwPart1 : DWORD ;    
  wPart2 : WORD ;    
  dwPart3_Address : DWORD ;    
  dwBitAddress : DWORD ;    
  bMemory : BYTE ;    //Speicherbereich
END_VAR
BEGIN
NETWORK
TITLE =
//ANY
//Byte 0: 10h für S7
//Byte 1: Datentyp
//Byte 2..3: Wiederholungsfaktor
//Byte 4..5: DB-Nr
//Byte 6: Speicherbereich
//Byte 7..9: Byte/Bit-Adresse
//
//Speicherbereiche
//#80  P : Perepherie
//#81  E : Eingänge
//#82  A : Ausgänge
//#83  M : Merker
//#84  DB : Datenbaustein
//#85  DI : Instanz-DB
//#86  L  : Lokaldaten (L-Stack)
//#87  V  : Verherige Lokaldaten


NETWORK
TITLE =ANY-Pointer Quelle für BlockMove bearbeiten
//Beim Wiederholungsfaktor wird automatisch von Byte ausgegeangen. 
//Für UDT's stimmt dies auch immer. Falls der Baustein allgemein zum kopieren von 
//Anypointerbasierten Daten verwendet werden soll, so muss dies beachtet bzw. 
//angepasst werden. 
//Den ANY-Pointer Quelle mit den Indexdaten modifizieren und als ANY-Pointer für 
//die BlockMove-Funktion speichern
      L     P##srcUdtArray; // Pointer auf den Quellpointer
      LAR1  ; // in Adressregister 1

      L     D [AR1,P#0.0]; // Part1
      T     #dwPart1; 
      L     W [AR1,P#4.0]; // Part2
      T     #wPart2; 
      L     D [AR1,P#6.0]; // Part3  (Address-Pointer)
      T     #dwPart3_Address; 
      SRD   24; // Shift 3 Byte = Speicherbereich
      T     #bMemory; 
      L     B#16#87; // Daten vom vorherigen Lockaldaten Stack (geht nicht!)
      ==I   ; 
      SPB   ERR; 


// Calculating the Address with Source ARRAY Index
      L     W [AR1,P#2.0]; // Wiederholungsfaktor
      L     #srcIndex; 
      *I    ; // Offset aus Index für Quellbereich
      SLD   3; // ins Pointerformat konvertieren
      L     #dwPart3_Address; // Ursprüngliche Quelladdresse
      UD    DW#16#FFFFFF; // oberes Byte fuer Speicherbereich ausblenden
      +D    ; // Quelladresspointer mit verrechnetem Index
      T     #dwBitAddress; 

      L     P##pSRC; // Pointer auf AnyPointer Quelle für BlockMove
      LAR1  ; // in Adressreguster 1

      L     #dwPart1; // Part 1 of ANY
      T     D [AR1,P#0.0]; // to pSRC [ANY] 

      L     #wPart2; // Part 2
      T     W [AR1,P#4.0]; // DB-Nr.

      L     #dwPart3_Address; // Part 3 Address
      UD    DW#16#FF000000; // Speicherbereich maskieren
      L     #dwBitAddress; // mit Array-Index modifizierte Adresse
      OD    ; // Speicherbereich_Adresse zusammenführen
      T     D [AR1,P#6.0]; 

NETWORK
TITLE =ANY-Pointer Ziel für BlockMove bearbeiten

      L     P##destUdtArray; // Pointer auf den Quellpointer
      LAR1  ; // in Adressregister 1

      L     D [AR1,P#0.0]; // Part1
      T     #dwPart1; 
      L     W [AR1,P#4.0]; // Part2
      T     #wPart2; 
      L     D [AR1,P#6.0]; // Part3  (Address-Pointer)
      T     #dwPart3_Address; 
      SRD   24; // Shift 3 Byte = Speicherbereich
      T     #bMemory; 
      L     B#16#87; // Daten vom vorherigen Lockaldaten Stack (geht nicht!)
      ==I   ; 
      SPB   ERR; 

// Calculating the Address with Destination ARRAY Index
      L     W [AR1,P#2.0]; // Wiederholungsfaktor
      L     #destIndex; 
      *I    ; // Offset aus Index für Quellbereich
      SLD   3; // ins Pointerformat konvertieren
      L     #dwPart3_Address; // Ursprüngliche Quelladdresse
      UD    DW#16#FFFFFF; // oberes Byte fuer Speicherbereich ausblenden
      +D    ; // Quelladresspointer mit verrechnetem Index
      T     #dwBitAddress; 

      L     P##pDEST; // Pointer auf AnyPointer Quelle für BlockMove
      LAR1  ; // in Adressreguster 1

      L     #dwPart1; // Part 1 of ANY
      T     D [AR1,P#0.0]; // to pDEST [ANY] 

      L     #wPart2; // Part 2
      T     W [AR1,P#4.0]; // DB-Nr.

      L     #dwPart3_Address; // Part 3 Address
      UD    DW#16#FF000000; // Speicherbereich maskieren
      L     #dwBitAddress; // mit Array-Index modifizierte Adresse
      OD    ; // Speicherbereich_Adresse zusammenführen
      T     D [AR1,P#6.0]; 

NETWORK
TITLE =kopieren der Daten mittels BlockMove

      CALL "BLKMOV" (
           SRCBLK                   := #pSRC,
           RET_VAL                  := #BLKMOV_RetVal,
           DSTBLK                   := #pDEST);
      NOP   0; 
NETWORK
TITLE = 

      SET   ; 
      SAVE  ; 
      BEA   ; 

NETWORK
TITLE =
//Daten vom vorherigen Lokaldatenstack können nicht kopiert werden, da 
//BLKMOVE neuen L-Stack öffnet und die Daten somit vom vor- vorherigen Stack 
//wären
ERR:  L     W#16#8888; // Daten vom vorheriger Lockaldatenstack
      T     #BLKMOV_RetVal; // können nicht kopiert werden, da BLKMOVE neune Stack anlegt
      SET   ; 
      SAVE  ; 
      BE    ; 

END_FUNCTION

Dein Naehte-Array beginnt jetzt bei [0]. Ich gehe mal davon aus, dass es NahtNr 0 nicht gibt, sondern diese bei 1 beginnt.

In Naehte [0], schreibst du immer deine gerade aktuelle IO NIO Melung un den Timestamp. (Der Tastendruck IO(NIO)
Gleich anschließend kopierst du die Daten mit udt_ArrayCopy in die aktuelle Naht. Naehte[x].
Das wars.

Die letzte geschweißte NahtNr musst du dir halt noch zwischenspeichern bis die IO/NIO Meldung kommt.

Alternativ hab ich udtCopyArray auch noch als SCL Version. Da die SCL Version aber bei mir noch nicht im Feldeinsatz ist, könnten da noch Bugs drin sein.
Das ist definitiv bei der AWL Verision nicht der Fall.
Code:
FUNCTION m7_udtCopyArray : VOID
(*
   udtCopyArray:
   trotz UC Aufruf durch den SCL-Kompiler können keine Daten von/zu TEMP-Variablen erfolgen.
   Daten stimmen in diesem Fall nicht!
*)

TITLE = 'udtCopyArray'
VERSION : '3.0'
AUTHOR  : 'S.Maag'
FAMILY  : 'Maagic7'

(*  ================================================================================

 udtCopyArray:

    Kopiert UDT's aus Arrays, die Datenlänge des UDT wird automatisch ermittelt. 
    Anpassungen der Datenlänge nach Änderungen an den UDT's entfällt somit.
    
    Achtung Array bzw. Speichergrenzen werden nicht überprüft.
    Gegebenenfalls, Indexangaben vorher auf Korrektheit prüfen bzw. limittieren!
    Bei inkorrekten Indexangaben geht CPU in STOP.
    
    Verwendung: Verwaltung von Datensätzen wie Rezepturen, Betriebsdaten, 
    Positionsdaten usw. in der Steuerung. 
    
    Kopiert wird von/zu: DB, statischen Lokaldaten im Instanz-DB 
    (Multinnstanzfähig, ohne zus. Adresskorrektur, da Step7 bei Verwendung von 
    Instanzdaten bei UDT's automatisch als Quelle [#84] DB und Nr. mit korrekter 
    Adress angibt statt nur DI [#85])
    
    Nicht kopiert wrid von/zu lokalen Daten (TEMP), da vor- vorherige Lokaldaten 
    benötigt werden (S7 aber nur vorherige Lokaldaten unterstützt)
    
    [IN]
    srcUdtArray : Anypointer auf den ersten UDT im Quell-Array
    srcIndex    : Index des Quell-UDT im Array, beginnend bei 0
    destUdtArray: Anypointer auf den ersten UDT im Ziel-Array
    destIndex   : Index des Ziel-UDT im Array, beginnend mit 0

 
 DATE: 10/2007

 CHANGELOG:
 --------------------------------------------------------------------------------
 DATE         NAME        DESCRIPTION
 --------------------------------------------------------------------------------
 20.03.2017   S.Maag      Converted AWL Version m7b_udtCopyArray to SCL
 --------------------------------------------------------------------------------
 *)

VAR_INPUT
    srcUdtArray : ANY;  // AnyPointer to first UDT in SourceArray
    srcIndex : INT;     // Index of Source_UDT in the Array[0..x]
    destUdtArray : ANY; // AnyPointer to first UDT in DestinationArray
    destIndex : INT;    // Index of Destination_UDT in the Array[0..x]
END_VAR

VAR_OUTPUT
    BLKMOVE_RET : INT;    
END_VAR

VAR_TEMP
  
    anySRC : ANY;
    anyDEST :ANY;
   
    p_anySRC AT anySRC: STRUCT  // Mit dem  AT Befehl wird der gleiche Bereich in einer anderen Form définiert
       ID  : WORD;  // ID für ANY (1002 hex = es wird mit Bytes gearbeitet)
       REP :INT;    // Wiederholungsfaktor
       DBNo : INT;   // DB der im ANY Pointer benutzt wird ANY
       PTR : DWORD; // Pointer Doppelwort um den Angfang des Datenbereichs und den Datentyp zu definieren (84hex = DB Datentyp)
    END_STRUCT;
 
     p_anyDEST AT anyDEST: STRUCT  // Mit dem  AT Befehl wird der gleiche Bereich in einer anderen Form définiert
       ID  : WORD;  // ID für ANY (1002 hex = es wird mit Bytes gearbeitet)
       REP :INT;    // Wiederholungsfaktor
       DBNo : INT;   // DB der im ANY Pointer benutzt wird ANY
       PTR : DWORD; // Pointer Doppelwort um den Angfang des Datenbereichs und den Datentyp zu definieren (84hex = DB Datentyp)
    END_STRUCT;
      
    tmpDataPointer : DWORD;
    
END_VAR

BEGIN
    anySRC := srcUdtArray;
    anyDEST := destUdtArray;
    
    tmpDataPointer := DINT_TO_DWORD(DWORD_TO_DINT(p_anySRC.PTR AND DW#16#FFFFFF) + INT_TO_DINT(p_anySRC.REP) * INT_TO_DINT(srcIndex)* 8);
    p_anySRC.PTR := (p_anySRC.PTR AND DW#16#FF000000) OR tmpDataPointer;
 
    tmpDataPointer := DINT_TO_DWORD(DWORD_TO_DINT(p_anyDEST.PTR AND DW#16#FFFFFF) + INT_TO_DINT(p_anyDEST.REP) * INT_TO_DINT(destIndex) * 8);
    p_anyDEST.PTR := (p_anyDEST.PTR AND DW#16#FF000000) OR tmpDataPointer;
   
    BLKMOVE_RET := BLKMOV(srcblk:= anySRC, dstblk:= anyDEST); // SFC20
    OK := TRUE; // ENO
END_FUNCTION
 
korrekten Aufruf von udtCopyArray hab ich noch vergessen.

SourceArray und DestinationArray sind ja in deinem Fall gleich.
Angeben werden muss als Sourcd-/Destionation Array.
DB_Naehte.Naht[0]

Achtung unbedingt darauf achten, dass als ARRAY nicht der eigentliche ARRAY angeben wird, sondern der erste Eintrag.
Liegt daran, dass daraus die Any-Pointer automatisch berechnet werden.
 
Zurück
Oben