omnitiles/motors/
tilt_motor.rs

1// SPDX-License-Identifier: MIT
2// © 2025–2026 Christopher Liu
3
4//! Tilt actuator interface built on top of `CanMotor`.
5//!
6//! This module converts between the motor's internal shaft angle representation and a physical tile
7//! tilt angle, using a configurable gear ratio.
8
9use crate::drivers::Gim6010;
10
11/// High-level tilt motor wrapped around a `CanMotor`.
12///
13/// Geometry parameters:
14/// - `gear_ratio` — number of motor revolutions per tile revolution.
15pub struct TiltMotor<const DEV_ADDR: u16> {
16    motor: Gim6010<DEV_ADDR>,
17    gear_ratio: f32,
18}
19
20impl<const DEV_ADDR: u16> TiltMotor<DEV_ADDR> {
21    /// Create a new `TiltMotor` from an underlying `CanMotor` and a gear ratio.
22    pub fn new(motor: Gim6010<DEV_ADDR>, gear_ratio: f32) -> Self {
23        Self { motor, gear_ratio }
24    }
25
26    /// Access the underlying `CanMotor`.
27    #[inline]
28    pub fn inner_motor(&mut self) -> &mut Gim6010<DEV_ADDR> {
29        &mut self.motor
30    }
31
32    /// Convert a raw encoder value [0..65535] into motor shaft angle in radians.
33    #[inline]
34    pub fn shaft_angle_rad_from_raw(&self, raw: u16) -> f32 {
35        Gim6010::<DEV_ADDR>::raw_angle_to_rad(raw)
36    }
37
38    /// Convert a raw encoder value [0..65535] into motor shaft angle in degrees.
39    #[inline]
40    pub fn shaft_angle_deg_from_raw(&self, raw: u16) -> f32 {
41        Gim6010::<DEV_ADDR>::raw_angle_to_deg(raw)
42    }
43
44    /// Convert a desired motor shaft angle (radians) into a raw encoder value.
45    #[inline]
46    pub fn raw_for_shaft_angle_rad(&self, angle_rad: f32) -> u16 {
47        Gim6010::<DEV_ADDR>::angle_rad_to_raw(angle_rad)
48    }
49
50    /// Convert a desired motor shaft angle (degrees) into a raw encoder value.
51    #[inline]
52    pub fn raw_for_shaft_angle_deg(&self, angle_deg: f32) -> u16 {
53        Gim6010::<DEV_ADDR>::angle_deg_to_raw(angle_deg)
54    }
55
56    /// Convert a raw encoder value into tile tilt angle in radians.
57    #[inline]
58    pub fn tile_angle_rad_from_raw(&self, raw: u16) -> f32 {
59        let shaft = self.shaft_angle_rad_from_raw(raw);
60        shaft / self.gear_ratio
61    }
62
63    /// Convert a raw encoder value into tile tilt angle in degrees.
64    #[inline]
65    pub fn tile_angle_deg_from_raw(&self, raw: u16) -> f32 {
66        let shaft_deg = self.shaft_angle_deg_from_raw(raw);
67        shaft_deg / self.gear_ratio
68    }
69
70    /// Convert a desired tile tilt angle in radians into a raw encoder value.
71    #[inline]
72    pub fn raw_for_tile_angle_rad(&self, tile_angle_rad: f32) -> u16 {
73        let shaft = tile_angle_rad * self.gear_ratio;
74        self.raw_for_shaft_angle_rad(shaft)
75    }
76
77    /// Convert a desired tile tilt angle in degrees into a raw encoder value.
78    #[inline]
79    pub fn raw_for_tile_angle_deg(&self, tile_angle_deg: f32) -> u16 {
80        let shaft_deg = tile_angle_deg * self.gear_ratio;
81        self.raw_for_shaft_angle_deg(shaft_deg)
82    }
83}