Skip to main content

embassy_gy_bmi160/
lib.rs

1// Copyright (C) 2026 Jorge Andre Castro
2// GPL-2.0-or-later
3
4#![no_std]
5#![forbid(unsafe_code)]
6
7//! # embassy-gy-bmi160
8//!
9//! Driver asynchrone `no_std` pour l'IMU Bosch BMI160 via I2C.
10//! optimisé pour l'exécuteur `embassy`.
11//! 
12//! Ce pilote fournit un accès direct aux registres de données brutes 
13//! de l'accéléromètre et du gyroscope sans surcoût de calcul.
14
15pub mod signals;
16
17use core::marker::PhantomData;
18use embassy_time::Timer;
19use embedded_hal_async::i2c::I2c;
20
21/// Données de mouvement brutes sur trois axes (X, Y, Z).
22/// Représentées par des entiers signés de 16 bits.
23#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
24pub struct BmiData {
25    /// Valeur brute sur l'axe X.
26    pub x: i16,
27    /// Valeur brute sur l'axe Y.
28    pub y: i16,
29    /// Valeur brute sur l'axe Z.
30    pub z: i16,
31}
32
33/// Instance principale du driver BMI160.
34/// 
35/// Fonctionne avec n'importe quel périphérique implémentant `embedded-hal-async::i2c::I2c`.
36pub struct Bmi160<'d, I>
37where
38    I: I2c,
39{
40    i2c: I,
41    /// Adresse I2C configurée (0x68 ou 0x69).
42    pub addr: u8,
43    _phantom: PhantomData<&'d ()>,
44}
45
46impl<'d, I> Bmi160<'d, I>
47where
48    I: I2c,
49{
50    /// Initialise une nouvelle instance du driver.
51    /// 
52    /// # Arguments
53    /// * `i2c` - Bus I2C (ou I2cDevice partagé).
54    /// * `addr` - Adresse du composant (généralement 0x68).
55    pub fn new(i2c: I, addr: u8) -> Self {
56        Self {
57            i2c,
58            addr,
59            _phantom: PhantomData,
60        }
61    }
62
63    /// Met à jour l'adresse I2C dynamiquement.
64    pub fn set_address(&mut self, new_addr: u8) {
65        self.addr = new_addr;
66    }
67
68    /// Configure le capteur en "Normal Mode" pour l'accéléromètre et le gyroscope.
69    /// 
70    /// Envoie les commandes PMU aux registres de contrôle d'alimentation.
71    pub async fn init(&mut self) -> Result<(), I::Error> {
72        // Accéléromètre en mode Normal (Commande 0x11)
73        self.i2c.write(self.addr, &[0x7E, 0x11]).await?;
74        Timer::after_millis(10).await;
75
76        // Gyroscope en mode Normal (Commande 0x15)
77        self.i2c.write(self.addr, &[0x7E, 0x15]).await?;
78        Timer::after_millis(10).await;
79
80        Ok(())
81    }
82
83    /// Lit les données brutes du gyroscope (registres 0x0C à 0x11).
84    pub async fn read_gyro(&mut self) -> Result<BmiData, I::Error> {
85        let mut data = [0u8; 6];
86        self.i2c.write_read(self.addr, &[0x0C], &mut data).await?;
87        Ok(BmiData {
88            x: i16::from_le_bytes([data[0], data[1]]),
89            y: i16::from_le_bytes([data[2], data[3]]),
90            z: i16::from_le_bytes([data[4], data[5]]),
91        })
92    }
93
94    /// Lit les données brutes de l'accéléromètre (registres 0x12 à 0x17).
95    pub async fn read_accel(&mut self) -> Result<BmiData, I::Error> {
96        let mut data = [0u8; 6];
97        self.i2c.write_read(self.addr, &[0x12], &mut data).await?;
98        Ok(BmiData {
99            x: i16::from_le_bytes([data[0], data[1]]),
100            y: i16::from_le_bytes([data[2], data[3]]),
101            z: i16::from_le_bytes([data[4], data[5]]),
102        })
103    }
104}