mpu6050_dmp/
calibration_blocking.rs1use crate::{
12 accel::{Accel, AccelFullScale},
13 calibration::{
14 CalibrationActions, CalibrationParameters, MeanAccumulator, ReferenceGravity, DELAY_MS,
15 ITERATIONS, WARMUP_ITERATIONS,
16 },
17 error::Error,
18 gyro::Gyro,
19 sensor::Mpu6050,
20};
21use embedded_hal::{delay::DelayNs, i2c::I2c};
22
23pub fn collect_mean_values<I>(
25 mpu: &mut Mpu6050<I>,
26 delay: &mut impl DelayNs,
27 accel_scale: AccelFullScale,
28 gravity: ReferenceGravity,
29) -> Result<(Accel, Gyro), Error<I>>
30where
31 I: I2c,
32{
33 let mut accumulator = MeanAccumulator::new(accel_scale, gravity);
34
35 for _ in 0..WARMUP_ITERATIONS {
36 _ = mpu.accel()?;
37 _ = mpu.gyro()?;
38 delay.delay_ms(DELAY_MS);
39 }
40
41 for _ in 0..ITERATIONS {
42 let accel = mpu.accel()?;
43 let gyro = mpu.gyro()?;
44 accumulator.add(&accel, &gyro);
45 delay.delay_ms(DELAY_MS);
46 }
47
48 Ok(accumulator.means())
49}
50
51pub fn calibration_loop<I>(
53 mpu: &mut Mpu6050<I>,
54 delay: &mut impl DelayNs,
55 parameters: &CalibrationParameters,
56 actions: CalibrationActions,
57) -> Result<(CalibrationActions, Accel, Gyro), Error<I>>
58where
59 I: I2c,
60{
61 let mut actions = actions;
62
63 mpu.set_accel_full_scale(parameters.accel_scale)?;
64 mpu.set_gyro_full_scale(parameters.gyro_scale)?;
65 let mut accel_offset = mpu.get_accel_calibration()?;
66 let mut gyro_offset = mpu.get_gyro_calibration()?;
67 let (accel_mean, gyro_mean) =
68 collect_mean_values(mpu, delay, parameters.accel_scale, parameters.gravity)?;
69
70 if parameters.accel_threshold.is_value_within(accel_mean.x()) {
71 actions = actions.with_accel_x(false);
72 }
73 if parameters.accel_threshold.is_value_within(accel_mean.y()) {
74 actions = actions.with_accel_y(false);
75 }
76 if parameters.accel_threshold.is_value_within(accel_mean.z()) {
77 actions = actions.with_accel_z(false);
78 }
79 if parameters.gyro_threshold.is_value_within(gyro_mean.x()) {
80 actions = actions.with_gyro_x(false);
81 }
82 if parameters.gyro_threshold.is_value_within(gyro_mean.y()) {
83 actions = actions.with_gyro_y(false);
84 }
85 if parameters.gyro_threshold.is_value_within(gyro_mean.z()) {
86 actions = actions.with_gyro_z(false);
87 }
88
89 if actions.accel_x() {
90 accel_offset.x = parameters
91 .accel_threshold
92 .next_offset(accel_mean.x(), accel_offset.x());
93 }
94 if actions.accel_y() {
95 accel_offset.y = parameters
96 .accel_threshold
97 .next_offset(accel_mean.y(), accel_offset.y());
98 }
99 if actions.accel_z() {
100 accel_offset.z = parameters
101 .accel_threshold
102 .next_offset(accel_mean.z(), accel_offset.z());
103 }
104 if actions.gyro_x() {
105 gyro_offset.x = parameters
106 .gyro_threshold
107 .next_offset(gyro_mean.x(), gyro_offset.x());
108 }
109 if actions.gyro_y() {
110 gyro_offset.y = parameters
111 .gyro_threshold
112 .next_offset(gyro_mean.y(), gyro_offset.y());
113 }
114 if actions.gyro_z() {
115 gyro_offset.z = parameters
116 .gyro_threshold
117 .next_offset(gyro_mean.z(), gyro_offset.z());
118 }
119
120 if !actions.is_empty() {
121 mpu.set_accel_calibration(&accel_offset)?;
122 mpu.set_gyro_calibration(&gyro_offset)?;
123 }
124
125 Ok((actions, accel_mean, gyro_mean))
126}
127
128pub fn calibrate<I>(
130 mpu: &mut Mpu6050<I>,
131 delay: &mut impl DelayNs,
132 parameters: &CalibrationParameters,
133) -> Result<(Accel, Gyro), Error<I>>
134where
135 I: I2c,
136{
137 let mut actions = CalibrationActions::all();
138 while !actions.is_empty() {
139 (actions, _, _) = calibration_loop(mpu, delay, parameters, actions)?;
140 }
141 Ok((mpu.get_accel_calibration()?, mpu.get_gyro_calibration()?))
142}