Skip to main content

haptic_skin_firmware/drivers/
motors.rs

1//! Pilotage direct des 8 moteurs ERM via le PWM matériel du RP2040.
2//!
3//! Chaque moteur = 1 sortie PWM (canal A d'une slice). L'intensité est
4//! exposée en 8 bits (0..=255) et mise à l'échelle vers `PWM_TOP` en interne,
5//! pour que l'API publique colle au payload du protocole série (1 octet/moteur).
6
7use embassy_rp::pwm::{Config, Pwm};
8
9use crate::config::{MOTOR_COUNT, MOTOR_MAX_DUTY, PWM_TOP};
10
11/// Possède les 8 instances PWM et expose un pilotage par intensité 0..=255.
12pub struct Motors<'d> {
13    pwms: [Pwm<'d>; MOTOR_COUNT],
14}
15
16impl<'d> Motors<'d> {
17    pub fn new(pwms: [Pwm<'d>; MOTOR_COUNT]) -> Self {
18        Self { pwms }
19    }
20
21    /// Règle l'intensité du moteur `idx` (0 = éteint, 255 = plein régime).
22    ///
23    /// Sécurité : tout chemin d'écriture (self-test, SetMotor, SetAll) est borné
24    /// ici à `MOTOR_MAX_DUTY` → impossible d'envoyer 5 V plein régime à un moteur
25    /// 3 V, quelle que soit la commande hôte.
26    pub fn set(&mut self, idx: usize, intensity: u8) {
27        let intensity = if intensity > MOTOR_MAX_DUTY {
28            MOTOR_MAX_DUTY
29        } else {
30            intensity
31        };
32        // mise à l'échelle 8 bits → résolution PWM : 255 ↦ PWM_TOP+1 (100 %)
33        let compare = ((intensity as u32 * (PWM_TOP as u32 + 1)) / 256) as u16;
34
35        // On reconstruit la config : Config::default() a `enable = false`,
36        // il faut donc réactiver le slice à chaque écriture.
37        let mut c = Config::default();
38        c.top = PWM_TOP;
39        c.enable = true;
40        c.compare_a = compare;
41        self.pwms[idx].set_config(&c);
42    }
43
44    /// Applique les 8 intensités d'un coup.
45    pub fn set_all(&mut self, intensities: &[u8; MOTOR_COUNT]) {
46        for (i, &v) in intensities.iter().enumerate() {
47            self.set(i, v);
48        }
49    }
50
51    /// Coupe tous les moteurs.
52    pub fn stop_all(&mut self) {
53        for i in 0..MOTOR_COUNT {
54            self.set(i, 0);
55        }
56    }
57}