# lcec_danfoss_fc302 — Danfoss FC302 with MCA124 EtherCAT Card Driver for the **Danfoss FC302 VFD** with **MCA124 EtherCAT option card** in [linuxcnc-ethercat](https://github.com/linuxcnc-ethercat/linuxcnc-ethercat). --- ## Table of Contents 1. [Hardware Identification](#1-hardware-identification) 2. [Prerequisites](#2-prerequisites) 3. [Build & Install](#3-build--install) 4. [PDO Layout](#4-pdo-layout) 5. [HAL Pins](#5-hal-pins) 6. [ethercat-conf.xml](#6-ethercat-confxml) 7. [modParams Reference](#7-modparams-reference) 8. [CiA 402 State Machine](#8-cia-402-state-machine) 9. [Infos-RO SDO Monitoring](#9-infos-ro-sdo-monitoring) 10. [Configurable Temperature Slot](#10-configurable-temperature-slot) 11. [FC302 Front Panel Requirements](#11-fc302-front-panel-requirements) 12. [GladeVCP Status Panel](#12-gladevcp-status-panel) 13. [Known Limitations & Quirks](#13-known-limitations--quirks) 14. [Troubleshooting](#14-troubleshooting) --- ## 1. Hardware Identification | Field | Value | |---|---| | Vendor ID | `0x0200008D` | | Product Code | `0x00000064` | | EtherCAT option card | MCA124 | | CiA 402 profile | **VL (velocity) mode only** | | Distributed Clocks | **Not supported** — never add `` | --- ## 2. Prerequisites ### IgH EtherCAT Master — EoE Ethernet over EtherCAT (EoE) is **not required** and is recommended to be disabled. With EoE enabled the master still works, but significantly more warning/error messages appear in `dmesg` during normal operation. To disable EoE at build time: ```bash # Pass to the IgH master configure script: ./configure --disable-eoe ``` Or if using a kernel module build, set `CONFIG_EC_EOE=n` in the kernel config. > **Note:** Disabling EoE is a recommendation, not a hard requirement. > The driver functions correctly with EoE enabled, but the reduced > log noise makes troubleshooting significantly easier. --- ## 3. Build & Install Copy `lcec_fc302.c` to `src/devices/`, then: ```bash cd ~/src/linuxcnc-ethercat/src make sudo make install ``` --- ## 4. PDO Layout ### Fixed, Non-Configurable PDO Containers The MCA124 firmware has a **completely fixed PDO object directory**. The IgH master attempts to dynamically assign PDO container indices via SDO `0x1C12`/`0x1C13`, but the drive **rejects any container index** other than its two factory-fixed entries. Any additional container (e.g. `0x1617`, `0x1A17`) causes SDO abort `0x06020000 "Object does not exist"`. **SM2 — RxPDO `0x1616` (master → drive):** | Object | Size | Description | |---|---|---| | `0x6040:00` | u16 | ControlWord | | `0x6042:00` | s16 | Target VL (velocity setpoint) | **SM3 — TxPDO `0x1A16` (drive → master):** | Object | Size | Description | |---|---|---| | `0x6041:00` | u16 | StatusWord | | `0x6044:00` | s16 | Actual VL | | `0x2651:00` | s16 | Speed [RPM] | | `0x2679:00` | s16 | Feedback [RPM] — see note below | | `0x264A:00` | s16 | Power [0.01 kW] | | `0x2650:00` | s16 | Torque [Nm] | | `0x2655:00` | s16 | Torque [% High Res, 0.1 %/digit] | | `0x2661:00` | s16 | Brake Energy Average | | `0x265E:00` | u16 | DC Link Voltage [V] | | configurable | u16 | Temperature slot (see [#10](#10-configurable-temperature-slot)) | > **Feedback [RPM] (`0x2679`):** In the tested setup, an inductive sensor > on terminal 33 monitors the motor shaft directly. The sensor's pulse > signal is processed by the FC302 and the resulting speed value is made > available in this PDO slot. The FC302 is not using this feedback for > closed-loop speed control — it is purely informational. > Terminal configuration: FC302 par. **5-15 = \[pulse input\]**. ### Why these additional objects are in the TxPDO The extended TxPDO mapping (objects beyond `0x6041`/`0x6044`) was confirmed working via `ethercat pdos -p 0` after the FC302 firmware was configured through MCT-10. The objects are part of the drive's own fixed PDO map and do not require dynamic mapping by the IgH master. --- ## 5. HAL Pins All pins appear under `lcec...*` — by convention `lcec.m0.FC302.*` when the XML uses `name="m0"` for the master and `name="FC302"` for the slave. ### 5.1 CiA 402 Core (cyclic, every servo cycle) | Pin | Type | Dir | Description | |---|---|---|---| | `srv-cia-controlword` | u32 | IN | CiA 402 ControlWord | | `srv-cia-statusword` | u32 | OUT | CiA 402 StatusWord | | `srv-target-vl` | s32 | IN | Velocity setpoint | | `srv-actual-vl` | s32 | OUT | Velocity feedback | | `modes-op-display` | u32 | OUT | Modes of operation display `0x6061` — **always active**, updated ~2×/s via acyclic SDO regardless of `sdoReadConfig` | | `slave-online` | bit | OUT | TRUE when slave is reachable | | `slave-oper` | bit | OUT | TRUE when slave is in OP state | ### 5.2 Infos-RO-PDO Group (cyclic, every servo cycle) | Pin | Type | Dir | Object | Unit | |---|---|---|---|---| | `Infos-RO-PDO.speed-rpm` | s32 | OUT | `0x2651` | RPM | | `Infos-RO-PDO.feedback-rpm` | s32 | OUT | `0x2679` | RPM (inductive sensor) | | `Infos-RO-PDO.power-kw` | s32 | OUT | `0x264A` | 0.01 kW/digit | | `Infos-RO-PDO.torque-nm` | s32 | OUT | `0x2650` | Nm | | `Infos-RO-PDO.torque-pct-highres` | s32 | OUT | `0x2655` | 0.1 %/digit | | `Infos-RO-PDO.brake-energy-avg` | s32 | OUT | `0x2661` | — | | `Infos-RO-PDO.dc-link-voltage` | u32 | OUT | `0x265E` | V | | `Infos-RO-PDO.` | s32/u32 | OUT | configurable | (see [#10](#10-configurable-temperature-slot)) | ### 5.3 Infos-RO Group (acyclic SDO, enabled via `sdoReadConfig`) Pins are only created when the corresponding bit in `sdoReadConfig` is set. `Infos-RO.sdo-busy` is only created when at least one bit is set. | Bit | Pin | Type | Object | Unit | |---|---|---|---|---| | 0 | `Infos-RO.motor-thermal-pct` | u32 | `0x2652` | % | | 1 | `Infos-RO.kty-temperature` | s32 | `0x2653` | °C | | 2 | `Infos-RO.heatsink-temp` | s32 | `0x2662` | °C | | 3 | `Infos-RO.inverter-thermal-pct` | u32 | `0x2663` | % | | 4 | `Infos-RO.ctrl-card-temp` | s32 | `0x2667` | °C | | 5 | `Infos-RO.operating-hours` | u32 | `0x25DC` | h | | 6 | `Infos-RO.running-hours` | u32 | `0x25DD` | h | | 7 | `Infos-RO.kwh-counter` | u32 | `0x25DE` | kWh | | — | `Infos-RO.sdo-busy` | bit | — | TRUE while request in-flight | --- ## 6. ethercat-conf.xml ```xml ``` --- ## 7. modParams Reference All parameters are written as **startup SDOs** during the PREOP→SAFEOP transition via `ecrt_slave_config_sdo*()`. They are applied once at startup and do not change at runtime. ### CiA 402 Velocity Ramps | modParam | SDO | Type | Description | |---|---|---|---| | `accelDeltaSpeed` | `0x6048:01` | u32 | Accel numerator [vel-unit] | | `accelDeltaTime` | `0x6048:02` | u16 | Accel denominator (max 65535) | | `decelDeltaSpeed` | `0x6049:01` | u32 | Decel numerator [vel-unit] | | `decelDeltaTime` | `0x6049:02` | u16 | Decel denominator (max 65535) | Ramp rate = `deltaSpeed / deltaTime` in velocity-units per time-unit. ### VL Dimension Factor | modParam | SDO | Type | Description | |---|---|---|---| | `vlDimNumerator` | `0x604C:01` | s32 | Must not be 0 | | `vlDimDenominator` | `0x604C:02` | s32 | Must not be 0 | `v_physical = v_raw × numerator / denominator` ### FC302-Specific Ramp Times | modParam | SDO | FC302 par. | Description | |---|---|---|---| | `ramp1Up` | `0x2155:00` | 3-41 | Ramp 1 up time | | `ramp1Down` | `0x2156:00` | 3-42 | Ramp 1 down time | | `ramp2Up` | `0x215F:00` | 3-51 | Ramp 2 up time | | `ramp2Down` | `0x2160:00` | 3-52 | Ramp 2 down time | | `jogRampTime` | `0x217C:00` | 3-80 | Jog ramp time | | `qstopRampTime` | `0x217D:00` | 3-81 | Quick-stop ramp time | ### Jog Speeds | modParam | SDO | FC302 par. | Description | |---|---|---|---| | `busJog1Speed` | `0x237A:00` | 8-90 | Bus jog 1 speed (u16) | | `busJog2Speed` | `0x237B:00` | 8-91 | Bus jog 2 speed (u16) | ### Speed Limits `vlMinimum` and `vlMaximum` are **not writable via SDO** on this firmware (abort `0x08000020 "Data cannot be transferred to the application"`). Set speed limits directly on the FC302: | FC302 par. | Description | |---|---| | P4-11 | Motor Speed Low Limit [RPM] | | P4-12 | Motor Speed High Limit [RPM] | --- ## 8. CiA 402 State Machine ### Enable Sequence (400 V present) ``` CW = 0x06 → SW ≈ 0x231 "Ready To Switch On" CW = 0x07 → SW ≈ 0x233 "Switched On" CW = 0x0F → SW ≈ 0x237 "Operation Enabled" ← motor runs ``` ### Fault Reset ``` CW = 0x80 → fault acknowledged CW = 0x00 → clear reset bit → repeat enable sequence ``` > **STO (Safe Torque Off):** When terminal 37 goes LOW the drive trips > with alarm A68. The fault can be reset via `CW = 0x80` once terminal 37 > returns HIGH (safety chain cleared). No manual LCP interaction is required > if FC302 **P14-20 = [1] Auto Reset** and **P8-01 = [0] EtherCAT control**. ### Key StatusWord Values | Decimal | Hex | State | |---|---|---| | 704 | `0x2C0` | Switch On Disabled (power-on default) | | 689 | `0x2B1` | Ready To Switch On, Remote active | | 177 | `0x0B1` | Ready To Switch On, **Remote NOT active** (Hand/Local) | | 696 | `0x2B8` | Fault + Remote — send `CW = 0x80` | | 136 | `0x088` | Fault, no Remote — check LCP for alarm code | ### StatusWord Bits | Bit | Meaning when 1 | |---|---| | 0 | Ready to Switch On | | 1 | Switched On | | 2 | Operation Enabled | | **3** | **Fault active** | | 4 | Voltage Enabled (24 V logic present) | | 5 | Quick Stop NOT active (inverted) | | 6 | Switch On Disabled | | 7 | Warning | | **9** | **Remote — EtherCAT controls the drive** | > **Bit 9 = 0 (not Remote):** drive ignores ControlWord. Press the > **[Auto/Remote]** key on the LCP panel. --- ## 9. Infos-RO SDO Monitoring ### Mechanism The driver uses `ecrt_slave_config_create_sdo_request()` for acyclic SDO reads. A round-robin scheduler processes one channel per servo cycle with no artificial cooldown — the FC302 mailbox RTT (~30–50 ms) naturally limits the rate to approximately **2 updates per second per channel**. A **5-second startup delay** (`FC302_MON_STARTDELAY = 5000` cycles at 1 kHz) is applied before the first request fires. This allows a stale `0x6502` response left in the FC302 mailbox buffer by the lcec_cia402 framework to drain before monitoring begins, preventing "wrong SDO" collisions and Sync Manager Watchdog faults. `modes-op-display` (`0x6061`) uses its own dedicated SDO request handle and is always polled regardless of `sdoReadConfig`. ### Enabling Channels ```xml ``` ### Reading Without HAL (CLI) ```bash # Motor current example ethercat upload -p 0 -t int16 0x264E 0x00 # DC link voltage ethercat upload -p 0 -t uint16 0x265E 0x00 # Operating hours ethercat upload -p 0 -t uint32 0x25DC 0x00 # Live watch watch -n 2 "ethercat upload -p 0 -t uint32 0x25DC 0x00" ``` --- ## 10. Configurable Temperature Slot The last entry in the TxPDO is a 16-bit temperature slot whose **source object** depends on what is configured in FC302 par. **12-22.9** (displayed readout assignment). The driver must be told which object to expect via the `tempSlotSource` modParam so that it registers the correct PDO offset, creates the appropriately named HAL pin, and applies the correct type. | `tempSlotSource` | PDO object | HAL pin | Type | |---|---|---|---| | `1618` | `0x2652` | `Infos-RO-PDO.motor-thermal-pct` | u32 [%] | | `1619` | `0x2653` | `Infos-RO-PDO.kty-temperature` | s32 [°C] | | `1634` | `0x2662` | `Infos-RO-PDO.heatsink-temp` | s32 [°C] | | `1635` | `0x2663` | `Infos-RO-PDO.inverter-thermal-pct` | u32 [%] | | `1639` | `0x2667` | `Infos-RO-PDO.ctrl-card-temp` | s32 [°C] ← **default** | At startup the driver logs the resolved slot: ``` LCEC: FC302 m0.FC302: temp slot PDO object = 0x2667 (par 1639) LCEC: FC302 m0.FC302: last PDO temp slot = Infos-RO-PDO.ctrl-card-temp (par 1639) ``` --- ## 11. FC302 Front Panel Requirements The following parameters must be set on the FC302 itself (via LCP or MCT-10) before running LinuxCNC. A Danfoss MCT-10 parameter export is included in this repository for reference. | Parameter | Value | Description | |---|---|---| | **P1-00** | EtherCAT source | Reference source | | **P4-10** | `[0] Both directions` | Enables forward and reverse | | **P4-11** | 0 RPM | Motor speed low limit | | **P4-12** | application-specific | Motor speed high limit | | **P8-01** | `[0] EtherCAT` | Control site | | **P8-10** | `7` (VL CiA 402) | Control Word Profile — **set automatically** by driver | | **P14-20** | `[1] Auto Reset` | Auto-reset after alarm (enables bus fault reset) | > **P8-10** (`0x232A:00 = 0x0007`) is written automatically as a startup > SDO after the PDO assignment. Manual configuration is not required. > **Speed limits** (`vlMinimum` / `vlMaximum`) are not writable via SDO > on this firmware. Always use P4-11 / P4-12. --- ## 12. GladeVCP Status Panel A GladeVCP panel for LinuxCNC AXIS is available in the `glade/fc302/` subdirectory: ``` glade/fc302/ ├── fc302_status.glade # GTK3 UI definition └── fc302_status_handler.py # Python handler (decodes state, colors bits) ``` The panel adds a **FC302 Status** tab showing: - Slave online/OP state - CiA 402 Mode of Operation (decoded name) - State machine state (color-coded: green = OK, orange = idle, red = fault) - NOT REMOTE warning when bit 9 is cleared - All 16 bits of StatusWord and ControlWord with labels and colors ### Integration **`machine.ini`:** ```ini [DISPLAY] GLADEVCP = -c fc302panel -u glade/fc302/fc302_status_handler.py glade/fc302/fc302_status.glade EMBED_TAB_NAME = FC302 Status EMBED_TAB_LOCATION = ntb_preview [HAL] HALFILE = your_main.hal POSTGUI_HALFILE = postgui.hal ``` **`postgui.hal`** (loaded after GUI, when GladeVCP pins exist): ```hal net fc302-sw lcec.m0.FC302.srv-cia-statusword => fc302panel.statusword net fc302-cw lcec.m0.FC302.srv-cia-controlword => fc302panel.controlword net fc302-mo lcec.m0.FC302.modes-op-display => fc302panel.modes-op net fc302-onl lcec.m0.FC302.slave-online => fc302panel.slave-online net fc302-op lcec.m0.FC302.slave-oper => fc302panel.slave-oper ``` > The GladeVCP connections **must** be in `POSTGUI_HALFILE`, not in the > main HAL file. GladeVCP pins do not exist until after the GUI starts. --- ## 13. Known Limitations & Quirks ### Fixed PDO containers The MCA124 only accepts `0x1616` (RxPDO) and `0x1A16` (TxPDO). Any other container index causes AL error `0x001E "Invalid input configuration"`. ### `0x6502` SDO error at startup The lcec_cia402 framework internally attempts an SDO upload of `0x6502` (Supported Drive Modes). The FC302 MCA124 does not support this object, producing two messages in dmesg at every startup: ``` EtherCAT WARNING 0-0: Received mailbox protocol 0x02 as response. LCEC: slave m0.FC302: Failed to execute SDO upload (0x6502:0x00 ...) ``` These are **harmless**. The driver suppresses them by temporarily setting `RTAPI_MSG_NONE` around the `lcec_cia402_register_channel()` call. The `srv-supported-modes` and `srv-supports-mode-*` pins always read 0. ### `0x6046:01 / 0x6046:02` not writable VL velocity limits return SDO abort `0x08000020` regardless of the value. Use FC302 P4-11 / P4-12 instead. ### `enable_vl = 0` required Setting `enable_vl = 1` in the CiA 402 options also registers PDO entries for `0x6043`, `0x6046:01`, `0x6046:02` — none of which are PDO-mappable on the MCA124. This causes fatal startup errors. Target VL (`0x6042`) and actual VL (`0x6044`) are therefore registered manually. ### No Distributed Clocks Never add `` to the XML for this slave. ### Digital I/O not accessible via EtherCAT The MCA124 does not expose FC302 digital inputs or outputs as EtherCAT process data. Configure digital I/O locally via FC302 parameter group 5-xx. --- ## 14. Troubleshooting ### Drive stays in PREOP E `0x232A:00` (Control Word Profile) write failed, or PDO assignment was rejected. ```bash ethercat slaves # must show OP + dmesg | grep -E "EtherCAT|LCEC" | tail -30 ``` Verify FC302 P8-50 = 0 and that no conflicting manual setting of P8-10 exists. --- ### StatusWord bit 9 = 0 (Not Remote) Drive is in Hand/Local mode. Press **[Auto/Remote]** on the LCP. --- ### Fault in StatusWord (bit 3 = 1) ```bash # Fault reset via HAL: halcmd setp lcec.m0.FC302.srv-cia-controlword 128 halcmd setp lcec.m0.FC302.srv-cia-controlword 0 # Read active alarm code: ethercat upload -p 0 -t uint16 0x603F 0x00 ``` For STO faults: terminal 37 must return HIGH before the reset takes effect. --- ### SM Watchdog — all slaves drop to SAFEOP Caused by EtherCAT datagram timeout, typically a mailbox collision at startup. The 5-second `FC302_MON_STARTDELAY` prevents this. If it still occurs, check dmesg for `"wrong SDO response"` and consider increasing `FC302_MON_STARTDELAY` in the source. --- ### Working counter not reaching expected value ```bash ethercat slaves # All slaves should show: OP + ``` If the FC302 remains in PREOP, the working counter will be low. Resolve the PREOP issue first (see above). --- *Tested with LinuxCNC 2.9, linuxcnc-ethercat, IgH EtherCAT Master with `--disable-eoe`, FC302 firmware 08.34 & 7.xx, MCA124 option card.*