From fd96eebe0aec1f6c6a0277a2d4be70190cec3e11 Mon Sep 17 00:00:00 2001 From: "blazej.kuhajda" Date: Mon, 1 Jun 2026 06:53:16 +0200 Subject: [PATCH 1/4] disable dynamic boost --- .../ctrl/src/AxoCmmtAs/AxoCmmtAs.st | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/components.festo.drives/ctrl/src/AxoCmmtAs/AxoCmmtAs.st b/src/components.festo.drives/ctrl/src/AxoCmmtAs/AxoCmmtAs.st index 06bcc41f2..829e028ea 100644 --- a/src/components.festo.drives/ctrl/src/AxoCmmtAs/AxoCmmtAs.st +++ b/src/components.festo.drives/ctrl/src/AxoCmmtAs/AxoCmmtAs.st @@ -3462,6 +3462,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#1542, eAxoMessageCategory#Error); + // MC_TorqueControlErrorID := DINT#1542; + // State := UINT#129; + // END_IF; + // END_IF; + IF State = UINT#124 THEN Busy := TRUE; Active := TRUE; From 9ccb278dd72790ba02ccfd6fc3f4aa24a17d9f91 Mon Sep 17 00:00:00 2001 From: "blazej.kuhajda" Date: Mon, 1 Jun 2026 14:35:51 +0200 Subject: [PATCH 2/4] wip --- .../ctrl/src/AxoDrives/AxoDrive_Config.st | 2 + .../ctrl/src/AxoCmmtAs/AxoCmmtAs.st | 52 ++++++++++--------- .../src/PROFIdrive/PROFIdriveTelegram_111.st | 32 ++++++------ 3 files changed, 45 insertions(+), 41 deletions(-) diff --git a/src/components.drives/ctrl/src/AxoDrives/AxoDrive_Config.st b/src/components.drives/ctrl/src/AxoDrives/AxoDrive_Config.st index 7786cefea..8a490c5b0 100644 --- a/src/components.drives/ctrl/src/AxoDrives/AxoDrive_Config.st +++ b/src/components.drives/ctrl/src/AxoDrives/AxoDrive_Config.st @@ -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 diff --git a/src/components.festo.drives/ctrl/src/AxoCmmtAs/AxoCmmtAs.st b/src/components.festo.drives/ctrl/src/AxoCmmtAs/AxoCmmtAs.st index 829e028ea..53c8698e5 100644 --- a/src/components.festo.drives/ctrl/src/AxoCmmtAs/AxoCmmtAs.st +++ b/src/components.festo.drives/ctrl/src/AxoCmmtAs/AxoCmmtAs.st @@ -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]; @@ -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 @@ -3482,8 +3483,8 @@ NAMESPACE AXOpen.Components.Festo.Drives // RETURN; // END_IF; // IF Parametrization.Outputs.Error THEN - // Messenger.Activate( UINT#1542, eAxoMessageCategory#Error); - // MC_TorqueControlErrorID := DINT#1542; + // Messenger.Activate( UINT#1543, eAxoMessageCategory#Error); + // MC_TorqueControlErrorID := DINT#1543; // State := UINT#129; // END_IF; // END_IF; @@ -3539,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 Date: Mon, 1 Jun 2026 20:17:14 +0200 Subject: [PATCH 3/4] ocs(components.festo.drives): document PR #1166 fix Document the AxoCmmtAs torque-control position-loss fix: in-position window gate, ZSW1 bit-position annotations, and the disabled 1542 torque-control guard. - per-library CHANGELOG 0.61.1 + GitVersion.yml bump - TROUBLES: position-loss + 1542 issues, ZSW1 diagnostics, InPositionWindow tuning, known limitations - AxoCmmtAs.md: positioning-tolerance section - central CHANGELOG.md: [FIX] entry Refs #1152, #1166 --- CHANGELOG.md | 22 ++++++++ GitVersion.yml | 2 +- src/components.festo.drives/docs/AxoCmmtAs.md | 12 +++++ src/components.festo.drives/docs/CHANGELOG.md | 10 ++++ src/components.festo.drives/docs/TROUBLES.md | 51 +++++++++++++++++++ 5 files changed, 96 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1dad8197d..4c7b9d36e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,25 @@ +### [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] `axdev` password guard contradicted the secrets complexity policy **Note:** Bug fix in `src/axopen.dev`. Branch: `feat/axdev-user-secrets-loader`. diff --git a/GitVersion.yml b/GitVersion.yml index 8efe7f98c..a4cb25032 100644 --- a/GitVersion.yml +++ b/GitVersion.yml @@ -1,5 +1,5 @@ mode: ContinuousDeployment -next-version: 0.61.0 +next-version: 0.61.1 branches: main: regex: ^master$|^main$ diff --git a/src/components.festo.drives/docs/AxoCmmtAs.md b/src/components.festo.drives/docs/AxoCmmtAs.md index b160f408a..adff7f7ad 100644 --- a/src/components.festo.drives/docs/AxoCmmtAs.md +++ b/src/components.festo.drives/docs/AxoCmmtAs.md @@ -26,6 +26,18 @@ Generated documentation for the `AxoCmmtAs` component. [!code-pascal[](../../showcase/app/src/components.festo.drives/Documentation/AxoCmmtAs_Showcase.st?name=Usage)] +## 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. + ## Source 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). diff --git a/src/components.festo.drives/docs/CHANGELOG.md b/src/components.festo.drives/docs/CHANGELOG.md index d4eda302a..bd3bacb92 100644 --- a/src/components.festo.drives/docs/CHANGELOG.md +++ b/src/components.festo.drives/docs/CHANGELOG.md @@ -23,6 +23,16 @@ on every run. --> +### 0.61.1 + +**Bug fixes:** +- Fixed `AxoCmmtAs` losing axis position while in torque control (issue #1152). A positioning move no longer completes on the `Telegram111_In.ZSW1.targetPosReached` bit alone — it now additionally requires the actual position to be within the `InPositionWindow` tolerance (`ABS(Position - ActualPosition) <= Config.InPositionWindow`) before advancing past the target-reached step. +- Removed an unstable torque-control guard that spuriously raised programming error `1542` when `targetPosReached` was asserted during torque-control states. The check is disabled pending further investigation. + +**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:** diff --git a/src/components.festo.drives/docs/TROUBLES.md b/src/components.festo.drives/docs/TROUBLES.md index 5cdc2ba7d..fc7979268 100644 --- a/src/components.festo.drives/docs/TROUBLES.md +++ b/src/components.festo.drives/docs/TROUBLES.md @@ -1,5 +1,56 @@ # Troubleshooting +## Common issues + +### A positioning move reports complete while the axis is not at the commanded target + +**What you observe** — After a torque-control phase, a subsequent absolute positioning move advances as "in position", but `ActualPosition` differs noticeably from the commanded `Position` (the axis appears to have "lost" its position). + +**Why it happens** — The Festo CMMT-AS drive can assert the `Telegram111_In.ZSW1.targetPosReached` (bit X10) status signal while the mechanical position is still outside an acceptable band — for example when the preceding torque-control phase disturbed the axis. Acting on that bit alone lets the move sequence advance prematurely. + +**What to check** — `AxoCmmtAs` gates the target-reached transition on both the `targetPosReached` bit *and* `ABS(Position - ActualPosition) <= _AxisReference^.Config.InPositionWindow`. Tune `InPositionWindow` (see [Diagnostics](#diagnostics)): +- Too **small** → the move never satisfies the window and the sequence stalls just before completing. +- Too **large** → the move completes while the axis is still off target (the original symptom). + +### Programming error `1542` raised during torque control + +**What you observe** — Message `1542` (`eAxoMessageCategory#ProgrammingError`) is activated and `MC_TorqueControlErrorID` is set to `1542` while the axis is in a torque-control state. + +**Why it happens** — A guard previously flagged `targetPosReached` becoming true during torque-control states (`126`/`127`) as a programming error. That guard proved unreliable and is disabled in this release. + +**What to check** — If you still hit `1542` during torque control, you are running an older build; update to a build that includes this fix. The guard is intentionally removed pending further investigation, so it should no longer fire. + +## Diagnostics + +Read the drive's status from the cyclic PROFIdrive telegram 111 input word `Telegram111_In.ZSW1`. As of this release each signal carries its hardware bit position in the attribute label: + +| Signal (`ZSW1.…`) | Bit | Meaning | +|---|---|---| +| `targetPosReached` | X10 | Drive reports the commanded target position has been reached | +| `operationEnabled` | X2 | Power stage enabled, drive following commands | +| `readyForSwitchOn` | X0 | Drive ready to be switched on | +| `ready` | X1 | Drive ready | +| `faultPresent` | X3 | A drive fault is active | +| `warningActive` | X7 | A drive warning is active | +| `switchingOnInhibitedActive` | X6 | Switch-on inhibit active | +| `noQuickStopActive` | X5 | Quick-stop *not* active (TRUE = normal operation) | +| `noCoastingActive` | X4 | Coast-stop *not* active (TRUE = normal operation) | +| `followingErrorInTolerance` | X8 | Following error within tolerance | +| `driveStopped` | X13 | Drive is stopped | + +For positioning precision, the relevant tuning parameter lives in the drive's `AxoDrive_Config` (from the `components.drives` base library): + +| Parameter | Type | Default | Purpose | +|---|---|---|---| +| `InPositionWindow` | `LREAL` | `0.05` | Maximum allowed `ABS(Position - ActualPosition)` (in axis position units) for a positioning move to count as complete, in addition to the drive's `targetPosReached` bit. | + +## Known limitations + +- The dynamic torque-boost parameter write (PNU `13073`, "Selection of dynamic torque boost") is not implemented — the code path is present but disabled. +- The torque-control "target reached during torque control" safety guard (programming error `1542`) is currently disabled and under investigation. + +## Support + Unfortunately, we don't have a direct solution to your problem at the moment. If you encounter any issues, please [file a report on our GitHub](https://github.com/inxton/AXOpen/issues/new/choose). We appreciate your feedback and patience. --- From eafc42ff48b024b4e9bffad639c63296966b261a Mon Sep 17 00:00:00 2001 From: "blazej.kuhajda" Date: Tue, 2 Jun 2026 06:57:44 +0200 Subject: [PATCH 4/4] doc --- src/components.festo.drives/docs/AxoCmmtAs.md | 11 ++++++++++- src/components.festo.drives/docs/CHANGELOG.md | 4 ++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/components.festo.drives/docs/AxoCmmtAs.md b/src/components.festo.drives/docs/AxoCmmtAs.md index adff7f7ad..3c73a0d8b 100644 --- a/src/components.festo.drives/docs/AxoCmmtAs.md +++ b/src/components.festo.drives/docs/AxoCmmtAs.md @@ -38,7 +38,16 @@ The window is configured on the drive's `AxoDrive_Config` (provided by the `comp See [`TROUBLES.md`](TROUBLES.md#a-positioning-move-reports-complete-while-the-axis-is-not-at-the-commanded-target) for tuning guidance. -## Source +## 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). diff --git a/src/components.festo.drives/docs/CHANGELOG.md b/src/components.festo.drives/docs/CHANGELOG.md index bd3bacb92..ee9e249f2 100644 --- a/src/components.festo.drives/docs/CHANGELOG.md +++ b/src/components.festo.drives/docs/CHANGELOG.md @@ -26,8 +26,8 @@ ### 0.61.1 **Bug fixes:** -- Fixed `AxoCmmtAs` losing axis position while in torque control (issue #1152). A positioning move no longer completes on the `Telegram111_In.ZSW1.targetPosReached` bit alone — it now additionally requires the actual position to be within the `InPositionWindow` tolerance (`ABS(Position - ActualPosition) <= Config.InPositionWindow`) before advancing past the target-reached step. -- Removed an unstable torque-control guard that spuriously raised programming error `1542` when `targetPosReached` was asserted during torque-control states. The check is disabled pending further investigation. +- 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.