Skip to main content

autocore_std/motion/
homing.rs

1//! Homing methods for CiA 402 servo drives.
2//!
3//! [`HomingMethod`] covers both hardware-delegated (drive-internal) homing
4//! and software-implemented homing where the [`Axis`](super::Axis) monitors
5//! [`AxisView`](super::AxisView) sensor signals.
6
7/// Homing methods for CiA 402 servo drives.
8///
9/// **Integrated** methods delegate to the drive's built-in CiA 402 homing
10/// mode (SDO 0x6098). The drive uses its own sensor inputs.
11///
12/// **Software** methods (no `Integrated` prefix) are implemented by the
13/// [`Axis`](super::Axis) struct, which monitors [`AxisView`](super::AxisView)
14/// sensor signals for edge triggers and captures the home position.
15#[derive(Debug, Clone, Copy, PartialEq, Eq)]
16pub enum HomingMethod {
17    // ── Hardware-delegated (drive handles it) ──
18
19    /// Hard stop in positive direction (torque foldback). CiA 402 code: -1.
20    HardStopPos,
21    /// Hard stop in negative direction (torque foldback). CiA 402 code: -2.
22    HardStopNeg,
23    /// Drive's integrated positive limit switch. CiA 402 code: 18.
24    IntegratedLimitSwitchPos,
25    /// Drive's integrated negative limit switch. CiA 402 code: 17.
26    IntegratedLimitSwitchNeg,
27    /// Drive's integrated home sensor, positive direction, rising edge. CiA 402 code: 19.
28    IntegratedHomeSensorPosRt,
29    /// Drive's integrated home sensor, negative direction, rising edge. CiA 402 code: 21.
30    IntegratedHomeSensorNegRt,
31    /// Drive's integrated home sensor, positive direction, falling edge. CiA 402 code: 22.
32    IntegratedHomeSensorPosFt,
33    /// Drive's integrated home sensor, negative direction, falling edge. CiA 402 code: 20.
34    IntegratedHomeSensorNegFt,
35    /// Current position as home (no motor movement). CiA 402 code: 37.
36    CurrentPosition,
37    /// Arbitrary CiA 402 homing method code (vendor-specific or non-standard).
38    Integrated(i8),
39
40    // ── Software-implemented (Axis monitors AxisView sensors) ──
41
42    /// Move positive, home on rising edge of positive limit switch.
43    LimitSwitchPosRt,
44    /// Move negative, home on rising edge of negative limit switch.
45    LimitSwitchNegRt,
46    /// Move positive, home on falling edge of positive limit switch.
47    LimitSwitchPosFt,
48    /// Move negative, home on falling edge of negative limit switch.
49    LimitSwitchNegFt,
50    /// Move positive, home on rising edge of home sensor.
51    HomeSensorPosRt,
52    /// Move negative, home on rising edge of home sensor.
53    HomeSensorNegRt,
54    /// Move positive, home on falling edge of home sensor.
55    HomeSensorPosFt,
56    /// Move negative, home on falling edge of home sensor.
57    HomeSensorNegFt,
58}
59
60impl HomingMethod {
61    /// True if the drive handles this method internally (hardware-delegated).
62    pub fn is_integrated(&self) -> bool {
63        match self {
64            Self::HardStopPos
65            | Self::HardStopNeg
66            | Self::IntegratedLimitSwitchPos
67            | Self::IntegratedLimitSwitchNeg
68            | Self::IntegratedHomeSensorPosRt
69            | Self::IntegratedHomeSensorNegRt
70            | Self::IntegratedHomeSensorPosFt
71            | Self::IntegratedHomeSensorNegFt
72            | Self::CurrentPosition
73            | Self::Integrated(_) => true,
74
75            Self::LimitSwitchPosRt
76            | Self::LimitSwitchNegRt
77            | Self::LimitSwitchPosFt
78            | Self::LimitSwitchNegFt
79            | Self::HomeSensorPosRt
80            | Self::HomeSensorNegRt
81            | Self::HomeSensorPosFt
82            | Self::HomeSensorNegFt => false,
83        }
84    }
85
86    /// CiA 402 method code for hardware-delegated methods.
87    ///
88    /// # Panics
89    ///
90    /// Panics if called on a software-implemented method.
91    /// Check [`is_integrated()`](Self::is_integrated) first.
92    pub fn cia402_code(&self) -> i8 {
93        match self {
94            Self::HardStopPos => -1,
95            Self::HardStopNeg => -2,
96            Self::IntegratedLimitSwitchPos => 18,
97            Self::IntegratedLimitSwitchNeg => 17,
98            Self::IntegratedHomeSensorPosRt => 19,
99            Self::IntegratedHomeSensorNegRt => 21,
100            Self::IntegratedHomeSensorPosFt => 22,
101            Self::IntegratedHomeSensorNegFt => 20,
102            Self::CurrentPosition => 37,
103            Self::Integrated(code) => *code,
104            _ => panic!("cia402_code() called on software homing method {:?}", self),
105        }
106    }
107
108    /// True if this method involves motor movement.
109    pub fn requires_motion(&self) -> bool {
110        !matches!(self, Self::CurrentPosition)
111    }
112}
113
114#[cfg(test)]
115mod tests {
116    use super::*;
117
118    #[test]
119    fn integrated_methods_are_integrated() {
120        assert!(HomingMethod::HardStopPos.is_integrated());
121        assert!(HomingMethod::HardStopNeg.is_integrated());
122        assert!(HomingMethod::IntegratedLimitSwitchPos.is_integrated());
123        assert!(HomingMethod::IntegratedLimitSwitchNeg.is_integrated());
124        assert!(HomingMethod::IntegratedHomeSensorPosRt.is_integrated());
125        assert!(HomingMethod::IntegratedHomeSensorNegRt.is_integrated());
126        assert!(HomingMethod::IntegratedHomeSensorPosFt.is_integrated());
127        assert!(HomingMethod::IntegratedHomeSensorNegFt.is_integrated());
128        assert!(HomingMethod::CurrentPosition.is_integrated());
129        assert!(HomingMethod::Integrated(35).is_integrated());
130    }
131
132    #[test]
133    fn software_methods_are_not_integrated() {
134        assert!(!HomingMethod::LimitSwitchPosRt.is_integrated());
135        assert!(!HomingMethod::LimitSwitchNegRt.is_integrated());
136        assert!(!HomingMethod::LimitSwitchPosFt.is_integrated());
137        assert!(!HomingMethod::LimitSwitchNegFt.is_integrated());
138        assert!(!HomingMethod::HomeSensorPosRt.is_integrated());
139        assert!(!HomingMethod::HomeSensorNegRt.is_integrated());
140        assert!(!HomingMethod::HomeSensorPosFt.is_integrated());
141        assert!(!HomingMethod::HomeSensorNegFt.is_integrated());
142    }
143
144    #[test]
145    fn cia402_codes_correct() {
146        assert_eq!(HomingMethod::HardStopPos.cia402_code(), -1);
147        assert_eq!(HomingMethod::HardStopNeg.cia402_code(), -2);
148        assert_eq!(HomingMethod::IntegratedLimitSwitchPos.cia402_code(), 18);
149        assert_eq!(HomingMethod::IntegratedLimitSwitchNeg.cia402_code(), 17);
150        assert_eq!(HomingMethod::IntegratedHomeSensorPosRt.cia402_code(), 19);
151        assert_eq!(HomingMethod::IntegratedHomeSensorNegRt.cia402_code(), 21);
152        assert_eq!(HomingMethod::IntegratedHomeSensorPosFt.cia402_code(), 22);
153        assert_eq!(HomingMethod::IntegratedHomeSensorNegFt.cia402_code(), 20);
154        assert_eq!(HomingMethod::CurrentPosition.cia402_code(), 37);
155        assert_eq!(HomingMethod::Integrated(35).cia402_code(), 35);
156    }
157
158    #[test]
159    #[should_panic]
160    fn cia402_code_panics_on_software_method() {
161        HomingMethod::LimitSwitchPosRt.cia402_code();
162    }
163
164    #[test]
165    fn requires_motion() {
166        assert!(HomingMethod::HardStopPos.requires_motion());
167        assert!(HomingMethod::IntegratedLimitSwitchPos.requires_motion());
168        assert!(HomingMethod::IntegratedHomeSensorPosRt.requires_motion());
169        assert!(!HomingMethod::CurrentPosition.requires_motion());
170        assert!(HomingMethod::LimitSwitchPosRt.requires_motion());
171        assert!(HomingMethod::HomeSensorPosRt.requires_motion());
172        assert!(HomingMethod::Integrated(35).requires_motion());
173    }
174}