ev3_drivebase/drivebase/
brake_mode.rs

1use super::DriveBase;
2use ev3dev_lang_rust::{Ev3Error, motors::TachoMotor};
3
4impl DriveBase {
5    /// Sets the brake mode for both motors.
6    ///
7    /// The brake mode determines how the motors behave when stopped:
8    ///
9    /// - **Coast**: Motors freely coast to a stop (no braking)
10    /// - **Brake**: Motors actively brake but don't hold position
11    /// - **Hold**: Motors hold their current position with power
12    ///
13    /// # Parameters
14    ///
15    /// - `brake_mode`: The desired brake mode to apply to both motors
16    ///
17    /// # Errors
18    ///
19    /// Returns an error if the brake mode cannot be set on either motor.
20    ///
21    /// # Examples
22    ///
23    /// ```no_run
24    /// use ev3_drivebase::{DriveBase, Motor, Direction, BrakeMode};
25    /// use ev3_drivebase::ev3dev_lang_rust::{Ev3Error, motors::MotorPort};
26    ///
27    /// fn main() -> Result<(), Ev3Error> {
28    ///     let left = Motor::new(MotorPort::OutA, Direction::Clockwise);
29    ///     let right = Motor::new(MotorPort::OutB, Direction::CounterClockwise);
30    ///     let drivebase = DriveBase::new(left, right, 43.2, 185.0)?;
31    ///
32    ///     // Use Hold mode for precise positioning
33    ///     drivebase.set_brake_mode(BrakeMode::Hold)?;
34    ///
35    ///     Ok(())
36    /// }
37    /// ```
38    pub fn set_brake_mode(&self, brake_mode: BrakeMode) -> Result<&Self, Ev3Error> {
39        self.left.set_stop_action(brake_mode.as_ref())?;
40        self.right.set_stop_action(brake_mode.as_ref())?;
41        Ok(self)
42    }
43
44    /// Gets the current brake mode for both motors.
45    ///
46    /// If the motors have different brake modes, this method will set the right motor's
47    /// brake mode to match the left motor's and return the left motor's mode.
48    ///
49    /// # Errors
50    ///
51    /// Returns an error if the brake mode cannot be read or set.
52    ///
53    /// # Examples
54    ///
55    /// ```no_run
56    /// use ev3_drivebase::{DriveBase, Motor, Direction, BrakeMode};
57    /// use ev3_drivebase::ev3dev_lang_rust::{Ev3Error, motors::MotorPort};
58    ///
59    /// fn main() -> Result<(), Ev3Error> {
60    ///     let left = Motor::new(MotorPort::OutA, Direction::Clockwise);
61    ///     let right = Motor::new(MotorPort::OutB, Direction::CounterClockwise);
62    ///     let drivebase = DriveBase::new(left, right, 43.2, 185.0)?;
63    ///
64    ///     let current_mode = drivebase.get_brake_mode()?;
65    ///     println!("Current brake mode: {:?}", current_mode);
66    ///
67    ///     Ok(())
68    /// }
69    /// ```
70    pub fn get_brake_mode(&self) -> Result<BrakeMode, Ev3Error> {
71        let left_brake_mode: BrakeMode = self.left.get_stop_action()?.into();
72        let right_brake_mode: BrakeMode = self.right.get_stop_action()?.into();
73
74        if right_brake_mode != left_brake_mode {
75            self.right.set_stop_action(left_brake_mode.as_ref())?;
76        }
77
78        Ok(left_brake_mode)
79    }
80}
81
82/// The brake mode determines how motors behave when stopped.
83///
84/// Each mode offers different trade-offs between stopping speed, position accuracy,
85/// and power consumption:
86///
87/// - **Coast**: Lowest power consumption, but least precise stopping
88/// - **Brake**: Good balance between speed and precision
89/// - **Hold**: Most precise, but highest power consumption
90///
91/// # Examples
92///
93/// ```
94/// use ev3_drivebase::BrakeMode;
95///
96/// // For general movement where exact stopping position doesn't matter
97/// let casual = BrakeMode::Coast;
98///
99/// // For controlled stopping without position holding
100/// let controlled = BrakeMode::Brake;
101///
102/// // For precise positioning tasks
103/// let precise = BrakeMode::Hold;
104/// ```
105#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
106pub enum BrakeMode {
107    /// The motor will freely coast to a stop.
108    ///
109    /// No active braking is applied. The motor will gradually slow down due to friction.
110    /// This mode uses the least power but provides the least control over stopping position.
111    Coast,
112
113    /// The motor will actively brake, resisting motion until it comes to a stop.
114    ///
115    /// Slows the motor faster than `Coast` but does not hold the final position.
116    /// After stopping, the motor can be moved freely by external forces.
117    Brake,
118
119    /// The motor will actively hold its current position once stopped.
120    ///
121    /// Provides the most precise stopping and maintains position against external forces.
122    /// This mode consumes more power as it continuously applies holding torque.
123    Hold,
124}
125
126impl AsRef<str> for BrakeMode {
127    fn as_ref(&self) -> &str {
128        match self {
129            Self::Coast => TachoMotor::STOP_ACTION_COAST,
130            Self::Brake => TachoMotor::STOP_ACTION_BRAKE,
131            Self::Hold => TachoMotor::STOP_ACTION_HOLD,
132        }
133    }
134}
135
136impl From<&str> for BrakeMode {
137    fn from(value: &str) -> Self {
138        match value {
139            TachoMotor::STOP_ACTION_BRAKE => Self::Brake,
140            TachoMotor::STOP_ACTION_HOLD => Self::Hold,
141            _ => Self::Coast,
142        }
143    }
144}
145
146impl From<String> for BrakeMode {
147    fn from(value: String) -> Self {
148        Self::from(value.as_str())
149    }
150}