embedded_devices/devices/belling/bl0942/
mod.rs1use super::ChecksumError;
87use embedded_devices_derive::forward_register_fns;
88use embedded_devices_derive::sensor;
89use embedded_interfaces::TransportError;
90use uom::si::electrical_resistance::ohm;
91use uom::si::f64::{ElectricCurrent, ElectricPotential, ElectricalResistance, Energy, Frequency, Power};
92
93pub mod registers;
94
95pub const V_REF: f64 = 1.218;
96pub const V_RMS_COEFF: f64 = V_REF / (73989.0 * 1000.0);
97pub const I_RMS_COEFF: f64 = V_REF / (305978.0 * 1000.0);
98pub const I_FAST_RMS_FACTOR: f64 = 0.363;
99pub const P_COEFF: f64 = V_REF * V_REF / (3537.0 * 1_000_000.0);
100pub const E_COEFF: f64 = 1638.4 * 256.0 / 3600.0;
101
102#[derive(Debug, embedded_devices_derive::Measurement)]
104pub struct Measurement {
105 #[measurement(Voltage)]
107 pub voltage: ElectricPotential,
108 #[measurement(Current)]
110 pub current: ElectricCurrent,
111 #[measurement(Power)]
113 pub power: Power,
114 #[measurement(Energy)]
116 pub energy: Energy,
117 #[measurement(Frequency)]
119 pub frequency: Frequency,
120}
121
122#[maybe_async_cfg::maybe(
128 idents(hal(sync = "embedded_hal", async = "embedded_hal_async"), RegisterInterface),
129 sync(feature = "sync"),
130 async(feature = "async")
131)]
132pub struct BL0942<D: hal::delay::DelayNs, I: embedded_interfaces::registers::RegisterInterface> {
133 delay: D,
135 interface: I,
137 pub shunt_resistance: ElectricalResistance,
139 pub voltage_divider_coeff: f64,
142 pub i_lsb: f64,
144 pub v_lsb: f64,
146 pub p_lsb: f64,
148 pub e_lsb: f64,
150}
151
152pub trait BL0942Register {}
153
154#[maybe_async_cfg::maybe(
155 idents(hal(sync = "embedded_hal", async = "embedded_hal_async"), SpiDevice),
156 sync(feature = "sync"),
157 async(feature = "async")
158)]
159impl<D, I> BL0942<D, embedded_interfaces::spi::SpiDevice<I>>
160where
161 I: hal::spi::r#SpiDevice,
162 D: hal::delay::DelayNs,
163{
164 #[inline]
172 pub fn new_spi(
173 delay: D,
174 interface: I,
175 shunt_resistance: ElectricalResistance,
176 voltage_divider_r1: ElectricalResistance,
177 voltage_divider_r2: ElectricalResistance,
178 ) -> Self {
179 let r1 = voltage_divider_r1.get::<ohm>();
180 let r2 = voltage_divider_r2.get::<ohm>();
181 let voltage_divider_coeff = (r1 + r2) / r1;
182 let p_lsb = P_COEFF * voltage_divider_coeff / shunt_resistance.get::<ohm>();
183 Self {
184 delay,
185 interface: embedded_interfaces::spi::SpiDevice::new(interface),
186 shunt_resistance,
187 voltage_divider_coeff,
188 i_lsb: I_RMS_COEFF / shunt_resistance.get::<ohm>(),
189 v_lsb: V_RMS_COEFF * voltage_divider_coeff,
190 p_lsb,
191 e_lsb: E_COEFF * p_lsb,
192 }
193 }
194}
195
196#[forward_register_fns]
197#[sensor(Voltage, Current, Power, Energy)]
198#[maybe_async_cfg::maybe(
199 idents(
200 hal(sync = "embedded_hal", async = "embedded_hal_async"),
201 RegisterInterface,
202 ResettableDevice
203 ),
204 sync(feature = "sync"),
205 async(feature = "async")
206)]
207impl<D: hal::delay::DelayNs, I: embedded_interfaces::registers::RegisterInterface> BL0942<D, I> {
208 pub async fn init(&mut self) -> Result<(), TransportError<ChecksumError, I::BusError>> {
210 use crate::device::ResettableDevice;
211
212 self.reset().await?;
215 self.delay.delay_ms(1).await;
216
217 Ok(())
218 }
219}
220
221#[maybe_async_cfg::maybe(
222 idents(
223 hal(sync = "embedded_hal", async = "embedded_hal_async"),
224 RegisterInterface,
225 ResettableDevice
226 ),
227 sync(feature = "sync"),
228 async(feature = "async")
229)]
230impl<D: hal::delay::DelayNs, I: embedded_interfaces::registers::RegisterInterface> crate::device::ResettableDevice
231 for BL0942<D, I>
232{
233 type Error = TransportError<ChecksumError, I::BusError>;
234
235 async fn reset(&mut self) -> Result<(), Self::Error> {
237 self.write_register(self::registers::WriteProtection::default().with_key(registers::ProtectionKey::Unlocked))
238 .await?;
239 self.write_register(self::registers::SoftReset::default().with_magic(registers::ResetMagic::Reset))
240 .await?;
241 Ok(())
242 }
243}
244
245#[maybe_async_cfg::maybe(
246 idents(
247 hal(sync = "embedded_hal", async = "embedded_hal_async"),
248 RegisterInterface,
249 OneshotSensor
250 ),
251 sync(feature = "sync"),
252 async(feature = "async")
253)]
254impl<D: hal::delay::DelayNs, I: embedded_interfaces::registers::RegisterInterface> crate::sensor::OneshotSensor
255 for BL0942<D, I>
256{
257 type Error = TransportError<ChecksumError, I::BusError>;
258 type Measurement = Measurement;
259
260 async fn measure(&mut self) -> Result<Self::Measurement, Self::Error> {
262 use uom::si::{electric_current::ampere, electric_potential::volt, energy::watt_hour, power::watt};
263
264 let i_rms = self.read_register::<self::registers::CurrentRms>().await?.read_value() as f64 * self.i_lsb;
265 let v_rms = self.read_register::<self::registers::VoltageRms>().await?.read_value() as f64 * self.v_lsb;
266 let power = self.read_register::<self::registers::ActivePower>().await?.read_value() as f64 * self.p_lsb;
267 let energy = self
268 .read_register::<self::registers::EnergyCounter>()
269 .await?
270 .read_value() as f64
271 * self.e_lsb;
272 let frequency = self
273 .read_register::<self::registers::Frequency>()
274 .await?
275 .read_frequency();
276 let measurement = Measurement {
277 voltage: ElectricPotential::new::<volt>(v_rms),
278 current: ElectricCurrent::new::<ampere>(i_rms),
279 power: Power::new::<watt>(power),
280 energy: Energy::new::<watt_hour>(energy),
281 frequency,
282 };
283
284 Ok(measurement)
285 }
286}
287
288#[maybe_async_cfg::maybe(
289 idents(
290 hal(sync = "embedded_hal", async = "embedded_hal_async"),
291 RegisterInterface,
292 OneshotSensor,
293 ContinuousSensor
294 ),
295 sync(feature = "sync"),
296 async(feature = "async")
297)]
298impl<D: hal::delay::DelayNs, I: embedded_interfaces::registers::RegisterInterface> crate::sensor::ContinuousSensor
299 for BL0942<D, I>
300{
301 type Error = TransportError<ChecksumError, I::BusError>;
302 type Measurement = Measurement;
303
304 async fn start_measuring(&mut self) -> Result<(), Self::Error> {
306 Ok(())
307 }
308
309 async fn stop_measuring(&mut self) -> Result<(), Self::Error> {
311 Ok(())
312 }
313
314 async fn measurement_interval_us(&mut self) -> Result<u32, Self::Error> {
316 Ok(self
317 .read_register::<self::registers::UserMode>()
318 .await?
319 .read_rms_update_rate()
320 .as_us())
321 }
322
323 async fn current_measurement(&mut self) -> Result<Option<Self::Measurement>, Self::Error> {
325 use crate::sensor::OneshotSensor;
326 Ok(Some(self.measure().await?))
327 }
328
329 async fn is_measurement_ready(&mut self) -> Result<bool, Self::Error> {
331 Ok(true)
332 }
333
334 async fn next_measurement(&mut self) -> Result<Self::Measurement, Self::Error> {
336 use crate::sensor::OneshotSensor;
337 let interval = self.measurement_interval_us().await?;
338 self.delay.delay_us(interval).await;
339 self.measure().await
340 }
341}