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}