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}