embedded_devices/devices/microchip/mcp9808/
mod.rs1use embedded_devices_derive::{forward_register_fns, sensor};
70use embedded_interfaces::TransportError;
71use uom::si::f64::ThermodynamicTemperature;
72
73pub mod address;
74pub mod registers;
75
76use self::registers::{AmbientTemperature, Configuration, DeviceIdRevision, ManufacturerId, Resolution, ShutdownMode};
77
78#[cfg_attr(feature = "defmt", derive(defmt::Format))]
79#[derive(Debug, thiserror::Error)]
80pub enum InitError<BusError> {
81 #[error("transport error")]
83 Transport(#[from] TransportError<(), BusError>),
84 #[error("invalid device id")]
86 InvalidDeviceId,
87 #[error("invalid manufacturer id")]
89 InvalidManufacturerId,
90}
91
92#[derive(Debug, embedded_devices_derive::Measurement)]
94pub struct Measurement {
95 #[measurement(Temperature)]
97 pub temperature: ThermodynamicTemperature,
98}
99
100#[maybe_async_cfg::maybe(
105 idents(hal(sync = "embedded_hal", async = "embedded_hal_async"), RegisterInterface),
106 sync(feature = "sync"),
107 async(feature = "async")
108)]
109pub struct MCP9808<D: hal::delay::DelayNs, I: embedded_interfaces::registers::RegisterInterface> {
110 delay: D,
112 interface: I,
114}
115
116pub trait MCP9808Register {}
117
118#[maybe_async_cfg::maybe(
119 idents(hal(sync = "embedded_hal", async = "embedded_hal_async"), I2cDevice),
120 sync(feature = "sync"),
121 async(feature = "async")
122)]
123impl<D, I> MCP9808<D, embedded_interfaces::i2c::I2cDevice<I, hal::i2c::SevenBitAddress>>
124where
125 I: hal::i2c::I2c<hal::i2c::SevenBitAddress> + hal::i2c::ErrorType,
126 D: hal::delay::DelayNs,
127{
128 #[inline]
134 pub fn new_i2c(delay: D, interface: I, address: self::address::Address) -> Self {
135 Self {
136 delay,
137 interface: embedded_interfaces::i2c::I2cDevice::new(interface, address.into()),
138 }
139 }
140}
141
142#[forward_register_fns]
143#[maybe_async_cfg::maybe(
144 idents(hal(sync = "embedded_hal", async = "embedded_hal_async"), RegisterInterface),
145 sync(feature = "sync"),
146 async(feature = "async")
147)]
148impl<D: hal::delay::DelayNs, I: embedded_interfaces::registers::RegisterInterface> MCP9808<D, I> {
149 pub async fn init(&mut self) -> Result<(), InitError<I::BusError>> {
152 let device_id = self.read_register::<DeviceIdRevision>().await?;
153 if device_id.read_device_id() != self::registers::DEVICE_ID_VALID {
154 return Err(InitError::InvalidDeviceId);
155 }
156
157 let manufacturer_id = self.read_register::<ManufacturerId>().await?;
158 if manufacturer_id.read_manufacturer_id() != self::registers::MANUFACTURER_ID_VALID {
159 return Err(InitError::InvalidManufacturerId);
160 }
161
162 Ok(())
163 }
164}
165
166#[sensor(Temperature)]
167#[maybe_async_cfg::maybe(
168 idents(
169 hal(sync = "embedded_hal", async = "embedded_hal_async"),
170 RegisterInterface,
171 OneshotSensor
172 ),
173 sync(feature = "sync"),
174 async(feature = "async")
175)]
176impl<D: hal::delay::DelayNs, I: embedded_interfaces::registers::RegisterInterface> crate::sensor::OneshotSensor
177 for MCP9808<D, I>
178{
179 type Error = TransportError<(), I::BusError>;
180 type Measurement = Measurement;
181
182 async fn measure(&mut self) -> Result<Self::Measurement, Self::Error> {
185 let mut reg_conf = self.read_register::<Configuration>().await?;
187 reg_conf.write_shutdown_mode(ShutdownMode::Continuous);
188 self.write_register(reg_conf).await?;
189
190 let resolution = self.read_register::<Resolution>().await?;
192 let conversion_time = 1000 + resolution.read_temperature_resolution().conversion_time_us();
193 self.delay.delay_us(conversion_time).await;
194
195 reg_conf.write_shutdown_mode(ShutdownMode::Shutdown);
197 self.write_register(reg_conf).await?;
198
199 let temperature = self.read_register::<AmbientTemperature>().await?.read_temperature();
201 Ok(Measurement { temperature })
202 }
203}
204
205#[maybe_async_cfg::maybe(
206 idents(
207 hal(sync = "embedded_hal", async = "embedded_hal_async"),
208 RegisterInterface,
209 ContinuousSensor
210 ),
211 sync(feature = "sync"),
212 async(feature = "async")
213)]
214impl<D: hal::delay::DelayNs, I: embedded_interfaces::registers::RegisterInterface> crate::sensor::ContinuousSensor
215 for MCP9808<D, I>
216{
217 type Error = TransportError<(), I::BusError>;
218 type Measurement = Measurement;
219
220 async fn start_measuring(&mut self) -> Result<(), Self::Error> {
222 let reg_conf = self.read_register::<Configuration>().await?;
223 self.write_register(reg_conf.with_shutdown_mode(ShutdownMode::Continuous))
224 .await?;
225 Ok(())
226 }
227
228 async fn stop_measuring(&mut self) -> Result<(), Self::Error> {
230 let reg_conf = self.read_register::<Configuration>().await?;
231 self.write_register(reg_conf.with_shutdown_mode(ShutdownMode::Shutdown))
232 .await?;
233 Ok(())
234 }
235
236 async fn measurement_interval_us(&mut self) -> Result<u32, Self::Error> {
238 let resolution = self.read_register::<Resolution>().await?;
240 let conversion_time = resolution.read_temperature_resolution().conversion_time_us();
241 Ok(conversion_time)
242 }
243
244 async fn current_measurement(&mut self) -> Result<Option<Self::Measurement>, Self::Error> {
246 let temperature = self.read_register::<AmbientTemperature>().await?.read_temperature();
247 Ok(Some(Measurement { temperature }))
248 }
249
250 async fn is_measurement_ready(&mut self) -> Result<bool, Self::Error> {
252 Ok(true)
253 }
254
255 async fn next_measurement(&mut self) -> Result<Self::Measurement, Self::Error> {
257 let interval = self.measurement_interval_us().await?;
258 self.delay.delay_us(interval).await;
259 self.current_measurement()
260 .await?
261 .ok_or_else(|| TransportError::Unexpected("measurement was not ready even though we expected it to be"))
262 }
263}