stepper_motion/config/
motor.rs

1//! Motor configuration from TOML.
2
3use heapless::String;
4use serde::Deserialize;
5
6use super::limits::SoftLimits;
7use super::units::{Degrees, DegreesPerSec, DegreesPerSecSquared, Microsteps};
8
9/// Complete motor configuration from TOML.
10#[derive(Debug, Clone, Deserialize)]
11pub struct MotorConfig {
12    /// Human-readable name (max 32 chars).
13    pub name: String<32>,
14
15    /// Base steps per revolution (typically 200 for 1.8° motors).
16    pub steps_per_revolution: u16,
17
18    /// Microstep setting (1, 2, 4, 8, 16, 32, etc.).
19    pub microsteps: Microsteps,
20
21    /// Gear ratio (output:input, e.g., 5.0 means 5:1 reduction).
22    #[serde(default = "default_gear_ratio")]
23    pub gear_ratio: f32,
24
25    /// Maximum angular velocity in degrees per second.
26    #[serde(rename = "max_velocity_deg_per_sec")]
27    pub max_velocity: DegreesPerSec,
28
29    /// Maximum angular acceleration in degrees per second squared.
30    #[serde(rename = "max_acceleration_deg_per_sec2")]
31    pub max_acceleration: DegreesPerSecSquared,
32
33    /// Invert direction pin logic.
34    #[serde(default)]
35    pub invert_direction: bool,
36
37    /// Optional soft limits.
38    #[serde(default)]
39    pub limits: Option<SoftLimits>,
40
41    /// Optional backlash compensation in degrees.
42    #[serde(default, rename = "backlash_compensation_deg")]
43    pub backlash_compensation: Option<Degrees>,
44}
45
46fn default_gear_ratio() -> f32 {
47    1.0
48}
49
50impl MotorConfig {
51    /// Calculate total steps per output shaft revolution.
52    pub fn total_steps_per_revolution(&self) -> u32 {
53        (self.steps_per_revolution as f32 * self.microsteps.value() as f32 * self.gear_ratio)
54            as u32
55    }
56
57    /// Calculate steps per degree of output rotation.
58    pub fn steps_per_degree(&self) -> f32 {
59        self.total_steps_per_revolution() as f32 / 360.0
60    }
61}
62
63#[cfg(test)]
64mod tests {
65    use super::*;
66
67    #[test]
68    fn test_total_steps() {
69        let config = MotorConfig {
70            name: String::try_from("test").unwrap(),
71            steps_per_revolution: 200,
72            microsteps: Microsteps::SIXTEENTH,
73            gear_ratio: 2.0,
74            max_velocity: DegreesPerSec(360.0),
75            max_acceleration: DegreesPerSecSquared(720.0),
76            invert_direction: false,
77            limits: None,
78            backlash_compensation: None,
79        };
80
81        // 200 * 16 * 2.0 = 6400
82        assert_eq!(config.total_steps_per_revolution(), 6400);
83    }
84}