Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,24 @@
### [FIX] `AxoCmmtAs` loses axis position while in torque control

**Note:** PLC bug fix in `src/components.festo.drives` (`AxoCmmtAs`, `PROFIdriveTelegram_111`) and `src/components.drives` (`AxoDrive_Config`). No public-API removal. Branch: `1152-bug-cmmt-as-while-in-torque-control-loses-axis-position`. Issue #1152, PR #1166.

- fix: `AxoCmmtAs` positioning no longer advances past the target-reached step on the `Telegram111_In.ZSW1.targetPosReached` (X10) bit alone. It now additionally requires the actual position to be within the in-position window — `ABS(Position - ActualPosition) <= _AxisReference^.Config.InPositionWindow` — before transitioning, so a drive that asserts `targetPosReached` while still off target (e.g. after a torque-control phase) no longer "loses" its position.
- fix: Removed an unstable torque-control guard that raised programming error `1542` (`eAxoMessageCategory#ProgrammingError`, `MC_TorqueControlErrorID := 1542`) whenever `targetPosReached` became true during torque-control states `126`/`127`. The check proved unreliable and is disabled pending further investigation.
- feat: `AxoDrive_Config` (in `src/components.drives`) gains an `InPositionWindow` parameter (`LREAL`, default `0.05`) supplying the tolerance above.
- chore: Annotated the `PROFIdriveTelegram_111_ZSW1` status signals with their hardware bit positions (X0–X15) in the attribute labels, and added matching bit-position comments to the ZSW1 mapping in `AxoCmmtAs`.
- chore: Disabled an unfinished dynamic-torque-boost parameter write (PNU `13073`).
- docs: Updated `components.festo.drives` docs (CHANGELOG `0.61.1`, TROUBLES, `AxoCmmtAs.md`) to document the in-position window, the ZSW1 bit map, and the torque-control behaviour.

**Impact:**
- Absolute positioning moves on Festo CMMT-AS drives complete only when the axis is genuinely within `InPositionWindow` of the commanded target, fixing the position loss observed after torque control.
- The spurious `1542` programming error during torque control no longer fires.

**Risks/Review:**
- `InPositionWindow` defaults to `0.05` (axis position units). Too small a value can stall a move just before completion; too large lets it complete while still off target — tune per axis.
- The torque-control `1542` guard is disabled rather than fixed; the underlying condition is still under investigation.

**Testing:**
- Delivered and reviewed via PR #1166 (issue #1152). No automated AxUnit test was added for the in-position gate.
### [FIX] `AxoKrc5` no longer throws spurious task-timeout errors

**Note:** PLC bug fix in `src/components.kuka.robotics/ctrl/src/AxoKrc5/v_5_x_x/AxoKrc5.st`. KRC5-only — `AxoKrc4` is unchanged. No public-API change. Branch: `1165-bug-kuka-issue-with-robot-reset` ([#1167](https://github.com/Inxton/AXOpen/pull/1167)).
Expand Down
2 changes: 2 additions & 0 deletions src/components.drives/ctrl/src/AxoDrives/AxoDrive_Config.st
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ NAMESPACE AXOpen.Components.Drives
InTorqueWindowPerCent : LREAL := LREAL#5.0;
{#ix-set:AttributeName = "<#InTorque window time#>"}
InTorqueWindowTime : LTIME := LT#100ms;
{#ix-set:AttributeName = "<#InPosition window#>"}
InPositionWindow : LREAL := LREAL#0.05;
END_VAR
END_CLASS
END_NAMESPACE
74 changes: 51 additions & 23 deletions src/components.festo.drives/ctrl/src/AxoCmmtAs/AxoCmmtAs.st
Original file line number Diff line number Diff line change
Expand Up @@ -952,22 +952,22 @@ NAMESPACE AXOpen.Components.Festo.Drives
END_IF;

// ZSW1
_AxisReference^.Telegram111_In.ZSW1.followingErrorInTolerance := _Telegram111[0].%X0;
_AxisReference^.Telegram111_In.ZSW1.controlRequest := _Telegram111[0].%X1;
_AxisReference^.Telegram111_In.ZSW1.targetPosReached := _Telegram111[0].%X2;
_AxisReference^.Telegram111_In.ZSW1.homePosSet := _Telegram111[0].%X3;
_AxisReference^.Telegram111_In.ZSW1.acknowledgeTraversingBlockActivated := _Telegram111[0].%X4;
_AxisReference^.Telegram111_In.ZSW1.driveStopped := _Telegram111[0].%X5;
_AxisReference^.Telegram111_In.ZSW1.axisAccelerates := _Telegram111[0].%X6;
_AxisReference^.Telegram111_In.ZSW1.axisDecelerates := _Telegram111[0].%X7;
_AxisReference^.Telegram111_In.ZSW1.readyForSwitchOn := _Telegram111[1].%X0;
_AxisReference^.Telegram111_In.ZSW1.ready := _Telegram111[1].%X1;
_AxisReference^.Telegram111_In.ZSW1.operationEnabled := _Telegram111[1].%X2;
_AxisReference^.Telegram111_In.ZSW1.faultPresent := _Telegram111[1].%X3;
_AxisReference^.Telegram111_In.ZSW1.noCoastingActive := _Telegram111[1].%X4;
_AxisReference^.Telegram111_In.ZSW1.noQuickStopActive := _Telegram111[1].%X5;
_AxisReference^.Telegram111_In.ZSW1.switchingOnInhibitedActive := _Telegram111[1].%X6;
_AxisReference^.Telegram111_In.ZSW1.warningActive := _Telegram111[1].%X7;
_AxisReference^.Telegram111_In.ZSW1.followingErrorInTolerance := _Telegram111[0].%X0; //.8
_AxisReference^.Telegram111_In.ZSW1.controlRequest := _Telegram111[0].%X1; //.9
_AxisReference^.Telegram111_In.ZSW1.targetPosReached := _Telegram111[0].%X2; //.10
_AxisReference^.Telegram111_In.ZSW1.homePosSet := _Telegram111[0].%X3; //.11
_AxisReference^.Telegram111_In.ZSW1.acknowledgeTraversingBlockActivated := _Telegram111[0].%X4; //.12
_AxisReference^.Telegram111_In.ZSW1.driveStopped := _Telegram111[0].%X5; //.13
_AxisReference^.Telegram111_In.ZSW1.axisAccelerates := _Telegram111[0].%X6; //.14
_AxisReference^.Telegram111_In.ZSW1.axisDecelerates := _Telegram111[0].%X7; //.15
_AxisReference^.Telegram111_In.ZSW1.readyForSwitchOn := _Telegram111[1].%X0; //.0
_AxisReference^.Telegram111_In.ZSW1.ready := _Telegram111[1].%X1; //.1
_AxisReference^.Telegram111_In.ZSW1.operationEnabled := _Telegram111[1].%X2; //.2
_AxisReference^.Telegram111_In.ZSW1.faultPresent := _Telegram111[1].%X3; //.3
_AxisReference^.Telegram111_In.ZSW1.noCoastingActive := _Telegram111[1].%X4; //.4
_AxisReference^.Telegram111_In.ZSW1.noQuickStopActive := _Telegram111[1].%X5; //.5
_AxisReference^.Telegram111_In.ZSW1.switchingOnInhibitedActive := _Telegram111[1].%X6; //.6
_AxisReference^.Telegram111_In.ZSW1.warningActive := _Telegram111[1].%X7; //.7
//POS_ZSW1
_AxisReference^.Telegram111_In.POS_ZSW1.%B1 := _Telegram111[2];
_AxisReference^.Telegram111_In.POS_ZSW1.%B0 := _Telegram111[3];
Expand Down Expand Up @@ -2416,8 +2416,9 @@ NAMESPACE AXOpen.Components.Festo.Drives
END_IF;
IF State = UINT#84 THEN
_AxisReference^.Telegram111_Out.STW1.activateTraversing := FALSE;
IF _AxisReference^.Telegram111_In.ZSW1.targetPosReached THEN
State := UINT#85;
IF _AxisReference^.Telegram111_In.ZSW1.targetPosReached
AND ABS( Position - THIS.ActualPosition) <= _AxisReference^.Config.InPositionWindow THEN
State := UINT#85;
END_IF;
END_IF;
IF State = UINT#85 THEN
Expand Down Expand Up @@ -3462,6 +3463,32 @@ NAMESPACE AXOpen.Components.Festo.Drives
State := UINT#129;
END_IF;
END_IF;

// //Writing P1.102223.0.0 – Selection of dynamic torque boost → [0] None
// // PNU 13073.0 - USINT
// IF State = UINT#1123 THEN
// Busy := TRUE;
// Active := TRUE;
// Parametrization.Inputs.Enable := TRUE;
// Parametrization.Inputs.ReadWrite := TRUE;
// Parametrization.Inputs.ParameterNo := 13073;
// Parametrization.Inputs.Subindex := 0;
// Parametrization.Inputs.AxisNo := BYTE#1;
// Parametrization.Inputs.HardwareId := _AxisReference^.HWIDs.HW_ModuleAccessPoint;
// Parametrization.Inputs.ValueWriteLINT := LINT#0;
// IF Parametrization.Outputs.Done AND NOT Parametrization.Outputs.Error THEN
// Parametrization.Inputs.Enable := FALSE;
// Parametrization.Inputs.ReadWrite := FALSE;
// State := UINT#124;
// RETURN;
// END_IF;
// IF Parametrization.Outputs.Error THEN
// Messenger.Activate( UINT#1543, eAxoMessageCategory#Error);
// MC_TorqueControlErrorID := DINT#1543;
// State := UINT#129;
// END_IF;
// END_IF;

IF State = UINT#124 THEN
Busy := TRUE;
Active := TRUE;
Expand Down Expand Up @@ -3513,11 +3540,12 @@ NAMESPACE AXOpen.Components.Festo.Drives
Error := TRUE;
END_IF;

IF (State=UINT#126 OR State =UINT#127) AND _AxisReference^.Telegram111_In.ZSW1.targetPosReached THEN
Messenger.Activate( UINT#1542, eAxoMessageCategory#ProgrammingError);
MC_TorqueControlErrorID := DINT#1542;
State := UINT#129;
END_IF;
// ! IT IS NOT STABLE !
// IF (State=UINT#126 OR State =UINT#127) AND _AxisReference^.Telegram111_In.ZSW1.targetPosReached THEN
// Messenger.Activate( UINT#1542, eAxoMessageCategory#ProgrammingError);
// MC_TorqueControlErrorID := DINT#1542;
// State := UINT#129;
// END_IF;

IF State>=UINT#120 AND State<UINT#127 THEN
IF MC_TorqueControlContinuousUpdate_SV AND (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -202,37 +202,37 @@ NAMESPACE AXOpen.Components.Festo.Drives
CLASS PUBLIC PROFIdriveTelegram_111_ZSW1
VAR PUBLIC
{#ix-attr:[Container(Layout.Stack)]}
{#ix-set:AttributeName = "<#followingErrorInTolerance#>"}
{#ix-set:AttributeName = "<#followingErrorInTolerance#> (X8)"}
followingErrorInTolerance : BOOL;
{#ix-set:AttributeName = "<#controlRequest#>"}
{#ix-set:AttributeName = "<#controlRequest#> (X9)"}
controlRequest : BOOL;
{#ix-set:AttributeName = "<#targetPosReached#>"}
{#ix-set:AttributeName = "<#targetPosReached#> (X10)"}
targetPosReached : BOOL;
{#ix-set:AttributeName = "<#homePosSet#>"}
{#ix-set:AttributeName = "<#homePosSet#> (X11)"}
homePosSet : BOOL;
{#ix-set:AttributeName = "<#acknowledgeTraversingBlockActivated#>"}
{#ix-set:AttributeName = "<#acknowledgeTraversingBlockActivated#> (X12)"}
acknowledgeTraversingBlockActivated : BOOL;
{#ix-set:AttributeName = "<#driveStopped#>"}
{#ix-set:AttributeName = "<#driveStopped#> (X13)"}
driveStopped : BOOL;
{#ix-set:AttributeName = "<#axisAccelerates#>"}
{#ix-set:AttributeName = "<#axisAccelerates#> (X14)"}
axisAccelerates : BOOL;
{#ix-set:AttributeName = "<#axisDecelerates#>"}
{#ix-set:AttributeName = "<#axisDecelerates#> (X15)"}
axisDecelerates : BOOL;
{#ix-set:AttributeName = "<#readyForSwitchOn#>"}
{#ix-set:AttributeName = "<#readyForSwitchOn#> (X0)"}
readyForSwitchOn : BOOL;
{#ix-set:AttributeName = "<#ready#>"}
{#ix-set:AttributeName = "<#ready#> (X1)"}
ready : BOOL;
{#ix-set:AttributeName = "<#operationEnabled#>"}
{#ix-set:AttributeName = "<#operationEnabled#> (X2)"}
operationEnabled : BOOL;
{#ix-set:AttributeName = "<#faultPresent#>"}
{#ix-set:AttributeName = "<#faultPresent#> (X3)"}
faultPresent : BOOL;
{#ix-set:AttributeName = "<#noCoastingActive#>"}
{#ix-set:AttributeName = "<#noCoastingActive#> (X4)"}
noCoastingActive : BOOL;
{#ix-set:AttributeName = "<#noQuickStopActive#>"}
{#ix-set:AttributeName = "<#noQuickStopActive#> (X5)"}
noQuickStopActive : BOOL;
{#ix-set:AttributeName = "<#switchingOnInhibitedActive#>"}
{#ix-set:AttributeName = "<#switchingOnInhibitedActive#> (X6)"}
switchingOnInhibitedActive : BOOL;
{#ix-set:AttributeName = "<#warningActive#>"}
{#ix-set:AttributeName = "<#warningActive#> (X7)"}
warningActive : BOOL;
END_VAR
END_CLASS
Expand Down
23 changes: 22 additions & 1 deletion src/components.festo.drives/docs/AxoCmmtAs.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,28 @@ Generated documentation for the `AxoCmmtAs` component.

[!code-pascal[](../../showcase/app/src/components.festo.drives/Documentation/AxoCmmtAs_Showcase.st?name=Usage)]

## Source
## Positioning tolerance

A positioning move only completes when the drive asserts `Telegram111_In.ZSW1.targetPosReached` (bit X10) **and** the actual position is within the configured in-position window — `ABS(Position - ActualPosition) <= Config.InPositionWindow`. This prevents the move from advancing while the axis is still off target (for example after a torque-control phase).

The window is configured on the drive's `AxoDrive_Config` (provided by the `components.drives` base library):

| Parameter | Type | Default | Purpose |
|---|---|---|---|
| `InPositionWindow` | `LREAL` | `0.05` | Maximum allowed deviation between commanded `Position` and `ActualPosition` (in axis position units) for a move to count as complete. |

See [`TROUBLES.md`](TROUBLES.md#a-positioning-move-reports-complete-while-the-axis-is-not-at-the-commanded-target) for tuning guidance.

## Torque control

Torque control uses `clamping-torque`. The drive is commanded to a `fixed-stop` with a torque limit. The task completes when the drive sends the signal `POS_ZSW2.13 - Fixed stop Clamping torque reached`. That signal is filtered on the PLC side by a time-torque window that can be configured via the properties `DriveConfig.InTorqueWindowPerCent` and `DriveConfig.InTorqueWindowTime`. The position limit is handled only on the PLC side.
If additional filtering is needed, it can also be configured on the drive side with the parameters:
`P1.4665.0.0 Damping time` and `P1.4668.0.0 Monitoring window torque`.
When the task is complete, the drive holds the clamping torque.

In some cases the target-torque calculation fails. The drive adds friction compensation into the torque regulation, which can produce a higher torque than expected and requested. The drive will never reach the target torque. In that case you need to exclude all compensation from the torque calculation by setting:
`P1.102223.0.0 – Selection of dynamic torque boost` to `None`.


View the library source at [`AxoCmmtAs.st`](https://github.com/Inxton/AXOpen/tree/3-unify-showcase/src/components.festo.drives/ctrl/src/AxoCmmtAs/AxoCmmtAs.st).

Expand Down
10 changes: 10 additions & 0 deletions src/components.festo.drives/docs/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,16 @@
on every run.
-->

### 0.61.1

**Bug fixes:**
- Fixed `AxoCmmtAs` move-absolute task to verify `InPositionWindow` tolerance (`ABS(Position - ActualPosition) <= Config.InPositionWindow`) at the end of movement before completing the move.
- Removed aborting torque-control task with error `1542`, when `targetPosReached` was raised.

**Other:**
- Annotated the `PROFIdriveTelegram_111_ZSW1` status signals with their hardware bit positions (X0–X15) in the attribute labels, and added matching bit-position comments to the ZSW1 mapping in `AxoCmmtAs`, clarifying which telegram bit drives each status signal.
- Documented the `InPositionWindow` positioning-tolerance parameter (provided by `AxoDrive_Config`) consumed by `AxoCmmtAs` move completion.

### 0.43.0

**Other:**
Expand Down
Loading
Loading