# Probleme mit SFC 14 / SFC 15 in FB



## smartie (12 Februar 2010)

Hallo zusammen, ich bastle mir im Moment mehrere FB´s zur Steuerung mehrerer Servos über Profibus.

Zum Lesen und Schreiben der Daten benutze ich die SFC14 / SFC15.


```
[B]Netzwerk 1[/B]

      L     #IO_ADRESSE               // IN : INT
      T     #Adresse                  // TEMP : WORD

[B]Netzwerk 2[/B]
 
 CALL  SFC   14                       // Daten von DP-Slave lesen
       LADDR  :=#Adresse              // TEMP : WORD
       RET_VAL:=#RET_VAL_SFC14        // TEMP : WORD
       RECORD :=#PI                   // STAT : STRUCT
 
[B]Netzwerk 3 [/B]   

 CALL  SFC   15                       // Daten auf DP-Slave schreiben
       LADDR  :=#Adresse              // TEMP : WORD
       RECORD :=#PO                   // STAT : STRUCT
       RET_VAL:=#RET_VAL_SFC15        // TEMP : WORD
```
Rufe ich den FB nun einmal in meinem Programm auf, so empfange ich alle Daten aus meinem Servo im STRUCT PI und kann damit arbeiten.

*Probleme gibts aber beim Schreiben:*
Setze ich ein Bit vom STRUCT PO so sehe ich zwar das das Bit in meinem FB gesetzt ist, am DP-Slave aber toggelt das Bit.

Probleme habe ich also scheinbar nur beim Schreiben der Daten.

Aber ich erkenne keinen Unterschied zwischen SFC 14 und SFC 15.

Kann mir jemand von euch auf die Sprünge helfen?

Gruß smartie


----------



## rostiger Nagel (12 Februar 2010)

Hallo Smartie,
die Adressen von der Ein.-und Ausgang Peripherie stimmen im 
DP-Teilnehmer überein. Der Struct ist nicht länger wie die Ausgang-
Peripherie. Was gibt den der Ret_Val vom SFC_15 zurück?

gruß Helmut


----------



## smartie (12 Februar 2010)

So, gerade eben als ich den PC runter fahren und Feierabend machen wollte ist mir eingefallen wo mein Problem liegt:

Ich habe für verschiedene Funktionen der Servos verschiedene FB´s erstellt.
Also für Tippen, Referenzieren, etc.

Diese FB´s enthalten alle die SFC 14 und SFC 15.


Da alle FB´s permanent bearbeitet werden schreibe und lese ich also immer wieder mit den beiden SFC´s von der gleichen Adresse.

Und das scheint wohl nicht so einfach zu gehen.

Wenn ich nämlich nur einen der ingesamt 8 FB´s aufrufe dann toggelt mein Bit nicht mehr.

Da einige der FB´s sehr viele Anschlüsse haben möchte ich nicht gerne nur einen großen FB machen, sondern schon wie geplant je Funktion einen FB.

Auch den Umweg über einen FB in den ich die Daten vom DP-Slave einlese und reinschreibe möchte ich nicht unbedingt gehen.

Am liebsten würde ich schon für jede Funktion einfach die EA - Adresse des DP-Slave angeben und fertig...

Hatte schon mal jemand mit der Problematik zu tun?

Gruß smartie

@ Helmut : Die Adressen stimmen natürlich und RETVAL beider SFC´s ist 0. Trotzdem Danke


----------



## rostiger Nagel (12 Februar 2010)

also das was du da vorhast ist nicht so günstig, einen mehrmaligen
aufruf des sfc14-15 für den selben Teilnehmer, das kann nicht
funktionieren.
Du solltest vlt. deine FB's für deine Betriebsarten beibehalten und 
koordninieren und dann zum schluß die SFC für den Teilnehmer nur
einmal aufrufen.


----------



## smartie (13 Februar 2010)

Guten Morgen,

ja das hatte ich schon befürchtet.

@ Helmut : Was meinst du mit



> Du solltest vlt. deine FB's für deine Betriebsarten beibehalten und
> koordninieren und dann zum schluß die SFC für den Teilnehmer nur
> einmal aufrufen.



Gruß smartie


----------



## rostiger Nagel (13 Februar 2010)

Du hast doch für jede Betriebsart einen FB, aus diesen FB's sammelst du
die Information die für dich wichtig sind und verschaltest die dann
auf einen FB der für die Komunikation mit deinen Umrichter verantwortlich
ist.

Für mich hört sich das ein wenig nach SEW an was du da hast. 
Ich mache das so das ich einen FC habe wo ich alles mit mache,
dann habe ich ein dazu gehörigen UDT für die Daten. Diese Daten
kann ich dann Global oder als Instanz ablegen und füttere diese.
An den FC lege ich nur noch den Zeiger wo die Daten liegen.


```
FUNCTION "SEW_SBP" : VOID
TITLE =SEW-Servo: Buspositonierung
AUTHOR : HO
FAMILY : SEW
NAME : BUS_POSI
VERSION : 0.1
 
VAR_INPUT
  Daten_Zeiger : ANY ; //Zeiger Ablage Daten für die Achse
END_VAR
VAR_TEMP
  PI : STRUCT  //Prozeßeingangsdaten
   Status : BYTE ; //PE: Status Umrichter
   Motor_turning : BOOL ; //PE: Motor läuft
   Inverter_ready : BOOL ; //PE: Umrichter bereit
   referenced : BOOL ; //PE: Achse Referenziert
   Target_position_reached : BOOL ; //PE: Ziel Position erreicht
   Brake_released : BOOL ; //PE: Bremse gelöst
   Error : BOOL ; //PE: Fehler
   Limit_Switch_CW : BOOL ; //PE: Endschalter Rechts
   Limit_switch_CCW : BOOL ; //PE: Endschalter Links
   Actual_position : DINT ; //PE: Aktuelle Position
   Actual_speed : INT ; //PE: Aktuelle Geschwindigkeit
   Active_current : INT ; //PE: Aktueller Motor-Strom
   Device_utilisation : INT ; //PE: Aktuelle Geräteauslastung
  END_STRUCT ; 
  PO : STRUCT  //Prozeßausgangsdaten
   start : BOOL ; //PA: Start
   Jog_plus : BOOL ; //PA: Tippen +
   Jog_minus : BOOL ; //PA: Tippen -
   mode_low : BOOL ; //PA: Mode Bit Low
   mode_high : BOOL ; //PA: Mode Bit High
   CTW_Bit_13 : BOOL ; //PA: Bit 13
   CTW_Bit_14 : BOOL ; //PA: Bit 14
   SWES : BOOL ; //PA: /Softwareendschalter
   Contr_inhibit : BOOL ; //PA: Reglersperre - /Freigabe
   Rapid_stop : BOOL ; //PA: Freigabe - /Schnellstop
   Stop : BOOL ; //PA: Freigabe - /Halt
   hold : BOOL ; //PA: /Halteregelung
   Ramp : BOOL ; //PA: Rampen
   Para : BOOL ; //PA: Parameter
   Reset_fault : BOOL ; //PA: Reset
   CTW_Bit_7 : BOOL ; //PA: Bit 7
   Setpoint_position : DINT ; //PA: Soll Position
   Setpoint_speed : INT ; //PA: Soll Geschwindigkeit
   Start_ramp : INT ; //PA: Hochlauf Rampe
   Stop_ramp : INT ; //PA: Tieflauf Rampe
  END_STRUCT ; 
  Daten : STRUCT  //Zeiger für DB und Adresse der Anzeige
   DB_Nr : INT ; //Anzeige-DB Nr
   Adresse : DWORD ; //Anzeige Start-Adresse im DB
  END_STRUCT ; 
  Ref : BOOL ; //Referenz
  Pos : BOOL ; //Positonierung angewählt
  Peripherie : WORD ; //Peripherie-Zeiger Umrichter
  RET_VAL_SFC14 : INT ; //Rückgabe vom DP lesen
  RET_VAL_SFC15 : INT ; //Rückgabe zum DP schreiben
  Merker : BOOL ; //Temponärer Merker
END_VAR
BEGIN
NETWORK
TITLE =Daten-Zeiger umladen
//ANY-Zeiger umladen
      L     P##Daten_Zeiger; 
      LAR1  ; 
//DB-Nr Temp. zwischenspeichern
      L     W [AR1,P#4.0]; 
      T     #Daten.DB_Nr; 
//Adresse Temp. zwischenspeichern
      L     D [AR1,P#6.0]; 
      T     #Daten.Adresse; 
NETWORK
TITLE =Datenbaustein aufschlagen und Adressregister stellen
      AUF   DB [#Daten.DB_Nr]; 
      LAR1  #Daten.Adresse; 
NETWORK
TITLE =Daten aus den Umrichter lesen
//Zeiger Peripherie stellen
      L     DBW [AR1,P#0.0]; //SEW_SBP_Daten.DRIVE_IO_ADDRESS
      T     #Peripherie; 
//Eingangsdaten vom FU lesen
      CALL "DPRD_DAT" (
           LADDR                    := #Peripherie,
           RET_VAL                  := #RET_VAL_SFC14,
           RECORD                   := #PI);
//Adressregister wieder herstellen
      LAR1  #Daten.Adresse; 
//Fehlerauswertung "vom FU-lesen"
      L     #RET_VAL_SFC14; 
      L     0; 
      <>I   ; 
      SPB   ERR; 
NETWORK
TITLE =Prozeßeingangsdaten aufbereiten und Rangieren
//Aktuelle Position
      L     #PI.Actual_position; 
      T     DBD [AR1,P#18.0]; //SEW_SBP_Daten.ACTUAL_POSITION
//Aktuelle Geschwindigkeit
      L     #PI.Actual_speed; 
      T     DBW [AR1,P#22.0]; //SEW_SBP_Daten.ACTUAL_SPEED
//Aktueller Strom
      L     #PI.Active_current; 
      T     DBW [AR1,P#24.0]; //SEW_SBP_Daten.ACTUAL_CURRENT
//Aktuelle Geräteauslastung
      L     #PI.Device_utilisation; 
      T     DBW [AR1,P#26.0]; //SEW_SBP_Daten.DEVICE_UTILISTION
//FU-Bereit
      U     #PI.Inverter_ready; 
      =     DBX [AR1,P#14.3]; //SEW_SBP_Daten.INVERTER_READY
//Zielpostion erreicht
      U     #PI.Target_position_reached; 
      =     DBX [AR1,P#14.7]; //SEW_SBP_Daten.TARGET_POS_REACHED
//Referenziert
      U     #PI.referenced; 
      =     DBX [AR1,P#14.6]; //SEW_SBP_Daten.REFERNCED
//Endschalter Rechts
      U     #PI.Limit_Switch_CW; 
      =     DBX [AR1,P#15.0]; //SEW_SBP_Daten.SWITCH_max
//Endschalter Links
      U     #PI.Limit_switch_CCW; 
      =     DBX [AR1,P#15.1]; //SEW_SBP_Daten.SWITCH_min
//Warnung
      U     #PI.Inverter_ready; 
      U     #PI.Error; 
      =     DBX [AR1,P#14.2]; //SEW_SBP_Daten.WARNING_OF_AXIS
//Fehler
      UN    #PI.Inverter_ready; 
      U     #PI.Error; 
      =     DBX [AR1,P#14.1]; //SEW_SBP_Daten.FAULT_OF_AXIS
//Fehler vorhanden???
      U     #PI.Error; 
      SPB   EL; 
//Kein Fehler "0" laden
      L     0; 
      SPA   ENR; 
//Fehler vorhanden und Rangieren
EL:   L     #PI.Status; 
ENR:  T     DBW [AR1,P#16.0]; //SEW_SBP_Daten.FAULT_NO
NETWORK
TITLE =Prozeßausgangsdaten aufbereiten und rangieren
//Freigabe - /Schnellstopp rangieren
      U     DBX [AR1,P#2.0]; //SEW_SBP_Daten.ENABLE_RAPID_STOP
      =     #PO.Rapid_stop; 
//Tippen plus angewählt
      U     DBX [AR1,P#2.2]; //SEW_SBP_Daten.JOG_PLUS_MODE
      UN    DBX [AR1,P#2.3]; //SEW_SBP_Daten.JOG_MINUS_MODE
      UN    DBX [AR1,P#2.4]; //SEW_SBP_Daten.REF_TRAVEL_MODE
      UN    DBX [AR1,P#2.5]; //SEW_SBP_Daten.POSITIONING_MODE
      =     #PO.Jog_plus; 
//Tippen minus angewählt
      UN    DBX [AR1,P#2.2]; //SEW_SBP_Daten.JOG_PLUS_MODE
      U     DBX [AR1,P#2.3]; //SEW_SBP_Daten.JOG_MINUS_MODE
      UN    DBX [AR1,P#2.4]; //SEW_SBP_Daten.REF_TRAVEL_MODE
      UN    DBX [AR1,P#2.5]; //SEW_SBP_Daten.POSITIONING_MODE
      =     #PO.Jog_minus; 
//Referenzieren angewählt
      UN    DBX [AR1,P#2.2]; //SEW_SBP_Daten.JOG_PLUS_MODE
      UN    DBX [AR1,P#2.3]; //SEW_SBP_Daten.JOG_MINUS_MODE
      U     DBX [AR1,P#2.4]; //SEW_SBP_Daten.REF_TRAVEL_MODE
      UN    DBX [AR1,P#2.5]; //SEW_SBP_Daten.POSITIONING_MODE
      =     #Ref; 
//Positionieren angewählt
      UN    DBX [AR1,P#2.2]; //SEW_SBP_Daten.JOG_PLUS_MODE
      UN    DBX [AR1,P#2.3]; //SEW_SBP_Daten.JOG_MINUS_MODE
      UN    DBX [AR1,P#2.4]; //SEW_SBP_Daten.REF_TRAVEL_MODE
      U     DBX [AR1,P#2.5]; //SEW_SBP_Daten.POSITIONING_MODE
      =     #Merker; 
      U     #Merker; 
      U     #PI.referenced; 
      =     #Pos; 
      U     #Merker; 
      UN    #PI.referenced; 
      =     DBX [AR1,P#14.5]; //SEW_SBP_Daten.NOT_REFERENCED 
//Software Endschalter freifahren
      U     #PI.Motor_turning; 
      SPB   SWES; 
      SET   ; 
      U     DBX [AR1,P#2.5]; //SEW_SBP_Daten.SOFT_SWITCH_RELEASE
      =     #PO.SWES; 
SWES: NOP   0; 
//Anwahl "mode_low"
      O     #PO.Jog_plus; 
      O     #PO.Jog_minus; 
      O     #Pos; 
      =     #PO.mode_low; 
//Halteregelung
      UN    #PO.mode_low; 
      UN    #Ref; 
      =     #PO.hold; 
//Anwahl "Mode high"
      O     #Ref; 
      O     #Pos; 
      =     #PO.mode_high; 
//Freigabe - /Halt via Feldbus
      U     #PO.Rapid_stop; 
      =     #PO.Stop; 
      UN    #Merker; 
      =     DBX [AR1,P#14.4]; //SEW_SBP_Daten.AXIS_INTERLOCKED
//Fault_Reset
      U     DBX [AR1,P#2.1]; //SEW_SBP_Daten.RESET
      =     #PO.Reset_fault; 
//Start Freigabe
      U     #PI.Brake_released; 
      =     #PO.start; 
//Rücksetzen aller nicht verwendeten Steuerwort-Bits
      SET   ; 
      R     #PO.Contr_inhibit; 
      R     #PO.Ramp; 
      R     #PO.Para; 
      R     #PO.CTW_Bit_13; 
      R     #PO.CTW_Bit_14; 
      R     #PO.SWES; 
//Sollwerte übertragen
      L     DBD [AR1,P#4.0]; //SEW_SBP_Daten.Job.SETPOINT_POS
      T     #PO.Setpoint_position; 
      L     DBW [AR1,P#8.0]; //SEW_SBP_Daten.SETPOINT_SPEED
      T     #PO.Setpoint_speed; 
      L     DBW [AR1,P#10.0]; //SEW_SBP_Daten.START_RAMP
      T     #PO.Start_ramp; 
      L     DBW [AR1,P#12.0]; //SEW_SBP_Daten.STOP_RAMP
      T     #PO.Stop_ramp; 
NETWORK
TITLE =Daten zum Umrichter schreiben
//Ausgangsdaten an FU schreiben
      CALL "DPWR_DAT" (
           LADDR                    := #Peripherie,
           RECORD                   := #PO,
           RET_VAL                  := #RET_VAL_SFC15);
//Adressregister wieder herstellen
      LAR1  #Daten.Adresse; 
//Fehlerauswertung "an FU schreiben"
      L     #RET_VAL_SFC15; 
      L     0; 
      <>I   ; 
      SPB   ERR; 
      SET   ; 
      =     DBX [AR1,P#14.0]; //SEW_SBP_Daten.COMMUNICATION_OK
//Baustein Beenden "Kein Fehler"
      BEA   ; 
NETWORK
TITLE =Kommunikationsfehler auswerten
ERR:  L     0; 
      T     DBW [AR1,P#16.0]; //SEW_SBP_Daten.FAULT_NO
      T     DBD [AR1,P#18.0]; //SEW_SBP_Daten.ACTUAL_POSITION
      T     DBW [AR1,P#22.0]; //SEW_SBP_Daten.ACTUAL_SPEED
      T     DBW [AR1,P#24.0]; //SEW_SBP_Daten.ACTUAL_CURRENT
      T     DBW [AR1,P#26.0]; //SEW_SBP_Daten.ACTUAL_DEVICE_UTILISTION
      SET   ; 
      R     DBX [AR1,P#14.0]; //SEW_SBP_Daten.COMMUNICATION_OK
      R     DBX [AR1,P#14.1]; //SEW_SBP_Daten.FAULT_OF_AXIS
      R     DBX [AR1,P#14.2]; //SEW_SBP_Daten.WARNING_OF_AXIS
      R     DBX [AR1,P#14.3]; //SEW_SBP_Daten.INVERTER_READY
      R     DBX [AR1,P#14.4]; //SEW_SBP_Daten.AXIS_INTERLOCKED
      R     DBX [AR1,P#14.5]; //SEW_SBP_Daten.NOT_REFERENCED
      R     DBX [AR1,P#14.6]; //SEW_SBP_Daten.REFERNCED
      R     DBX [AR1,P#14.7]; //SEW_SBP_Daten.TARGET_POS_REACHED  
END_FUNCTION
```


----------



## rostiger Nagel (13 Februar 2010)

hier der UDT

```
TYPE "SEW_SBP_Daten"
TITLE =Daten SEW-Servo:  Erweiterte Buspositonierung
VERSION : 0.1
 
  STRUCT  
   DRIVE_IO_ADDRESS : INT ; //Umrichter Adresse
   ENABLE_RAPID_STOP : BOOL ; //Freigabe - /Schnellstop
   RESET : BOOL ; //Reset
   JOG_PLUS_MODE : BOOL ; //Tippen Plus
   JOG_MINUS_MODE : BOOL ; //Tippen Minus
   REF_TRAVEL_MODE : BOOL ; //Referenzfahrt
   POSITIONING_MODE : BOOL ; //Positonierung
   SOFT_SWITCH_RELEASE : BOOL ; //Software Endschalter freifahren
   Job : STRUCT  //Auftrag
    SETPOINT_POS : DINT ; //Soll-Position
    SETPOINT_SPEED : INT ; //Soll-Geschwindigkeit
    START_RAMP : INT ; //Hochlaufzeit
    STOP_RAMP : INT ; //Tieflaufzeit
   END_STRUCT ; 
   COMMUNICATION_OK : BOOL ; //SFC14/SFC15: Return Value = 0
   FAULT_OF_AXIS : BOOL ; //Fehler
   WARNING_OF_AXIS : BOOL ; //Warnung
   INVERTER_READY : BOOL ; //Umrichter Bereit
   AXIS_INTERLOCKED : BOOL ; //die Modeanwahl ist unplausibel (kein Mode oder mehrere Modi angewählt)
   NOT_REFERENCED : BOOL ; //Mode Positioning angewählt, obwohl die Achse nicht referenziert ist
   REFERNCED : BOOL ; //Achse ist Referenziert
   TARGET_POS_REACHED : BOOL ; //Ziel Position erreicht
   SWITCH_max : BOOL ; //Endlage max angefahren
   SWITCH_min : BOOL ; //Endlage min angefahren
   FAULT_NO : INT ; //Fehler Nr
   ACTUAL_POSITION : DINT ; //Aktuelle Position
   ACTUAL_SPEED : INT ; //Aktuelle Geschwindigkeit
   ACTUAL_CURRENT : INT ; //Aktueller Motorstrom
   DEVICE_UTILISATION : INT ; //Aktuelle Geräteauslastung
  END_STRUCT ; 
END_TYPE
```


----------



## smartie (13 Februar 2010)

Hallo Helmut,

fast richtig getippt, ist zwar von SEW aber Moviaxis. 

Vielen Dank für dein Beispiel.

Im Prinzip ist mir das schon klar, aber wenn ich es richtig verstehe entspricht dein FC jeweils einem meiner FB´s.
Du steuers doch mit dem einen FC einen Servo und verwendest dann nur einmal die SFC14 / SFC15 für diesen einen Servo.

Aber letzten endes machst du doch auch nichts anderes als die Daten vom
Servo in einen DB zu transferieren und liest sie dann da wieder aus.

Oder verstehe ich da was falsch?

Für mein Projekt benötige ich 8 FB´s für einen Servo die insgesamt etwa 50 Ausgänge haben.
Wenn ich das nun in einem FB oder auch FC machen würde wäre der ja riesig?

Insgesamt habe ich übrigens 4 Servoachsen.

Gruß smartie


----------



## rostiger Nagel (13 Februar 2010)

Wie sieht das den aus mit deinen Moviaxis, hast du einen zusammen-
hängenden Peripehriebereich für alle Achsen?
Oder für jede Achse einen einzelnen Peripehriebereich.


----------



## smartie (13 Februar 2010)

Im Moment habe ich je Achse 15 Wörter einzeln.

Ich könnte aber auch 60 Wörte zusämmenhängend zusammenhängend lesen bzw. schreiben.

Ich finde halt je Achse einen Peripheriebereich einfach übersichtlicher.


----------



## rostiger Nagel (13 Februar 2010)

ja ist doch gut so, jetzt kannst du doch für jede achse ein FB
oder einen FC machen. Und dann da nur für diese Achse die 
Daten übertragen.

Wenn du jetzt z.b. mein Beispiel nimmst, legst du einen FB an
in diesen FB Deklariest du für jede Achse einmal den UDT dann
fütterst im FB die Achsen mit Daten und rufst dann für jede
Achse den FC auf.


----------



## smartie (13 Februar 2010)

Ok, ich habe mir jetzt die "Mühe"  gemacht deinen Code mal als Quelle zu importieren und sehe das ich den Code wohl doch eher falsch verstanden habe.

Ich habe jetzt FC2 in meinem Programm, dass ist dein FC.

Der benötigt nun einen Datenzeiger. 
Hier muss nun wohl die Adresse des DB mit dem UDT angegeben werden.

Soweit verstehe ich es noch. Problematisch wirds nun mit dem UDT.
UDT habe ich bisher noch nicht verwendet.

Ich habe einen DB angelegt in dem ich eine Variable vom Typ UDT1 angelegt habe.
Ich hoffe das ist richtig so?

Aber nun komm ich nicht weiter. Wie beschreibe ich denn nun meinen Datenbaustein?
Vor allem weiß ich nicht wie ich denn nun die IO Adresse angebe.

Und meine FB´s müssen ja auch noch die Daten vom Servo bekommen,
ich will ja in jedem FB alle Informationen vom Servo haben.


----------



## rostiger Nagel (13 Februar 2010)

hier ein Beispiel wie ich es mit Instanzen in einen FB gemacht habe,
eigentlich brauchst du das nur erweitern und anpassen.
Unter VAR steht der UDT jeweils für jede Achse, die Daten stehen
später in den zugehörigen Instanzdatenbaustein.



```
FUNCTION_BLOCK "Movieaxis"
TITLE =Movieaxies
VERSION : 0.1
 
VAR
  Achse_1 : "SEW_SBP_Daten"; 
  Achse_2 : "SEW_SBP_Daten"; 
  Achse_3 : "SEW_SBP_Daten"; 
  Achse_4 : "SEW_SBP_Daten"; 
END_VAR
BEGIN
NETWORK
TITLE =Achse 1
//I_O Adresse stellen
      L     256; 
      T     #Achse_1.DRIVE_IO_ADDRESS; 
//Achse Vorwärts tippen
      U     M     10.0; 
      =     #Achse_1.JOG_PLUS_MODE; 
//Bausteinaufruf
      CALL "SEW_SBP" (
           Daten_Zeiger             := #Achse_1);
NETWORK
TITLE =Achse 2
//I_O Adresse stellen
      L     272; 
      T     #Achse_2.DRIVE_IO_ADDRESS; 
//Achse Vorwärts tippen
      U     M     11.0; 
      =     #Achse_2.JOG_PLUS_MODE; 
//Bausteinaufruf
      CALL "SEW_SBP" (
           Daten_Zeiger             := #Achse_2);
END_FUNCTION_BLOCK
```


----------



## rostiger Nagel (13 Februar 2010)

Smartie,
in den Beispiel sind alle Achsen in einen FB und einen Instanz DB.
Du kannst natürlich jetzt für jede Achse auch einen eigenen FB
mit Aufruf erzeugen. Oder einen Global DB machen wo die Daten von
den Achsen drinstehen.

Die Beispiele sind nur eine Hilfe und ein wenig zum Nachdenken anregen.


----------



## smartie (13 Februar 2010)

Ok, jetzt wirds langsam deutlicher. 

Der FC2 der die Kommunikation mit der Achse steuert wird in jedem *FB* aufgerufen.

Was du ja vorhin schon geschrieben hast (ich aber leider nicht so ganz verstanden habe):


> Wenn du jetzt z.b. mein Beispiel nimmst, legst du einen FB an in diesen FB Deklariest du für jede Achse einmal den UDT dann
> fütterst im FB die Achsen mit Daten und rufst dann für jede Achse den FC auf.



Ich glaube aber ich hab jetzt so langsam mal kapiert wie es gehen könnte.

Gruß smartie


----------



## rostiger Nagel (13 Februar 2010)

Aber bitte beachte das du den FC nur *einmal* für jede Achse aufrufst.
Sonst ist in etwas wie eine Doppel zuweisung von einen Ausgang, hier
ein Beispiel wie ich das meinen.


```
U E 0.0
= A 1.0
 
U E 0.1
= A 1.0
```
 
in diesen Beispiel kann der Ausgang nur über E 0.1 gesetzt werden
der Eingang E 0.0 hat keine auswirkung.


----------



## smartie (13 Februar 2010)

Schon klar.

Ich würde dann jetzt einen FB schreiben der die Kommunikation mit den Achsen handelt (und die Daten in die 4 DB´s mit dem UDT schreibt).

In meinen FB´s die die Funktionen der Achsen steuern greife ich dann auf die Daten aus den 4 DB´s zu.

Ich denke so müsste es doch gehen, oder?


----------



## rostiger Nagel (13 Februar 2010)

wunderbar....


----------



## smartie (13 Februar 2010)

Puh, schwere Geburt.

Aber mal was gunrundsätzliches zum Thema UDT:

Wennn ich einen Datenbaustein anlege und als Variable den Typ UDT festlege
dann sieht man ja wenn man diesen DB öffnet nur die eine Variable vom Typ UDT.

Wenn man dann also später mal wissen will was in diesem DB so alles steht dann muss man also noch zusätzlich den UDT öffnen.

Ist das richtig so oder geht das auch einfacher?

Gruß smartie


----------



## rostiger Nagel (13 Februar 2010)

du kannst die Ansicht umschalten unter den Menü Ansicht,
zwischen Deklarationsicht und Datensicht.
In der Datensicht siehst du es dann aufgelöst. Beim Deklarieren
ist es ganz angenehm, die UDT nicht aufgelöst zu sehen, so 
ist der Baustein übersichtlicher.


----------



## smartie (13 Februar 2010)

Hi,

ich habe jetzt einen FC erstellt der die Daten von einem Servo liest und in einen DB (mit einem UDT) transferiert.

Das funktioniert auch sehr gut.

Jetzt will ich den ersten FB für den Servo schreiben.

Dazu brauche ich nun wieder die Daten vom Servo aus dem DB.

Wie beim FC habe ich wieder einen Datenzeiger der die Daten aus dem DB an den FB übergibt.

Ich behaupte mal ich habe alles richtig gemacht, klappt aber nicht. 

Hier mal der Code meines FB


```
[B]Netzwerk 1[/B]
  
      L     P##Daten_Zeiger             // Datenzeiger in AKKU 1 laden
      LAR1                              //  AR1 mit Inhalt von AKKU 1 laden

      L     W [AR1,P#4.0]               // DB Nummer in AKKU 1 laden
      T     #Daten.DB_Nr                // Inhalt von AKKU 1 nach TEMP kopieren

      L     D [AR1,P#6.0]               // Adresse in AKKU 1 laden
      T     #Daten.Adresse              // Inhalt von AKKU 1 nach TEMP kopieren

[B]Netzwerk 2[/B]

      AUF   DB [#Daten.DB_Nr]           // DB Nummer mit Inhalt aus TEMP öffnen
      LAR1  #Daten.Adresse              // AR1 mit Inhalt von AKKU 1 laden

[B]Netzwerk 3[/B]

      U     #MX1.PI.Betriebsart_24V
      =     #AKTIV
```
Der Aufruf dazu sieht so aus:


```
CALL  FB     1 , DB111
       Daten_Zeiger       :="MX1".DB_VAR
       AKTIV              :=M0.1
```
In dem Datenbaustein MX1 ist das entsprechende Bit PI.Betriebsart_24V gesetzt. Aber das Bit M0.1 wird nicht HIGH.

Woran kann das liegen?


----------



## smartie (13 Februar 2010)

Ok also jetzt ist mir auf jeden Fall klar warum das nicht funktioniert.

Ich muss natürlich auch in dem FB alle meine Daten aus dem DB manuell auf die temporären Variablen zuweisen.
- BLKMOV funktioniert da nicht.

Ist doch richtig so? - Find ich nämlich schon recht umständlich ..

smartie


----------



## rostiger Nagel (13 Februar 2010)

Du hast ein FB genommen da musst du natürlich
mit den Adressregistern aufpassen. 
Warum machst du das so, endweder du nimmst ein
FC und legst die Daten global an oder einen FB und
erzeugst eine Instanz und holst dir die Daten aus der
direkt im FB aus der Instanz.


----------



## Larry Laffer (14 Februar 2010)

Hallo,
ich muß / möchte hier noch einmal auf den Beitrag #1 von Smartie zurückkommen ...
Aus meiner Sicht spricht gar nichts dagegen, für jede Achse (oder was auch immer) einen eigenen FB zu machen - das mache ich auch grundsätzlich immer so. Auch ein mehrfaches Aufrufen der SFC14 und 15 sollte kein Problem darstellen.
Im Grundsatz sollte der ursprüngliche Baustein also funktionieren.
Was mich hier jetzt interessiert ist : wo ist denn der Datenbereich PI und PO deklariert ? Ich hoffe nicht im Bereich TEMP sondern doch ganz bestimmt im Bereich STAT des FB ...

Gruß
LL


----------



## SPSKILLER (14 Februar 2010)

ja. ist im stat bereich. Steht als Kommentar da (#1)


----------



## smartie (14 Februar 2010)

Hallo zusammen,

wie SPS Killer schon bemerkt hat sind PI und PO nicht im TEMP sondern im STAT Bereich definiert.

@ Larry Laffer:
Du sagst du hast das schon öfter so realisiert. - Hast du vielleicht ein Beispiel für mich?

@ Helmut:

Ich habe einen FC zur Kommunikation mit jeweils einer Achse erstellt.
Die FB's sind für die einzelnen Betriebsarten der Achsen.
Aber irgendwie muss ich doch die Daten aus dem DB in den FB bekommen.

Ich hoffe ich nerv euch nicht zu sehr damit, aber das ist schon ne Menge neues für mich.

Gruß smartie


----------



## smartie (14 Februar 2010)

@ Larry Laffer:
Im übrigen habe ich insgesamt 8 FB's je Achse die jeweils einen Aufruf der SFC14 / 15 haben.


----------



## rostiger Nagel (15 Februar 2010)

@Larry Laffer,
ich stimme dir auf jedem fall zu das man die SFC14/15 öfter aufrufen
kann. Bei Smartie sieht allerdings so aus, das er dieses für jede Betriebs-
art macht (wie ich aus Beitrag #3 lese) ich denke mal das er dieses aber
nicht gegeneinander veriegelt. Ich glaube er schreibt etwas in der ersten
Betriebsart etwas rein und macht es weiter unten mit einer anderen Betriebs-
art wieder platt.
Deswegen war mein Tip nur einmal an den Teilnehmer zu schreiben und
in die Betriebsarten separat zu sehen.
Aber Smartie hält sich auch Vornehm zurück mit entsprechenden Informationen 
bzw. Code.

@Smartie,
um dir weiter helfen zu können stell doch mal mehr von deinen Programm
hier rein damit wir überhaubt sehen können wo es hackt.


----------



## Larry Laffer (15 Februar 2010)

... sieh mal an ... da ist der Helmut wieder etwas schneller gewesen ...

@Smartie:
Auif die Schnelle finde ich jetzt keinen Beispiel-Baustein - das bringt uns m.E. aber auch nicht wirklich weiter. Ich sehe das genau wie Helmut und würde auch sagen, dass es sinnig ist, deinen ganzen Baustein zu kennen und nicht nur den Auszug der ersten Zeilen (wenn das denn überhaupt so aussieht). Diese Zeilen könnten auch in einem meiner Bausteine so drin stehen.
Was dir schon zu denken geben sollte ist, dass dir der / die SFC keinen Fehler melden - die sind damit nämlich eigentlich nicht kleinlich. 

Gruß
LL


----------



## smartie (15 Februar 2010)

Guten Morgen,

*FC10 - MX1 Steuern*



> FUNCTION FC 10 : VOID
> TITLE =
> VERSION : 0.1
> 
> ...


*

FC1 - MOVIAXIS1*


```
FUNCTION FC 1 : VOID
TITLE =
AUTHOR : HO
FAMILY : SEW
NAME : BUS_POSI
VERSION : 0.1


VAR_INPUT
  Daten_Zeiger : ANY ;    //Zeiger Ablage Daten für die Achse
  IO_Adresse : INT ;    
END_VAR
VAR_OUTPUT
  FEHLER_SFC : BOOL ;    
END_VAR
VAR_TEMP
  Daten : STRUCT     //Zeiger für DB und Adresse der Anzeige
   DB_Nr : INT ;    //Anzeige-DB Nr
   Adresse : DWORD ;    //Anzeige Start-Adresse im DB
  END_STRUCT ;    
  Peripherie : WORD ;    //Peripherie-Zeiger Umrichter
  RET_VAL_SFC14 : INT ;    //Rückgabe vom DP lesen
  RET_VAL_SFC15 : INT ;    //Rückgabe zum DP schreiben
  MX1 : UDT 1;    
  test : BOOL ;    
END_VAR
BEGIN
NETWORK
TITLE =Adresse von INT nach Word wandeln

      L     #IO_Adresse; 
      T     #Peripherie; 
      NOP   0; 
NETWORK
TITLE =Daten vom Umrichter lesen
//#MX1.PI
      CALL SFC   14 (
           LADDR                    := #Peripherie,
           RET_VAL                  := #RET_VAL_SFC14,
           RECORD                   := #MX1.PI);
      NOP   0; 
NETWORK
TITLE =Daten zum Umrichter schreiben

      CALL SFC   15 (
           LADDR                    := #Peripherie,
           RECORD                   := #MX1.PO,
           RET_VAL                  := #RET_VAL_SFC15);
      NOP   0; 
NETWORK
TITLE =Fehlerauswertung SFC

      O(    ; 
      L     #RET_VAL_SFC15; 
      L     0; 
      <>I   ; 
      )     ; 
      O(    ; 
      L     #RET_VAL_SFC14; 
      L     0; 
      <>I   ; 
      )     ; 
      =     #FEHLER_SFC; 
NETWORK
TITLE =Test

      U     #MX1.PI.Betriebsart_24V; 
      =     #test; 
NETWORK
TITLE =Datenzeiger auftrennen

      L     P##Daten_Zeiger; // Datenzeiger in AKKU 1 laden
      LAR1  ; //  AR1 mit Inhalt von AKKU 1 laden

      L     W [AR1,P#4.0]; // DB Nummer in AKKU 1 laden
      T     #Daten.DB_Nr; // Inhalt von AKKU 1 nach TEMP kopieren

      L     D [AR1,P#6.0]; // Adresse in AKKU 1 laden
      T     #Daten.Adresse; // Inhalt von AKKU 1 nach TEMP kopieren

NETWORK
TITLE =Datenbaustein aufschlagen

      AUF   DB [#Daten.DB_Nr]; // DB Nummer mit Inhalt aus TEMP öffnen
      LAR1  #Daten.Adresse; // AR1 mit Inhalt von AKKU 1 laden
NETWORK
TITLE =Daten aus #PI in Zwischenspeicher DB kopieren

      U     #MX1.PI.FU_freigegeben; 
      =     DBX [AR1,P#3.1]; 

      U     #MX1.PI.Betriebsart_24V; 
      =     DBX [AR1,P#3.4]; 



NETWORK
TITLE =Daten aus Zwischenspeicher DB in #PO kopieren


      U     DBX [AR1,P#32.1]; 
      =     #MX1.PO.Freigabe_Schnellstop; 


      U     DBX [AR1,P#32.2]; 
      =     #MX1.PO.Freigabe_Halt; 

END_FUNCTION
```


----------



## smartie (15 Februar 2010)

Weiter gehts:

FB2 - MX Referenzieren (zum Testen erst mal nur "ACHSE FREIGEBEN")


```
VAR
  MX1 : UDT 1;    
END_VAR
VAR_TEMP
  Daten : STRUCT     //Zeiger für DB und Adresse der Anzeige
   DB_Nr : INT ;    //Anzeige-DB Nr
   Adresse : DWORD ;    //Anzeige Start-Adresse im DB
  END_STRUCT ;    
END_VAR
BEGIN
NETWORK
TITLE =Datenzeiger auftrennen

      L     P##Daten_Zeiger; // Datenzeiger in AKKU 1 laden
      LAR1  ; //  AR1 mit Inhalt von AKKU 1 laden

      L     W [AR1,P#4.0]; // DB Nummer in AKKU 1 laden
      T     #Daten.DB_Nr; // Inhalt von AKKU 1 nach TEMP kopieren

      L     D [AR1,P#6.0]; // Adresse in AKKU 1 laden
      T     #Daten.Adresse; // Inhalt von AKKU 1 nach TEMP kopieren

NETWORK
TITLE =Datenbaustein aufschlagen

      AUF   DB [#Daten.DB_Nr]; // DB Nummer mit Inhalt aus TEMP öffnen
      LAR1  #Daten.Adresse; // AR1 mit Inhalt von AKKU 1 laden
NETWORK
TITLE =Daten aus Zwischenspeicher DB in FB transferieren

      U     DBX [AR1,P#3.4]; 
      =     #MX1.PI.Betriebsart_24V; 

      U     DBX [AR1,P#3.1]; 
      =     #MX1.PI.FU_freigegeben; 

NETWORK
TITLE =Daten aus FB in Zwischenspeicher DB kopieren

      U     #MX1.PO.Freigabe_Schnellstop; 
      =     DBX [AR1,P#32.1]; 

      U     #MX1.PO.Freigabe_Halt; 
      =     DBX [AR1,P#32.2]; 


NETWORK
TITLE =



NETWORK
TITLE =Achse freigeben

      U     #REFERENZIEREN_START; 
      =     #MX1.PO.Freigabe_Schnellstop; 
      =     #MX1.PO.Freigabe_Halt; 
NETWORK
TITLE =Rückmeldung : Betriebsart 24V (400V Versorung fehlt)

      U     #MX1.PI.Betriebsart_24V; 
      =     #AKTIV; 
NETWORK
TITLE =Rückmeldung : FU freigegeben

      U     #MX1.PI.FU_freigegeben; 
      =     #FERTIG; 

NETWORK
TITLE =



END_FUNCTION_BLOCK
```
UDT1


```
TYPE UDT 1
VERSION : 0.1


  STRUCT     
   IO_ADRESSE : INT ;    //IO-Adresse des Antriebs
   PI : STRUCT     
    Motor_steht : BOOL ;    //Statuswort : Motor steht
    Antrieb_betriebsbereit : BOOL ;    //Statuswort : Antrieb ist betriebsbereit
    Antrieb_referenziert : BOOL ;    //Statuswort : Antrieb ist referenziert
    Reserve_1 : BOOL ;    //Statuswort : Reserve
    Bremse_offen : BOOL ;    //Statuswort : Bremse ist offen (falls vorhanden)
    Fehler_FU : BOOL ;    //Statuswort : Fehler Frequenzumrichter
    Warnung_FU : BOOL ;    //Statuswort : Warnung Frequenzumrichter
    Fehler_IEC : BOOL ;    //Statuswort : Fehler MotionController
    Kommunikation_aufgebaut : BOOL ;    //Statuswort : Kommunikation (PLC <> MX) aufgebaut
    FU_freigegeben : BOOL ;    //Statuswort : Frequenzumrichter freigegeben
    Synchron : BOOL ;    //Statuswort : Synchron (zur Interpolierten Lageregelung)
    Sicherer_Halt : BOOL ;    //Statuswort : Sicherer Halt
    Betriebsart_24V : BOOL ;    //Statuswort : Betriebsart 24V (400V Versorgung fehlt)
    Prozessdaten_nicht_breit : BOOL ;    //Statuswort : Prozessdaten nicht bereit
    Reserve : BOOL ;    //Statuswort : Reserve
    SW_Endschalter_belegt : BOOL ;    //Statuswort : Software-Endschalter belegt
    AM_Referenzieren : BOOL ;    //Angewählter AxisMode : Referenzieren
    AM_Drehzahlregelung : BOOL ;    //Angewählter AxisMode : Drehzahlregelung
    AM_Pos_Abs : BOOL ;    //Angewählter AxisMode : Positionieren Absolut
    AM_Pos_Rel : BOOL ;    //Angewählter AxisMode : Positionieren Relativ
    AM_Tippen : BOOL ;    //Angewählter AxisMode : Tippen
    AM_Kurvenscheibe : BOOL ;    //Angewählter AxisMode : Kurvenscheibe
    AM_Synchronlauf : BOOL ;    //Angewählter AxisMode : Synchronlauf
    AM_Reserve : BOOL ;    //Angewählter AxisMode : Reserve
    AM_Referenzieren_fertig : BOOL ;    //AxisMode : Referenzieren fertig
    AM_Drehzahl_erreicht : BOOL ;    //AxisMode : Drehzahl erreicht
    AM_Pos_Abs_inP : BOOL ;    //AxisMode : Positioneren Absolut - In Position
    AM_Pos_Rel_inP : BOOL ;    //AxisMode : Positioneren Relativ - In Position
    AM_Tippen_Sollgeschw_err : BOOL ;    //AxisMode : Tippen - Sollgeschwindigkeit erreicht
    AM_Reserve_1 : BOOL ;    //AxisMode : Reserve
    AM_Reserve_2 : BOOL ;    //AxisMode : Reserve
    AM_Reserve_3 : BOOL ;    //AxisMode : Reserve
    AM_Referenzieren_stop : BOOL ;    //AxisMode : Referenzieren gestoppt
    AM_Drehzahlregelung_stop : BOOL ;    //AxisMode : Drehzahlregelung gestoppt
    AM_Pos_Abs_stop : BOOL ;    //AxisMode : Positionieren Absolut gestoppt
    AM_Pos_Rel_stop : BOOL ;    //AxisMode : Positionieren Relativ gestoppt
    AM_Tippen_stop : BOOL ;    //AxisMode : Tippen gestoppt
    AM_Kurvenscheibe_stop : BOOL ;    //AxisMode : Kurvenscheibe gestoppt
    AM_Synchronlauf_stop : BOOL ;    //AxisMode : Synchronlauf gestoppt
    AM_Reserve_4 : BOOL ;    //AxisMode : Reserve
    Akt_AM_Referenzieren : BOOL ;    //Axis Mode : Referenzieren - Aktiv
    Akt_AM_Drehzahlregelung : BOOL ;    //Axis Mode : Drehzahlregelung - Aktiv
    Akt_AM_Pos_Abs : BOOL ;    //Axis Mode : Positionieren Absolut - Aktiv
    Akt_AM_Pos_Rel : BOOL ;    //Axis Mode : Positionieren Relativ - Aktiv
    Akt_AM_Tippen : BOOL ;    //Axis Mode : Tippen - Aktiv
    Akt_AM_Kurvenscheibe : BOOL ;    //Axis Mode : Kurvenscheibe - Aktiv
    Akt_AM_Synchronlauf : BOOL ;    //Axis Mode : Synchronlauf - Aktiv
    Akt_AM_Reserve_1 : BOOL ;    //Axis Mode : Reserve
    Umrichterstatus : WORD ;    //Umrichterstatus
    Ist_Geschwindigkeit : WORD ;    //Ist-Geschwindigkeit
    Ist_Drehzahl : WORD ;    //Ist-Drehzahl
    Ist_Position_Anwender : DWORD ;    //Ist-Position in Anwendereinheit
    Ist_Position_Modulo : DWORD ;    //Ist-Position in Modulo
    IEC_Fehlernummer : WORD ;    //IEC Fehlernummer
    IEC_Subfehlernummer : WORD ;    //IEC Subfehlernummer
    FU_Fehlernummer : WORD ;    //Frequenzumrichter Fehlernummer
    FU_Subfehlernummer : WORD ;    //Frequenzumrichter Subfehlernummer
    Ist_Drehmoment : WORD ;    //Ist-Drehmoment
   END_STRUCT ;    
   PO : STRUCT     
    Reglersperre : BOOL ;    //Reglersperre
    Freigabe_Schnellstop : BOOL ;    //Freigabe/Schnellstop
    Freigabe_Halt : BOOL ;    //Freigabe/Halt
    Reserve_1 : BOOL ;    //Reserve
    Bremse_oeffnen : BOOL ;    //Bremse öffnen (falls vorhanden)
    Reserve_2 : BOOL ;    //Reserve
    Reset : BOOL ;    //Reset
    Reserve_3 : BOOL ;    //Reserve
    Reserve_4 : BOOL ;    //Reserve
    Tippen_Pos : BOOL ;    //Tippen Positiv
    Tippen_Neg : BOOL ;    //Tippen Negativ
    Reserve_5 : BOOL ;    //Reserve
    Reserve_6 : BOOL ;    //Reserve
    Reserve_7 : BOOL ;    //Reserve
    Reserve_8 : BOOL ;    //Reserve
    SW_Endschalter_AUS : BOOL ;    //Software-Endschalter deaktivieren
    AM_Referenzieren : BOOL ;    //Axis Mode : Referenzieren
    AM_Drehzahlregelung : BOOL ;    //Axis Mode : Drehzahlregelung
    AM_Pos_Abs : BOOL ;    //Axis Mode : Positionieren Absolut
    AM_Pos_Rel : BOOL ;    //Axis Mode : Positionieren Relativ
    AM_Tippen : BOOL ;    //Axis Mode : Tippen
    AM_Kurvenscheibe : BOOL ;    //Axis Mode : Kurvenscheibe
    AM_Synchronlauf : BOOL ;    //Axis Mode : Synchronlauf
    AM_Reserve : BOOL ;    //Axis Mode : Reserve
    STRT_Referenzieren : BOOL ;    //Axis Mode : START - Referenzieren
    STRT_Drehzahlregelung : BOOL ;    //Axis Mode : START - Drehzahlregelung
    STRT_Pos_Abs : BOOL ;    //Axis Mode : START - Positionieren Absolut
    STRT_Pos_Rel : BOOL ;    //Axis Mode : START - Positionieren Relativ
    STRT_Reserve_1 : BOOL ;    //Axis Mode : START - Reserve
    STRT_Kurvenscheibe : BOOL ;    //Axis Mode : START - Kurvenscheibe
    STRT_Synchronlauf : BOOL ;    //Axis Mode : START - Synchronlauf
    STRT_Reserve_2 : BOOL ;    //Axis Mode : START - Reserve
    Tippen_V_Soll : WORD ;    //Tippen - Sollgeschwindigkeit
    Tippen_Acc_Dec : WORD ;    //Tippen - Beschleunigung / Verzögerung
    DZR_V_Soll : WORD ;    //Drehzahlregelung - Sollgeschwindigkeit
    DZR_Acc_Dec : WORD ;    //Drehzahlregelung - Beschleunigung / Verzögerung
    Pos_Abs_V_Soll : WORD ;    //Positionieren Absolut - Sollgeschwindigkeit
    Pos_Abs_Acc_Dec : WORD ;    //Positionieren Absolut - Beschleunigung / Verzögerung
    Pos_Abs_Zielposition : DWORD ;    //Positionieren Absolut - Zielposition
    Pos_Rel_V_Soll : WORD ;    //Positionieren Relativ - Sollgeschwindigkeit
    Pos_Rel_Acc_Dec : WORD ;    //Positionieren Relativ - Beschleunigung / Verzögerung
    Pos_Rel_Distanz : DWORD ;    //Positionieren Relativ - Distanz
    Alle_BA_Ruck : WORD ;    //Alle Betriebsarten : Ruck
   END_STRUCT ;    
  END_STRUCT ;    
END_TYPE
```


----------



## smartie (15 Februar 2010)

Beschreibung:

FC10 Ist zum Steuern der Achse 1 gedacht

FC1 stellt die Kommunikation zwischen einem Antrieb und der SPS her.
Die empfangenen und zu sendenden Daten werden in den DB 1 eingetragen.

FB1 soll eigentlich das Referenzieren sein, verwende ich aber im Moment zum testen. 
Wird der Eingang #REFERENZIEREN_START gesetzt sollen die beiden Bits "Freigabe / Schnellstop" und Freigabe / Halt" gesetzt werden.

Darauf hin müsste der Antrieb das Bit "FU_freigegeben" setzten und am FB wird der Ausgang #FERTIG gesetzt.

Gruß smartie


----------



## rostiger Nagel (15 Februar 2010)

Hallo Smartie,
setzt doch auch mal bitte deinen FC1 rein.


----------



## smartie (15 Februar 2010)

Hallo Helmut,

ich habe das in Beitrag #30 geändert, ich hatte da ausversehen den FC2 (deinen Beispiel FC) hochgeladen. Jetzt ist mein FC1 hochgeladen.

smartie


----------



## rostiger Nagel (15 Februar 2010)

Gut Smartie,  
mann muß sich schon sehr anstrengen um das zu lesen,
aber wo hängt es den jetzt. Bekommst du immer noch 
nichts aus deinen Umrichter?


----------



## smartie (15 Februar 2010)

Das Problem ist nicht das ich nichts aus dem Umrichter bekomme, sondern das
zunächst (Beitrag #1) das Bit Freigabe in der SPS statisch 1 war, aber im FU getoggelt hat.

Das Problem habe ich jetzt nicht mehr.

Wenn ich jetzt die eine Achse ansteuere dann klappt alles.

Aber wenn ich eine zweite Achse dazu nehme und das Bit Freigabe Achse 1 setze dann wird nicht Achse 1 freigegeben, sondern Achse 2.

Die Rückmeldung das die Achse freigegeben ist kommt aber bei Achse 2 an, was ja richtig wäre.

Nur die Daten die ich an den Antrieb schreibe kommen falsch an..

Ich versuch mal das Programm als ZIP hochzuladen, wenn das geht.

smartie


----------



## smartie (15 Februar 2010)

So, hier das SPS-Programm als ZIP

smartie


----------



## rostiger Nagel (15 Februar 2010)

ohne das programm zu sehen, kann das denn sein das etwas
mit der I/O Adressierung der Achsen nicht stimmt ?


----------



## smartie (15 Februar 2010)

Die Adressierung müsste meine Meinung nach passen:

Wenn ich nur die Kommunikation mit Achse 1 aufrufe kommen alle Signale korrekt an.

Wenn ich nur die Kommunikation mit Achse 2 aufrufe kommen alle Signale korrekt an.

Wenn ich aber beide gleichzeitig aufrufe dann gibts Probleme.


----------



## rostiger Nagel (15 Februar 2010)

Ich kenne mich jetzt nicht mit den Moviaxis System von SEW aus,
ist das so das die Aufteilung wie folgt ist.
Steckplatz 3: Allgemeine Daten
Steckplatz 4: 1 Achse
Steckplatz 5: 2 Achse
Steckplatz 6: 3 Achse
Steckplatz 7: 4 Achse


----------



## smartie (15 Februar 2010)

Ja genau,

die ersten beiden Steckplätze müssen frei bleiben.

Der dritte Steckplatz ist für die Steuerung der Applikation in der MOVI PLC
gedacht, die folgenden Steckplätze sind für jeweils eine Achse.


----------



## rostiger Nagel (15 Februar 2010)

Also auf S7 seite kann ich jetzt nichts erkennen du hast ja wirklich
fast alles getrennt angelegt. Schon komisch.


----------



## smartie (15 Februar 2010)

Das Programm im MoviAxis ist von SEW und wir haben da am Freitag schon ziemlich lange über Fernwartung in der Steuerung gesucht,
sind aber letztlich zum Entschluss gekommen das es aus der S7 kommen muss.

Hast du dir auch nochmal das SPS-Programm angeschaut?

Ich werd jetzt auf jeden Fall noch mal bei SEW anrufen.

Das ich die SFC14 / SFC15 mehrmals für den gleichen Teilnehmer aufgerufen habe und das das falsch war ist ja ganz logisch (so im Nachhinein betrachtet).

Aber wo der Fehler jetzt liegt ??? - Keine Ahnung.


----------



## rostiger Nagel (15 Februar 2010)

aber was mir aufgefallen ist, der FC1 und FC2 sind doch gleich?
Dann kannst du die doch auch den gleichen Baustein mehrmals
aufrufen, nur mit unterschiedlicher beschaltung von ausssen.

Dann hast du doch schon deine Daten für die Achsen mit den 
FB1 Instanz DB erzeugt, das sollte doch reichen, auf diese
Daten kannst du doch zurückgreifen.

Es wirkt für mich jetzt ersteinmal ziemlich unübersichtlich.


----------



## smartie (15 Februar 2010)

Ja das mit FC1 und FC2 ist schon klar, aber eigentlich sollte das so doch auch funktionieren.

Das es etwas unübersichtlich ist liegt natürlich daran das das jetzt das Testprogramm in dem ich schon zig Änderungen durchgeführt habe.

Im Anhang lade ich mal die Variablentabelle ONLINE hoch:


----------



## rostiger Nagel (15 Februar 2010)

Eigentlich kann da nichts falsch sein wenn du den SFC 14/15 für
den gleichen Teilnehmer mehrmal aufrufst, das funktioniert auch 
bei SEW mach ich das mit den Standard Gatway doch auch und
es hängen mehrere Umrichter an diesen Gateway.


----------



## Larry Laffer (15 Februar 2010)

smartie schrieb:


> Die Adressierung müsste meine Meinung nach passen:
> 
> Wenn ich nur die Kommunikation mit Achse 1 aufrufe kommen alle Signale korrekt an.
> 
> ...


 
Ich hänge mich mal an diesen Beitrag ...
Hast du dir mal angesehen, wohin deine Pointer in Wirklichkeit adressieren ?
Kann es sein, dass es beim 2. Aufruf einen Unterschied zu dem Wunschziel gibt ?

Gruß
LL


----------



## smartie (15 Februar 2010)

Hallo Larry,



> Hast du dir mal angesehen, wohin deine Pointer in Wirklichkeit adressieren ?



Status beobachten in AWL ist für mich wie *Böhmische Dörfer*. Wie kann ich mir das ansehen?


----------



## Larry Laffer (15 Februar 2010)

... der Pointer (also das, was du ins AR1 lädst) ist der Bitwert deiner Ziel-Adresse (also Adresse * 8 ) wenn du das höchstwertigste Byte des DWORD mal außen vor läßt ...
Du weißt doch wohin du jeweils willst. Nun mußt du "nur" nachsehen, ob diese Position auch wirklich adressiert wird ...


----------



## smartie (15 Februar 2010)

Muss ganz ehrlich sagen das ich nicht ganz verstehe was du mir sagen willst.


----------



## rostiger Nagel (15 Februar 2010)

der Larry meint du sollst dir mal im Online Status anschauen wo die
Zeiger für die Adressen stehen "AR1".


----------



## Larry Laffer (15 Februar 2010)

... wenn jeder einzelne Aufruf für sich korrekt funktioniert, der 2. es aber nicht mehr tut, wenn es vorher einen anderen Aufruf gegeben hat, dann liegt für mich der Verdacht nahe, dass es da irgendeine Form der Beeinflussung gibt - diese könnte sich z.B. dadurch manifestieren, dass du zwar (z.B.) auf M100.0 zugreifen möchtest, durch deine Indexierung in Wirklichkeit aber M110.0 adressierst. Dafür war ich jetzt am "Indizien suchen" - habe aber auch so recht nichts konkretes, woran ich das festmachen kann.

Aber "by the way" ... arbeitest du jetzt mir der FC oder mit der FB-Variante ?
Wenn FB - versuch doch mal deine Daten in der Instanz des FB abzulegen statt in dem Global-DB (das ist mir sowieso suspekt ...).


----------



## rostiger Nagel (15 Februar 2010)

Larry Laffer schrieb:


> Aber "by the way" ... arbeitest du jetzt mir der FC oder mit der FB-Variante ?
> Wenn FB - versuch doch mal deine Daten in der Instanz des FB abzulegen statt in dem Global-DB (das ist mir sowieso suspekt ...).


 
Ich glaube da ein System erkannt zu haben.

Er hat die Daten Global, ladet die in ein FC um und woanders nocheinmal
in einen Instanz DB.

Den Sinn des System kann ich natürlich nicht erkennen .


----------



## smartie (15 Februar 2010)

Also ich habe jetzt mal von FC1 und FC2 online einen Bilschirmausdruck gemacht. 

(Und habe jetzt auch dank Helmuts Bildschirmausdruck geschnallt das man AR1 und AR2 durch Rechtsklick im rechten Bildschirmteil auch zum beobachten auswählen kann)


----------



## smartie (15 Februar 2010)

Was die Sache mit dem "System" betrifft, ich habe mich da schon ziemlich an Helmut´s Vorschlag orientiert (so wie ich ihn verstanden habe).

Finde es aber auch irgendwie extrem umständlich.

Da ich aber sowas bisher noch nicht wirklich oft gemacht habe (also FB´s  erstellen) habe ich auch keine Ahnung wie ich das einfacher gestalten könnte.

Aber wenn ich statt FC1 einen FB verwende dann brauche ich doch an dieser stelle keinen Datenbaustein mehr in den ich die Daten reinschreibe, sie stehen dann doch
ohnehin im InstazDB un dann wäre doch auch der Datenzeiger an diesem FB sinnlos. - Oder verstehe ich das falsch?

Den Datenzeiger bräuchte ich dann meinem Verständnis nach nur an den einzelnen FB´s für die Betriebsarten um die Daten aus dem Instanz DB in die einzelnen FB´s zu bekommen.


----------



## rostiger Nagel (15 Februar 2010)

nein Smartie das hast du nicht, leider.


----------



## smartie (15 Februar 2010)

Was hab ich nicht?

Ich bin völlig verwirrt.


----------



## rostiger Nagel (15 Februar 2010)

Ein FC den ich für unterschiedliche Achsen aufrufe, Daten Global halten.
Die Global-Daten dann in einen Globalen FB bzw. FC rangieren.


----------



## Larry Laffer (15 Februar 2010)

... da Helmut und ich dich jetzt ja so richtig schön zutexten ...

Der FB dient (für mich in erster Linie) der Kapselung einer Aufgabenstellung.
In deinem Fall :
- Einlesen der Daten des Servo's
- verarbeiten derselben mit ggf. zusätzlichen Bits über die IN-OUT-Schnittstelle
- Übergeben der Ergebnisse zum Servo
-- hierbei gilt (für mich) : Die zu übertragenden Daten bleiben erstmal in dem FB und seinem Instanz-DB. Das erspart schon mal ein bißchen Kuddelmuddel ...

... und dann das Gleiche mit dem nächsten FB und der nächsten Achse.

Wie schon geasgt ... ich vermute, dass du an irgendeiner Stelle mit den Pointer was verwurschtelst (ggf. z.B. wegen Multi-Instanz). Ich verspreche aber, dass ich später noch einmal intensiver in dein Programm hinein schaue ...


----------



## HaDi (15 Februar 2010)

Wenn im Netzwerk 3 (FC1 bzw. FC2) #MX1.PO (temp !) per SFC15 zum Umrichter übertragen wird, ohne vorher beschrieben zu werden, dann kann das (mit viel Glück) nur bei einem Umricher gut gehen.

Grüße von HaDi


----------



## smartie (15 Februar 2010)

@ Larry Laffer:

So war ja mein erster Ansatz:

Das ich also je Achse jeweils einen FB habe der alle Daten in einem InstanzDB liegen hat.

Da ich aber insgesamt 8 einzelne Funktionen je Achse habe, hätte dieser eine FB etwas 50 Äusgänge.

Weil mir das als etwas zu groß erschien wollte ich dann eben 8 einzelne FB´s je Achse machen und damit fing das Problem an.

smartie


----------



## smartie (15 Februar 2010)

@ HaDi:


> Wenn im Netzwerk 3 (FC1 bzw. FC2) #MX1.PO (temp !) per SFC15 zum Umrichter übertragen wird, ohne vorher beschrieben zu werden, dann kann das (mit viel Glück) nur bei einem Umricher gut gehen.


*Genau das war das Problem.*

Setze ich den SFC15 (Daten zum Umrichter schreiben) an das Ende der FC1 / FC2 dann funktioniert alles so wie es soll und es werden keine Bits vertauscht.

Aber jetzt muss ich trotzdem noch irgendwie eine Struktur reinbringen.

Soll ich denn jetzt für die Kommunikation mit den einzelnen Achsen einen FC oder einen FB verwenden?


----------



## Larry Laffer (15 Februar 2010)

smartie schrieb:


> Soll ich denn jetzt für die Kommunikation mit den einzelnen Achsen einen FC oder einen FB verwenden?


Das ist eigentlich Banane ... im Falle eines FB's ersparst du dir "nur" den Globaldaten-DB (oder einen vergleichbaren Speicherbereich ...
Ich persönlich finde da einen FB schöner.

Wenn du 50 Variablen auf deiner Schnittstelle hast, dann ist da irgend etwas auch noch nicht sauber ... wofür so viele Variablen ? Läßt sich da nicht noch etwas sinnvoll zusammenfassen ?

...


----------



## smartie (15 Februar 2010)

Hallo Larry,

die 50 Ausgänge pro Achse sind si schon ok.

Ich habe 7 Betriebsarten mit jeweils mindestens 3 Rückmeldungen (AKTIV, FERTIG, GESTOPPT).
Von diesen 7 Betriebsarten lassen sich 6 Stück übereinanderlegen (also gleichzeitig ansteuern) und das wird so auch benötigt.

Und dann gibt es noch einen Status FB der eben die Statusmeldungen der Achse ausgibt.


----------



## Larry Laffer (15 Februar 2010)

... das wirst du besser beurteilen können als ich ... 
Man sollte halt nur immer mal wieder drüber nachdenken ...


----------



## smartie (15 Februar 2010)

Also ich glaub ich gebs auf, ich kriegs einfach nicht hin.

Helmut oder Larry könnt ihr mir vielleicht bitte noch einmal für einen Doofi wie mich erklären wie ihr das ganze angehen würdet.

Ich erklär auch noch mal ganz kurz wie ich es mir vorstelle:

Insgesamt gibt es 4 Achsen.

Je Achse soll es 8 Funktionsbausteine für die verschiedenen Funktionen der Servos geben (Referenzieren, Tippen, Drehzahlregelung, .. Status).

Jeder der 8 einzelnen FB´s muss zu jeder Zeit aufgerufen werden können (unabhängig von den anderen).
Einen einzigen großen FB für jede Achse möchte ich ungern machen da dieser etwa 50 Äusgänge haben würde.

Die Daten von und für die einzelnen Achsen müssen per SFC14/15 auf den DP-Slave geschrieben werden.


Ich hab einfach keine Ahnung wie ich das ganze angehen soll und bin mittlerweile echt am verzweifeln. 

smartie


----------



## rostiger Nagel (15 Februar 2010)

Hallo Smartie,
meiner meinung nach solltest du einen FB machen der eine Achse,
komplett verwaltet (ähnlich den FC von mir) den du nur noch über 
die Schinttstelle die Aufträge zuteilst. Wie z.b. Tippen, Referenzieren,
Positonieren und was dir noch so einfällt.
Ich glaube nicht das die Schnittstelle so fett wird wie du befürchtest.

Diesen FB kannst du dann wieder als Instanz in den Kopf eines FB's ziehen.
In diesem FB werden dann die Aufträge an den Achs_FB zugeteilt.
So hast du später alles schön zusammen und mußt nicht immer wieder
schauen wer löst jetzt gerade irgendeine Betriebsart aus oder welche
Betriebsart ist gerade Aktiv.

Der Kopf für dein Achsbaustein könnte so aussehen als Beispiel.

```
FUNCTION_BLOCK "MX Achse"
TITLE =
VERSION : 0.1


VAR_INPUT
  IO_Adresse : WORD ;    
  Start : BOOL ;    
  Stop : BOOL ;    
  Tippen_plus : BOOL ;    
  Tippen_minus : BOOL ;    
  Ref : BOOL ;    
  Endlage_plus : BOOL ;    
  Endlage_minus : BOOL ;    
  Soll_Pos : DINT ;    
  Soll_Geschw : DINT ;    
END_VAR
VAR_OUTPUT
  Ist_Position : DINT ;    
  Ist_Geschw : DINT ;    
END_VAR
VAR
  PI : STRUCT     
   Motor_steht : BOOL ;    //Statuswort : Motor steht
   Antrieb_betriebsbereit : BOOL ;    //Statuswort : Antrieb ist betriebsbereit
   Antrieb_referenziert : BOOL ;    //Statuswort : Antrieb ist referenziert
   Reserve_1 : BOOL ;    //Statuswort : Reserve
   Bremse_offen : BOOL ;    //Statuswort : Bremse ist offen (falls vorhanden)
   Fehler_FU : BOOL ;    //Statuswort : Fehler Frequenzumrichter
   Warnung_FU : BOOL ;    //Statuswort : Warnung Frequenzumrichter
   Fehler_IEC : BOOL ;    //Statuswort : Fehler MotionController
   Kommunikation_aufgebaut : BOOL ;    //Statuswort : Kommunikation (PLC <> MX) aufgebaut
   FU_freigegeben : BOOL ;    //Statuswort : Frequenzumrichter freigegeben
   Synchron : BOOL ;    //Statuswort : Synchron (zur Interpolierten Lageregelung)
   Sicherer_Halt : BOOL ;    //Statuswort : Sicherer Halt
   Betriebsart_24V : BOOL ;    //Statuswort : Betriebsart 24V (400V Versorgung fehlt)
   Prozessdaten_nicht_breit : BOOL ;    //Statuswort : Prozessdaten nicht bereit
   Reserve : BOOL ;    //Statuswort : Reserve
   SW_Endschalter_belegt : BOOL ;    //Statuswort : Software-Endschalter belegt
   AM_Referenzieren : BOOL ;    //Angewählter AxisMode : Referenzieren
   AM_Drehzahlregelung : BOOL ;    //Angewählter AxisMode : Drehzahlregelung
   AM_Pos_Abs : BOOL ;    //Angewählter AxisMode : Positionieren Absolut
   AM_Pos_Rel : BOOL ;    //Angewählter AxisMode : Positionieren Relativ
   AM_Tippen : BOOL ;    //Angewählter AxisMode : Tippen
   AM_Kurvenscheibe : BOOL ;    //Angewählter AxisMode : Kurvenscheibe
   AM_Synchronlauf : BOOL ;    //Angewählter AxisMode : Synchronlauf
   AM_Reserve : BOOL ;    //Angewählter AxisMode : Reserve
   AM_Referenzieren_fertig : BOOL ;    //AxisMode : Referenzieren fertig
   AM_Drehzahl_erreicht : BOOL ;    //AxisMode : Drehzahl erreicht
   AM_Pos_Abs_inP : BOOL ;    //AxisMode : Positioneren Absolut - In Position
   AM_Pos_Rel_inP : BOOL ;    //AxisMode : Positioneren Relativ - In Position
   AM_Tippen_Sollgeschw_err : BOOL ;    //AxisMode : Tippen - Sollgeschwindigkeit erreicht
   AM_Reserve_1 : BOOL ;    //AxisMode : Reserve
   AM_Reserve_2 : BOOL ;    //AxisMode : Reserve
   AM_Reserve_3 : BOOL ;    //AxisMode : Reserve
   AM_Referenzieren_stop : BOOL ;    //AxisMode : Referenzieren gestoppt
   AM_Drehzahlregelung_stop : BOOL ;    //AxisMode : Drehzahlregelung gestoppt
   AM_Pos_Abs_stop : BOOL ;    //AxisMode : Positionieren Absolut gestoppt
   AM_Pos_Rel_stop : BOOL ;    //AxisMode : Positionieren Relativ gestoppt
   AM_Tippen_stop : BOOL ;    //AxisMode : Tippen gestoppt
   AM_Kurvenscheibe_stop : BOOL ;    //AxisMode : Kurvenscheibe gestoppt
   AM_Synchronlauf_stop : BOOL ;    //AxisMode : Synchronlauf gestoppt
   AM_Reserve_4 : BOOL ;    //AxisMode : Reserve
   Akt_AM_Referenzieren : BOOL ;    //Axis Mode : Referenzieren - Aktiv
   Akt_AM_Drehzahlregelung : BOOL ;    //Axis Mode : Drehzahlregelung - Aktiv
   Akt_AM_Pos_Abs : BOOL ;    //Axis Mode : Positionieren Absolut - Aktiv
   Akt_AM_Pos_Rel : BOOL ;    //Axis Mode : Positionieren Relativ - Aktiv
   Akt_AM_Tippen : BOOL ;    //Axis Mode : Tippen - Aktiv
   Akt_AM_Kurvenscheibe : BOOL ;    //Axis Mode : Kurvenscheibe - Aktiv
   Akt_AM_Synchronlauf : BOOL ;    //Axis Mode : Synchronlauf - Aktiv
   Akt_AM_Reserve_1 : BOOL ;    //Axis Mode : Reserve
   Umrichterstatus : WORD ;    //Umrichterstatus
   Ist_Geschwindigkeit : WORD ;    //Ist-Geschwindigkeit
   Ist_Drehzahl : WORD ;    //Ist-Drehzahl
   Ist_Position_Anwender : DWORD ;    //Ist-Position in Anwendereinheit
   Ist_Position_Modulo : DWORD ;    //Ist-Position in Modulo
   IEC_Fehlernummer : WORD ;    //IEC Fehlernummer
   IEC_Subfehlernummer : WORD ;    //IEC Subfehlernummer
   FU_Fehlernummer : WORD ;    //Frequenzumrichter Fehlernummer
   FU_Subfehlernummer : WORD ;    //Frequenzumrichter Subfehlernummer
   Ist_Drehmoment : WORD ;    //Ist-Drehmoment
  END_STRUCT ;    
  PO : STRUCT     
   Reglersperre : BOOL ;    //Reglersperre
   Freigabe_Schnellstop : BOOL ;    //Freigabe/Schnellstop
   Freigabe_Halt : BOOL ;    //Freigabe/Halt
   Reserve_1 : BOOL ;    //Reserve
   Bremse_oeffnen : BOOL ;    //Bremse öffnen (falls vorhanden)
   Reserve_2 : BOOL ;    //Reserve
   Reset : BOOL ;    //Reset
   Reserve_3 : BOOL ;    //Reserve
   Reserve_4 : BOOL ;    //Reserve
   Tippen_Pos : BOOL ;    //Tippen Positiv
   Tippen_Neg : BOOL ;    //Tippen Negativ
   Reserve_5 : BOOL ;    //Reserve
   Reserve_6 : BOOL ;    //Reserve
   Reserve_7 : BOOL ;    //Reserve
   Reserve_8 : BOOL ;    //Reserve
   SW_Endschalter_AUS : BOOL ;    //Software-Endschalter deaktivieren
   AM_Referenzieren : BOOL ;    //Axis Mode : Referenzieren
   AM_Drehzahlregelung : BOOL ;    //Axis Mode : Drehzahlregelung
   AM_Pos_Abs : BOOL ;    //Axis Mode : Positionieren Absolut
   AM_Pos_Rel : BOOL ;    //Axis Mode : Positionieren Relativ
   AM_Tippen : BOOL ;    //Axis Mode : Tippen
   AM_Kurvenscheibe : BOOL ;    //Axis Mode : Kurvenscheibe
   AM_Synchronlauf : BOOL ;    //Axis Mode : Synchronlauf
   AM_Reserve : BOOL ;    //Axis Mode : Reserve
   STRT_Referenzieren : BOOL ;    //Axis Mode : START - Referenzieren
   STRT_Drehzahlregelung : BOOL ;    //Axis Mode : START - Drehzahlregelung
   STRT_Pos_Abs : BOOL ;    //Axis Mode : START - Positionieren Absolut
   STRT_Pos_Rel : BOOL ;    //Axis Mode : START - Positionieren Relativ
   STRT_Reserve_1 : BOOL ;    //Axis Mode : START - Reserve
   STRT_Kurvenscheibe : BOOL ;    //Axis Mode : START - Kurvenscheibe
   STRT_Synchronlauf : BOOL ;    //Axis Mode : START - Synchronlauf
   STRT_Reserve_2 : BOOL ;    //Axis Mode : START - Reserve
   Tippen_V_Soll : WORD ;    //Tippen - Sollgeschwindigkeit
   Tippen_Acc_Dec : WORD ;    //Tippen - Beschleunigung / Verzögerung
   DZR_V_Soll : WORD ;    //Drehzahlregelung - Sollgeschwindigkeit
   DZR_Acc_Dec : WORD ;    //Drehzahlregelung - Beschleunigung / Verzögerung
   Pos_Abs_V_Soll : WORD ;    //Positionieren Absolut - Sollgeschwindigkeit
   Pos_Abs_Acc_Dec : WORD ;    //Positionieren Absolut - Beschleunigung / Verzögerung
   Pos_Abs_Zielposition : DWORD ;    //Positionieren Absolut - Zielposition
   Pos_Rel_V_Soll : WORD ;    //Positionieren Relativ - Sollgeschwindigkeit
   Pos_Rel_Acc_Dec : WORD ;    //Positionieren Relativ - Beschleunigung / Verzögerung
   Pos_Rel_Distanz : DWORD ;    //Positionieren Relativ - Distanz
   Alle_BA_Ruck : WORD ;    //Alle Betriebsarten : Ruck
  END_STRUCT ;    
END_VAR
BEGIN
NETWORK
TITLE =



END_FUNCTION_BLOCK
```

Schön wäre auch zu wissen was deine Achsen machen sollen,
soll es eine einfach point to point positonierung sein oder
sollen die Achsen eine Tabelle abfahren usw.

nur nicht aufgeben, hier werden Sie geholfen


----------



## smartie (15 Februar 2010)

Hallo Helmut, ich kann mir deinen Code gerade nicht ansehen da ich vom Handy aus online bin.

Aber ich will versuchen die Funktion der Achsen etwas besser zu schildern:

Insgesamt habe ich vier Achsen, drei physikalische und eine virtuelle Achse die als Master weitestgehend die anderen Achsen steuert. Alle Achsen zusammen steuern ein Handling. 

Jede Achse hat folgende Betriebsarten, die überlagert werden können und auch müssen:

REFERENZIEREN, DREHZAHLREGELUNG, POSITIONIEREN ABSOLUT, POSITIONIEREN RELATIV, TIPPEN, KURVENSCHEIBE, SYNCHRONLAUF. 

Jede der Betriebsarten hat den Eingang START und die Ausgänge AKTIV, FERTIG und GESTOPPT. 

Die Betriebsarten Drehzahlregelung, Positionieren Abs und Rel sowie Tippen haben zudem noch die Eingänge Geschwindigkeit, Beschleunigung sowie Zielposition. 

Da alle Betriebsarten überlagert werden können müssen diese Werte jeweils übergeben werden. 

Dazu kommt dann noch ein Status Baustein der die üblichen Ein- und Ausgänge wie Reglersperre, Istposition, Drehzahl, Störung, etc. hat. 
Insgesamt habe ich für eine Achse 49 Ausgänge die ich auf jeden Fall brauche. 
Eingänge müssten es etwa 30 sein. 
Kann die ja mal morgen hochladen. 

smartie


----------



## smartie (16 Februar 2010)

Guten Morgen,

wie versprochen stelle ich mal die Ein- und Ausgänge alller einzelnen Betriebsarten zusammen:
*
Referenzieren*

```
VAR_INPUT
  REFERENZIEREN_START : BOOL ;    
  IO_ADRESSE : INT ;    //IO_Adresse der Achse aus Hardwarekonfiguration
END_VAR
VAR_OUTPUT
  AKTIV : BOOL ;    
  FERTIG : BOOL ;    
  GESTOPPT : BOOL ;    
END_VAR
```
*Drehzahlregelung*

```
VAR_INPUT
  DREHZAHLREGELUNG_START : BOOL ;    
  GESCHWINDIGKEIT : INT ;    
  BESCHLEUNIGUNG : INT ;    
  IO_ADRESSE : INT ;    //IO_Adresse der Achse aus Hardwarekonfiguration
END_VAR
VAR_OUTPUT
  AKTIV : BOOL ;    
  DREHZAHL_ERREICHT : BOOL ;    
  GESTOPPT : BOOL ;    
END_VAR
```
*Positionieren Absolut*

```
VAR_INPUT
  POSITIONIEREN_ABS_START : BOOL ;    
  GESCHWINDIGKEIT : INT ;    
  BESCHLEUNIGUNG : INT ;    
  ZIELPOSITION : DINT ;    
  IO_ADRESSE : INT ;    //IO_Adresse der Achse aus Hardwarekonfiguration
END_VAR
VAR_OUTPUT
  AKTIV : BOOL ;    
  POSITION_ERREICHT : BOOL ;    
  GESTOPPT : BOOL ;    
END_VAR
```
*Positionieren Relativ*

```
VAR_INPUT
  POSITIONIEREN_REL_START : BOOL ;    
  GESCHWINDIGKEIT : INT ;    
  BESCHLEUNIGUNG : INT ;    
  DISTANZ : DINT ;    
  IO_ADRESSE : INT ;    //IO_Adresse der Achse aus Hardwarekonfiguration
END_VAR
VAR_OUTPUT
  AKTIV : BOOL ;    
  POSITION_ERREICHT : BOOL ;    
  GESTOPPT : BOOL ;    
END_VAR
```
*
Tippen*

```
VAR_INPUT
  TIPPEN_POSITIV : BOOL ;    
  TIPPEN_NEGATIV : BOOL ;    
  GESCHWINDIGKEIT : INT ;    
  BESCHLEUNIGUNG : INT ;    
  IO_ADRESSE : INT ;    //IO_Adresse der Achse aus Hardwarekonfiguration
END_VAR
VAR_OUTPUT
  AKTIV : BOOL ;    
  GESCHWINDIGKEIT_ERREICHT : BOOL ;    
  GESTOPPT : BOOL ;    
END_VAR
```
*Kurvenscheibe*

```
VAR_INPUT
  KURVENSCHEIBE_START : BOOL ;    
  IO_ADRESSE : INT ;    //IO_Adresse der Achse aus Hardwarekonfiguration
END_VAR
VAR_OUTPUT
  AKTIV : BOOL ;    
  GESTOPPT : BOOL ;    
END_VAR
```
*Synchronlauf*

```
VAR_INPUT
  SYNCHRONLAUF_START : BOOL ;    
  IO_ADRESSE : INT ;    //IO_Adresse der Achse aus Hardwarekonfiguration
END_VAR
VAR_OUTPUT
  AKTIV : BOOL ;    
  GESTOPPT : BOOL ;    
END_VAR
```
*Status
*

```
VAR_INPUT
  REGLERSPERRE : BOOL ;    
  FREIGABE_SCHNELLSTOPP : BOOL ;    
  FREIGABE_HALT : BOOL ;    
  BREMSE_OEFFNEN : BOOL ;    
  RESET : BOOL ;    
  RUCK_ALLE_BA : INT ;    
  IO_ADRESSE : INT ;    //IO_Adresse der Achse aus Hardwarekonfiguration  
END_VAR
VAR_OUTPUT
  MOTOR_STEHT : BOOL ;    
  BETRIEBSBEREIT : BOOL ;    
  REFERENZIERT : BOOL ;    
  BREMSE_OFFEN : BOOL ;    
  FEHLER_FU : BOOL ;    
  WARNUNG_FU : BOOL ;    
  FEHLER_IEC : BOOL ;    
  KOMMUNIKATION_OK : BOOL ;    
  FREIGEGEBEN : BOOL ;    
  SYNCHRON : BOOL ;    
  SICHERER_HALT : BOOL ;    
  BETRIEBSART_24V : BOOL ;    
  PDO_NICHT_BEREIT : BOOL ;    
  SW_ENDSCHALTER_BELEGT : BOOL ;    
  FU_FEHLERNUMMER : WORD ;    
  FU_SUBFEHLERNUMMER : WORD ;    
  IEC_FEHLERNUMMER : WORD ;    
  IEC_SUBFEHLERNUMMER : WORD ;    
  UMRICHTERSTATUS : WORD ;    
  IST_GESCHWINDIGKEIT : INT ;    
  IST_DREHZAHL : INT ;    
  ISTPOSITION_ANWENDER : DINT ;    
  ISTPOSITION_MODULO : DINT ;    
  IST_DREHMOMENT : INT ;    
END_VAR
```
Damit habe ich insgesamt *25 Eingänge *und* 43 Ausgänge* wenn ich das alles in einen FB packe.

smartie


----------



## Larry Laffer (16 Februar 2010)

... ich sehe das genau so wie Helmut - ein FB für eine Achse mit allen (wirklich) benötigten Parametern.
Bei diener E-Parameter-Liste will ich mal nichts sagen - das wird schon passen ...
Aber brauchst du die Ausgangsparameter wirklich alle ? Oder sind davon vielleicht einige (oder viele) auch einfach nur "nice-to-have" oder für eine Visu bestimmt. Wenn für Visu dann könnte die auch lesend auf den I-DB zugreifen ...

Gruß
LL


----------



## smartie (16 Februar 2010)

Hallo Larry,

ich habe mir jetzt mal einen großen FB gebastelt, der die SFC14 / SFC 15 enthält.

Diesen FB rufe ich je Achse einmal auf und das funktioniert auch ganz gut.

Einige der Ausgangsparameter (wie Fehlernummern) sind in der Tat einfach nur "nice-to-have" die ich in der Visu anzeigen will.
Ich kopiere diese im Moment in einen Datenbaustein, aber ich kann sie natürlich auch nur aus dem DB lesen.

(Aber ist das wirklich "sauber" so? - Ich hätte jetzt eher gedacht das man auf Daten aus einem InstanzDB eher nicht zugreift.)

smartie


----------



## Larry Laffer (16 Februar 2010)

smartie schrieb:


> (Aber ist das wirklich "sauber" so? - Ich hätte jetzt eher gedacht das man auf Daten aus einem InstanzDB eher nicht zugreift.)


 
Wenn du von der visu darauf zugreifst dann tust du das symbolisch und in dem Fall außerdem auch noch "nur lesend" (hoffe ich). Darin sehe ich kein Problem. Wenn du den FB irgendwann mal änderst, dann wird die Zuordnung der Variablen automatisch mit geändert - du brauchst dann nur die Visu-Projektierung neu übertragen ...

Gruß
LL


----------

