Beckhoff NC Einheit von Positionsachse ermitteln

roboticBeet

Level-2
Beiträge
451
Reaktionspunkte
187
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo,
kann ich softwaremäßig in der TwinCAT SPS die Einheit einer Positionierachse der TwinCAT NC auslesen, also ob eine Achse mit der Einheit mm, m, ° o. ä. parametriert wurde?

Manuell kann ich das natürlich einsehen (siehe Bild), ich würde das aber gerne per Software in der SPS auslesen...

Danke und viele Grüße

1724326047627.png
 
Das geht nicht. Die NC-Achse ist einheitenlos. Die markierte Einheit dient lediglich für die Anzeige innerhalb der Entwicklungsumgebung. Ich habe in der SPS einen String als Konstante / Konfiguration und das lese ich dann ins HMI ein.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Ok, danke. Idee war, das für einen einheitlichen Gesamtstreckenzähler zu verwenden, um die Einheiten richtig zu verrechnen. Dann muss eine entsprechende Einstellung nochmal in die Konfigurationsstruktur. Danke :)
 
Hallo RoboticBeet,

das geht!

Basis-Einheit, Beschleunigungsseinheit, Achsname, Achstyp, etc. kann alles gelesen werden.

Ist seit Jahren Teil einer Bibliothek welche ich bei allen NC-Projekten einsetze um die Projektierungsszeit von Projekten zu reduzieren.

Via MC_ReadParameter funktioniert es tatsächlich nicht, du musst dafür stattdessen ADSREADEX verwenden.

Hab den relevanten Code schnell raus kopiert. Falls die ganze Library von Interesse ist, anbei ein PDF dazu. Spart extrem Engineering-Zeit.

Allgemeine Zugriffsparameter:
nNcTaskPort : T_AmsPort := 501; // NC task port number
nIdxGrpBase : UDINT := 16#4000; // NC axes base index
nIdxGrpBaseEnc : UDINT := 16#5000; // NC axes base index encoder
nIdxGrpBaseCtrl : UDINT := 16#6000; // NC axes base index control
nIdxGrpBaseDrive : UDINT := 16#7000; // NC axes base index drive

Relevanter Code-Ausschnitt aus einer Schrittkette welche Initial beim SPS-Start einmalig ausgeführt wird:
(Snippet umfasst auch das Lesen von Achsname, Achstyp, usw.):
11: // InfoData (read once): Axis name
fbAdsReadEx(
NETID:=stControl.stNc.stAccess.sAdsNetId,
PORT:=stControl.stNc.stAccess.nNcTaskPort,
IDXGRP:=stControl.stNc.stAccess.nIdxGrpBase+stAxis.NcToPlc.AxisId,
IDXOFFS:=16#2,
LEN:=SIZEOF(aAxisName),
DESTADDR:=ADR(aAxisName),
READ:=TRUE,
TMOUT:=DEFAULT_ADS_TIMEOUT);
IF NOT fbAdsReadEx.BUSY THEN
fbAdsReadEx(
NETID:=stControl.stNc.stAccess.sAdsNetId,
PORT:=stControl.stNc.stAccess.nNcTaskPort,
IDXGRP:=stControl.stNc.stAccess.nIdxGrpBase+stAxis.NcToPlc.AxisId,
IDXOFFS:=16#2,
LEN:=SIZEOF(aAxisName),
DESTADDR:=ADR(aAxisName),
READ:=FALSE,
TMOUT:=DEFAULT_ADS_TIMEOUT);
IF NOT fbAdsReadEx.ERR THEN
FOR nLoop:= 0 TO 31 DO
aByteMaxStringLength[nLoop]:=aAxisName[nLoop];
END_FOR
stControl.stNc.stAxisInfo.sAxisName:=BYTEARR_TO_MAXSTRING(aByteMaxStringLength);
nInfoDataRead:=nInfoDataRead+1;
END_IF;
nParamReadingStep:=nParamReadingStep+1;
END_IF

12: // InfoData (read once): Axis unit
fbAdsReadEx(
NETID:=stControl.stNc.stAccess.sAdsNetId,
PORT:=stControl.stNc.stAccess.nNcTaskPort,
IDXGRP:=stControl.stNc.stAccess.nIdxGrpBase+stAxis.NcToPlc.AxisId,
IDXOFFS:=16#5,
LEN:=SIZEOF(aAxisUnit),
DESTADDR:=ADR(aAxisUnit),
READ:=TRUE,
TMOUT:=DEFAULT_ADS_TIMEOUT);
IF NOT fbAdsReadEx.BUSY THEN
fbAdsReadEx(
NETID:=stControl.stNc.stAccess.sAdsNetId,
PORT:=stControl.stNc.stAccess.nNcTaskPort,
IDXGRP:=stControl.stNc.stAccess.nIdxGrpBase+stAxis.NcToPlc.AxisId,
IDXOFFS:=16#5,
LEN:=SIZEOF(aAxisUnit),
DESTADDR:=ADR(aAxisUnit),
READ:=FALSE,
TMOUT:=DEFAULT_ADS_TIMEOUT);
IF NOT fbAdsReadEx.ERR THEN
FOR nLoop:= 0 TO 11 DO
aByteMaxStringLength[nLoop]:=aAxisUnit[nLoop];
END_FOR
stControl.stNc.stAxisInfo.sBaseUnit:=BYTEARR_TO_MAXSTRING(aByteMaxStringLength);
nInfoDataRead:=nInfoDataRead+1;
END_IF;
nParamReadingStep:=nParamReadingStep+1;
END_IF

13: // InfoData (read once): Axis unit interpretation
fbAdsReadEx(
NETID:=stControl.stNc.stAccess.sAdsNetId,
PORT:=stControl.stNc.stAccess.nNcTaskPort,
IDXGRP:=stControl.stNc.stAccess.nIdxGrpBase+stAxis.NcToPlc.AxisId,
IDXOFFS:=16#26,
LEN:=SIZEOF(nAdsReadUINT32Value),
DESTADDR:=ADR(nAdsReadUINT32Value),
READ:=TRUE,
TMOUT:=DEFAULT_ADS_TIMEOUT);
IF NOT fbAdsReadEx.BUSY THEN
fbAdsReadEx(
NETID:=stControl.stNc.stAccess.sAdsNetId,
PORT:=stControl.stNc.stAccess.nNcTaskPort,
IDXGRP:=stControl.stNc.stAccess.nIdxGrpBase+stAxis.NcToPlc.AxisId,
IDXOFFS:=16#26,
LEN:=SIZEOF(nAdsReadUINT32Value),
DESTADDR:=ADR(nAdsReadUINT32Value),
READ:=FALSE,
TMOUT:=DEFAULT_ADS_TIMEOUT);
IF NOT fbAdsReadEx.ERR THEN
stControl.stNc.stAxisInfo.bVelUnitPerMin:=nAdsReadUINT32Value.0;
stControl.stNc.stAxisInfo.bVelUnitPerSec:=NOT nAdsReadUINT32Value.0;
stControl.stNc.stAxisInfo.bPosInThousands:=nAdsReadUINT32Value.1;
stControl.stNc.stAxisInfo.bPosModuloDisp:=nAdsReadUINT32Value.2;
IF stControl.stNc.stAxisInfo.bVelUnitPerMin THEN
stControl.stNc.stAxisInfo.sVelocityUnit:=CONCAT(stControl.stNc.stAxisInfo.sBaseUnit,'/min');
ELSE
stControl.stNc.stAxisInfo.sVelocityUnit:=CONCAT(stControl.stNc.stAxisInfo.sBaseUnit,'/s');
END_IF
stControl.stNc.stAxisInfo.sAccelerationUnit:=CONCAT(stControl.stNc.stAxisInfo.sBaseUnit,'/s2');
stControl.stNc.stAxisInfo.sJerkUnit:=CONCAT(stControl.stNc.stAxisInfo.sBaseUnit,'/s3');
nInfoDataRead:=nInfoDataRead+1;
END_IF;
nParamReadingStep:=nParamReadingStep+1;
END_IF

14: // InfoData (read once): Axis type
fbAdsReadEx(
NETID:=stControl.stNc.stAccess.sAdsNetId,
PORT:=stControl.stNc.stAccess.nNcTaskPort,
IDXGRP:=stControl.stNc.stAccess.nIdxGrpBase+stAxis.NcToPlc.AxisId,
IDXOFFS:=16#3,
LEN:=SIZEOF(nAdsReadUINT32Value),
DESTADDR:=ADR(nAdsReadUINT32Value),
READ:=TRUE,
TMOUT:=DEFAULT_ADS_TIMEOUT);
IF NOT fbAdsReadEx.BUSY THEN
fbAdsReadEx(
NETID:=stControl.stNc.stAccess.sAdsNetId,
PORT:=stControl.stNc.stAccess.nNcTaskPort,
IDXGRP:=stControl.stNc.stAccess.nIdxGrpBase+stAxis.NcToPlc.AxisId,
IDXOFFS:=16#3,
LEN:=SIZEOF(nAdsReadUINT32Value),
DESTADDR:=ADR(nAdsReadUINT32Value),
READ:=FALSE,
TMOUT:=DEFAULT_ADS_TIMEOUT);
IF NOT fbAdsReadEx.ERR THEN
stControl.stNc.stAxisInfo.nAxisType:=nAdsReadUINT32Value;
nInfoDataRead:=nInfoDataRead+1;
END_IF;
nParamReadingStep:=nParamReadingStep+1;
END_IF
 

Anhänge

Interessant. Werde ich mal austesten, wenn etwas mehr Zeit ist. Die Einheit wird dann als numerischer Wert (Enum) zurückgeliefert? Hast du dafür auch die Enum-Definition?
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Es ist kein Enum, sondern ein Array of Byte. Der mit AdsReadEx aus der NC gelesene Wert kann daher in der PLC nicht direkt als String interpretiert werden. Die Konvertierung siehst du aber in dem Code den ich dir raus kopiert habe, die Achs-Unit wird dort in Schritt 12 gelesen.

Variablen auf welche die gelesenen Daten mit AdsReadEx geschrieben werden, sowie die Hilfsvariable für die anschliessende String-Konvertierung:
aAxisName : ARRAY[0..32] OF BYTE;
aAxisUnit : ARRAY[0..11] OF BYTE;
aByteMaxStringLength : ARRAY[0..MAX_STRING_LENGTH] OF BYTE;

Das Konvertieren zum Datentyp String erfolgt mittels BYTEARR_TO_MAXSTRING
stControl.stNc.stAxisInfo.sBaseUnit:=BYTEARR_TO_MAXSTRING(aByteMaxStringLength);
 
Zurück
Oben