stm_32/peripherals/
ms4525.rs1pub use embassy_stm32::mode::Async;
37pub use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
38pub use embassy_sync::signal::Signal;
39use veloxity_core::{errors, packets};
40
41use embassy_embedded_hal::shared_bus::asynch::i2c::I2cDevice;
43use embassy_stm32::i2c::I2c;
44use embedded_hal_async::i2c::I2c as _;
45
46use crate::synch_at;
48use embassy_time::Duration;
49use embassy_time::Timer;
50
51pub static PITOT_SIGNAL: Signal<
54 CriticalSectionRawMutex,
55 Result<packets::PitotPacket, errors::SensorError>,
56> = Signal::<CriticalSectionRawMutex, Result<packets::PitotPacket, errors::SensorError>>::new();
57
58pub struct Ms4525Sensor {
59 pub dev: I2cDevice<
60 'static,
61 CriticalSectionRawMutex,
62 I2c<'static, Async, embassy_stm32::i2c::mode::Master>,
63 >,
64}
65
66impl Ms4525Sensor {
67 pub async fn run(&mut self) {
68 const ADDRESS: u8 = 0x28;
69 const NO_ERROR: u8 = 0x00;
70
71 let mut data = [0u8; 2];
73 if self.dev.read(ADDRESS, &mut data).await.is_err() {
74 PITOT_SIGNAL.signal(Err(errors::SensorError::GenericSensorError(
75 "MS4525 Pitot failed: reading data",
76 )));
77 return;
78 }
79
80 Timer::after(Duration::from_micros(2000)).await;
81
82 let mut data = [0u8; 2];
84 if self.dev.read(ADDRESS, &mut data).await.is_err() {
85 PITOT_SIGNAL.signal(Err(errors::SensorError::GenericSensorError(
86 "MS4525 Pitot failed: reading data",
87 )));
88 return;
89 }
90
91 let status = (data[0] >> 6) & 0x03;
92 if status != NO_ERROR {
93 PITOT_SIGNAL.signal(Err(errors::SensorError::GenericSensorError(
94 "MS4525 Pitot failed: bad status",
95 )));
96 return;
97 }
98
99 let sample_period_us = Duration::from_hz(100).as_micros();
100 let loop_period = Duration::from_hz(400);
101 const PMAX: f64 = 6894.76; let mut sum_pressure: u32 = 0;
103 let mut sum_temperature: u32 = 0;
104 let mut sum_count: u32 = 0;
105
106 loop {
107 let timestamp = synch_at(loop_period);
108 Timer::at(timestamp).await; let mut data = [0u8; 4];
111 if self.dev.read(ADDRESS, &mut data).await.is_err() {
112 PITOT_SIGNAL.signal(Err(errors::SensorError::GenericSensorError(
113 "MS4525 Pitot failed: reading data",
114 )));
115 continue;
116 }
117
118 let status = (data[0] >> 6) & 0x03;
119 if status == NO_ERROR {
120 let pressure_u32 = (u32::from(data[0]) & 0x3F) << 8 | u32::from(data[1]);
121 let temperature_u32 =
122 (0xFFE0 & ((u32::from(data[2]) << 8) | u32::from(data[3]))) >> 5;
123
124 sum_pressure = sum_pressure + pressure_u32;
125 sum_temperature = sum_temperature + temperature_u32;
126 sum_count = sum_count + 1;
127 }
128
129 let timestamp_us = timestamp.as_micros();
130
131 if timestamp_us % sample_period_us == 0 {
132 if sum_count > 0 {
133 let avg_pressure = ((f64::from(sum_pressure) / (sum_count as f64) - 1638.3f64)
134 / 6553.2f64
135 - 1.0f64)
136 * PMAX;
137 let avg_temperature: f64 =
138 ((200.0f64 * f64::from(sum_temperature) / (sum_count as f64)) / 2047f64)
139 - 50f64;
140
141 let header = packets::RosflightPacketHeader {
142 timestamp: timestamp_us,
143 status: status as u16,
144 };
145 let pitot_packet = packets::PitotPacket {
146 header,
147 differential_pressure: avg_pressure as f32,
148 temperature: avg_temperature as f32,
149 ..Default::default()
150 };
151 PITOT_SIGNAL.signal(Ok(pitot_packet)); } else {
153 PITOT_SIGNAL.signal(Err(errors::SensorError::GenericSensorError(
154 "MS4525 Pitot failed: no valid data",
155 )));
156 }
157 sum_count = 0u32;
160 sum_pressure = 0u32;
161 sum_temperature = 0u32;
162 }
163 }
164 }
165}
166
167#[embassy_executor::task]
168pub async fn task(mut ms4525: Ms4525Sensor) {
169 ms4525.run().await;
170}