# Asynchronmotor mit Frequenzumrichter positionieren



## tnightlife (25 August 2017)

Hallo,

wie die Überschrift schon andeutet habe ich dir Anforderung mit einem Frequenzumrichter einen Asynchronmotor Positionen anfahren zu lassen (Muss nicht "sehr" genau sein). 

Ausgangslage:

Der Motor hat ein 12er Getriebe dran. Ich bekomme Positionen über einen optischen Sensor. Als Steuerung haben wir hier eine X20CP.... von B&R hier. FU ebenso von B&R eine P74 oder X64 zur Auswahl.

Da ich bisher eher mit Synchron-Servomotoren zutun hatte, weiß ich nicht so recht, ob es a) funktionieren kann und b) wie ich starten kann.

---

Meine Idee ist folgende:

- Über den SDC (quasi virtuelle Achse die dem FU Frequenzen bzw. Geschwindigkeiten vorgibt) von B&R lasse ich den Motor eine absolute Position anfahren
- Diese Position wird der Motor natürlich nie wirklich erreichen (Sollposition = AktuellePosition)
- Über den optischen Sensor werde ich versuchen quasi eine Regelung zu realisieren
- Die Frequenz die raus geht, kann ich beeinflussen (größer oder kleiner machen) -> Diesen würde ich entsprechend der Lage verändern

Ich weiß jedoch nicht, ob das der goldene Weg ist. Kann das überhaupt gelingen? Gibt es einen anderen Weg? Bietet B&R etwas an, was das implementieren vereinfachen würde? 

Ich freue mich auf eure Antworten


----------



## gangsterbob (26 August 2017)

Hallo,

die sdc Achse mit nem fu funktioniert gut. Was für einen optischen Sensor hast du und was für einen Aufbau?
Verstehe nicht ganz was du meinst? Die Position wird der SDC-Achse übergeben (von Zählerkarte bespw.). Der Rest läuft in der Sdc-Achse. Diese gibt dem Fu den Frequenzsollwert zyklisch vor.


----------



## zako (26 August 2017)

gangsterbob schrieb:


> Hallo,
> 
> die sdc Achse mit nem fu funktioniert gut. Was für einen optischen Sensor hast du und was für einen Aufbau?
> Verstehe nicht ganz was du meinst? Die Position wird der SDC-Achse übergeben (von Zählerkarte bespw.). Der Rest läuft in der Sdc-Achse. Diese gibt dem Fu den Frequenzsollwert zyklisch vor.



genau so kenne ich das von der SIMATIC S7-1500 auch.
Es kommt jetzt noch darauf an wie genau Dein FU den Motor (ich nehme an geberlos) regeln kann. 
Ich habe solche Aufbauten mit dem SINAMICS G in einer feldorientierten Regelungsart betrieben. Das war dann auch recht genau - wobei der SINAMICS in der aktuellen Firmware  "geregelt bis Drehzahl null" betrieben werden kann.
Falls Dein FU nur "U/f- Kennlinie" kann, dann wirst Du einen statischen Schleppabstand haben (kommt auch auf die Schlupffrequenz Deines Motors an und hängt v.a. von der Last ab). Da habe ich die Erfahrung gemacht, dass man besser mit weniger Verrundung fährt und "satt" in die Zielposition reinfährt.


----------



## tnightlife (29 August 2017)

Hi,
erstmal danke für die Antwort.
Es ist ein Sick DL35-B15552 Laser Distanzsensor (200mm-30.000mm) mit IO-Link Schnittstelle. Der Distanzsensor wird eingelesen über ein X20DS438A (IO-Link Master). Als Eingang hat man dann einen UINT Wert an die man eine Variable mappen kann.

Der Senseor bzw. der Geber hängt somit nicht direkt am FU. Ich habe lediglich eine Variable am X20DS438A an die ich die Positionsdaten bekomme.

---

Bisheriges Vorgehen:

Da man an den SDC zwei Geber anbinden kann (intern & extern), bin ich erst diesen Weg gegangen.
Im ersten Schritt habe ich versucht, die Positionsdaten an die Encoder-Schnittstelle (EncIf1) des SDC zu übergeben.
Jedoch bekomme ich danach immer einen Fehler (31221) im Testfenster, wenn ich versuche den Regler zu starten, um Basisbewegungen durchführen zu können. Wenn ich den EncIf1 wieder rausnehme, funktioniert das Testfenster wieder.
Folgendes wurde für den EncIf1 eingestellt:
iEncOK ist konstant True, da es an das ModuleOK von X20DS438A gemappt wurde.
iActTime und iLifeCnt inkrementiere ich zyklisch im schnellsten Task.
iActPos ist an die Positionsschnittstelle der X20DS438A gemappt.

Darüber hinaus habe ich die Information bekommen, dass das die Lageregelung mit SDC und FU sehr vorsichtig zu genießen ist, da es sehr schnell anfängt zu schwingen. Da der Fehler besteht, konnte ich leider nicht testen, ob dem so ist.

Aus diesem Grund weiß ich nun nicht ganz, wie ich vorgehen kann. Kann das überhaupt mit dem Aufbau funktionieren?

"...die sdc Achse mit nem fu funktioniert gut." -> Das hört sich so einfach an ;D.. 

Danke


----------



## tnightlife (30 August 2017)

gangsterbob schrieb:


> Hallo,
> 
> die sdc Achse mit nem fu funktioniert gut. Was fürr einen optischen Sensor hast du und was für einen Aufbau?
> Verstehe nicht ganz was du meinst? Die Position wird der SDC-Achse übergeben (von Zählerkarte bespw.). Der Rest läuft in der Sdc-Achse. Diese gibt dem Fu den Frequenzsollwert zyklisch vor.



Habe vergessen noch was hinzuzufügen. Du hattest geschrieben "Verstehe nicht ganz was du meinst?".

Da ich aktuell diesen Fehler habe, also die Positionsdaten von der Karte nicht direkt im SDC auswerten kann (Fehler wenn ich EncIf1 aktiviere) und ich die Information bekommen habe, dass der SDC nicht besonders gut für die Lageregelung eines ASYM geeignet ist wollte ich einen anderen Weg gehen. 

Der SDC gibt Geschwindigkeitssollwerte raus, die der ASYM für gewöhnlich nicht erreicht, da ohne Rückführung keine Regelung besteht. Es ist lediglich ein Stellbetrieb.

Da ich jedoch den Distanzsensor habe, kann ich bestimmen, welche Geschwindigkeit ich tatsächlich fahre. 
Die vom SDC ausgegebene Sollgeschwindigkeit wird über die Variable oSetPos an den Datenpunkt des FU's durchgegeben. Somit weiß ich auch, wie die Geschwinigkeitsrampe auszusehen hat.

Also weiß ich (a) wie schnell ich zu welcher Zeit sein sollte, um die Position erreichen zu können und (b) wie schnell ich aktuell fahre. Somit kann ich mich einfach an die Variable oSetPos "zwischenhängen" und den Wert, der tatsächlich an den FU geschrieben wird mit einem Regler (PI) leicht nach oben (oder unten) korrigieren, sodass sich die tatsächliche Geschwindigkeit möglichst der berechneten Rampe annähert.

---

Problem: Das habe ich noch nie gemacht ;D. Geht das? Kann das gehen? Gibt es einen anderen (besseren und/oder leichteren) Weg?

Wenn ich nicht den Fehler mit der EncIf1 Schnittstelle hätte, würde ich es mit dem SDC und der Encoder Schnittstelle EncIf1 ausprobieren, jedoch bekomme ich den Fehler nicht weg. Support kann mir da nicht wirklich weiterhelfen. 

Freue mich auf eure Ratschläge.


----------



## gangsterbob (30 August 2017)

>>> Fehler (31221)

*Beschreibung:* 
Laufzeit-Fehler der Geberüberwachung beim Kommando  'Regler einschalten', 'Referenzieren starten' oder während aktiver Regelung.  
Die SDC PV 'iActTime' beinhaltet keinen gültigen Zeitstempel, der  Zeitstempel ist ausserhalb des erlaubten Zeitfensters (keine zyklische Erfassung  der Istposition). 
Die SDC Geberstatus PV 'iEncOK' ist weggefallen.  


*Reaktion:* 
Siehe Folgefehler. 
Werden die SDC PVs 'iActTime' und  'iEncOK' des Geber Interface wieder zu jedem SDC Zyklus richtig versorgt, ist  der Betrieb wieder möglich. 


*Ursache/Abhilfe:* 
Überprüfung des I/O-Mappings der Geber PVs.  
Überprüfen der Fehlerzustände des Geber Hardwaremoduls, auf welches die SDC  Geber PVs gemappt sind. 
Überprüfung der SDC Achskonfigurations PV. 
Geber  ist nicht angeschlossen. 
Geberversorgung nicht vorhanden oder fehlerhaft.  
Geberverbindung ist defekt oder gestört. 
Verdrahtung der Geberverbindung  überprüfen. 
Geber defekt. 
Fehlauslösung durch defekte Hardware oder  Störungen (Drahtbruch, Leitungsschluss, Verdrahtungsfehler,  Ansteuerungs-Hardware defekt oder gestört). 




Da scheint aber irgendwas nicht richtig initialisiert oder verschaltet zu sein..

Hast du die initialisierung und die Zähler ähnlich zu folgendem durchgeführt?

Init

 gAxis10_HW.DrvIf_Typ := ncSDC_DRVSERVO16;
 strcpy( ADR(gAxis10_HW.DrvIf_Name[0]), ADR('gAxis10_DrvIf') );

 gAxis10_HW.EncIf1_Typ := ncSDC_ENC32; 
 strcpy( ADR(gAxis10_HW.EncIf1_Name[0]), ADR('gAxis10_EncIf1') ); 

 gAxis10_HW.DiDoIf_Typ := ncSDC_DIDO;
 strcpy( ADR(gAxis10_HW.DiDoIf_Name[0]), ADR('gAxis10_DiDoIf') );

Cyclic
gAxis10_DiDoIf.iLifeCntReference        := gAxis10_DiDoIf.iLifeCntReference + 1;
gAxis10_DiDoIf.iLifeCntNegHwEnd      := gAxis10_DiDoIf.iLifeCntNegHwEnd  + 1;
gAxis10_DiDoIf.iLifeCntPosHwEnd      := gAxis10_DiDoIf.iLifeCntPosHwEnd  + 1;


gAxis10_DiDoIf.iLifeCntDriveReady     := gAxis10_DiDoIf.iLifeCntDriveReady + 1;
gAxis10_DiDoIf.iLifeCntDriveEnable    := gAxis10_DiDoIf.iLifeCntDriveEnable + 1;    
gAxis10_DrvIf.iLifeCnt                          := gAxis10_DrvIf.iLifeCnt + 1;     

gAxis10_EncIf1.iLifeCnt                      := gAxis10_EncIf1.iLifeCnt + 1;
gAxis10_EncIf1.iRefPulseCnt              := gAxis10_EncIf1.iRefPulseCnt + 1;
gAxis10_EncIf1.iActTime                     := DINT_TO_INT(g_SystemTimeCPU);
gAxis10_EncIf1.iActPos                      := adi_Geberposition;



Wichtig sind die Bezeichnungen der Variablennamen

in diesem Fall heisst ja die Achse

"gAxis10"

Die anden Variablen wie "gAxis10_EncIf1" MÜSSEN zwingend auch gAxis10 mit den Endungen "..._EncIf1" usw. heissen. Bei den anderen Strukturen gilt das Gleiche.

Weiterhin muss natürlich in der .apt Tabele der korrekt berechnete Wert "SERVO_V_MAX_OUTPUT" eingetragen sein (Siehe Hilfe)! Außerdem noch "SCALE_ENCOD_INCR" (Wie man das in deinem Fall eingibt kann ich die auf Anhieb auch nicht sagen). 


Viel Erfolg noch!


----------



## gangsterbob (30 August 2017)

Achso...weiterhin würde ich dem Antrieb selbst einen normalen Geber spendieren (Über zählerkarte). Mit zahnriemen oder sowas, oder direkt hinten an die Motorwelle.  Und dann nur den Positionssollwert über den Laser ermitteln. Das funktioniert auf jeden Fall!
Denke mit dem Lasersensor direkt könnte es schwierig werden...


----------



## tnightlife (30 August 2017)

Der Tipp mit "gAxis10_EncIf1" und "gAxis10_EncIf1.iActTime := DINT_TO_INT(g_SystemTimeCPU);" haben geholfen. Hatte nur mit "_EncIf" auf die Struktur verwiesen und die "1" nicht geschrieben. Die ActPos Schnittstelle hatte ich auch nur inkrementiert, statt die SystemTime zuzuweisen.

In der .apt Tabelle habe ich beim "PCTRL_S_ACT_PARID" Parameter "ENCOD1_S_ACT" eingesetzt, statt den Default-Wert PCTRL_S_SET.
Ich weiß nicht, ob ich das "SERVO_V_MAX_OUTPUT" richtig verstanden/berechnet habe. Dort habe ich 15000 eingesetzt. (ca. 900 rev./min. Nennmoment -> 15 rev./s -> 15*1000=15000 (1000 = Load units per revolution).

---

Also der Fehler kommt nicht mehr, sodass ich im Testfenster arbeiten kann.

Aktuell teste ich auch nicht mit dem Laser Distanzsensor, sondern mit einem Inkrementalgeber, den ich an die Welle festgemacht habe (schlauch + schlauchschelle).

Das Hindernis im Moment ist ein Schleppfehler, der nach wenigen Sekunden auftritt. Irgendwas passt das noch nicht ganz zusammen. Den Schleppfehler kann ich so hoch drehen wie ich mag.
Wenn ich die ActPos und die SetPos trace, sehe ich, dass die SetPos der ActPos -nacheilt- und beim eintreten des Schleppfehlers der SetPos einen Sprung hat und sofort die Positon des Actpos erreicht.

Das die Sollposition der Istposition nacheilt ist für mich ein sehr merkwürdiges Phänomen. Hast du eventuell eine Idee wo ich was vergessen haben könnte?


----------

