sht4x_rjw/lib.rs
1//! ## SHT4x embedded-hal driver
2//!
3//! `sht4x-rjw` is an [`embedded-hal`], [`no_std`] driver for the [Sensirion SHT4x
4//! series][sht4x] of I2C temperature and humidity sensors with **blocking** and
5//! **async** support. The driver implements all features described in section 4.5
6//! of the [datasheet].
7//!
8//! ## Features
9//!
10//! By default, this crate contains a blocking driver, [`blocking::SHT4x`].
11//!
12//! Optional features include:
13//!
14//! - **Async** support via [`embedded-hal-async`]. Use the `async` feature flag
15//! and the [`asynch::SHT4x`] driver struct. The blocking and async drivers are
16//! otherwise identical.
17//! - **[`defmt`]** support through the `defmt` feature flag.
18//! - **Fixed-point** conversions through the `fixed` feature flag and the
19//! [`fixed`] crate.
20//!
21//! You can remove the blocking driver by passing `--no-default-features` to
22//! `cargo add`, or adding `default-features = false` to the dependency spec in
23//! your `Cargo.toml`.
24//!
25//! [`defmt`]: https://defmt.ferrous-systems.com/
26//!
27//! ## Example usage
28//!
29//! ```
30//! # use embedded_hal_mock::eh1::i2c::{Mock, Transaction};
31//! # use sht4x_rjw::blocking::SHT4x;
32//! # fn main() -> anyhow::Result<()> {
33//! # let mut delay = embedded_hal_mock::eh1::delay::NoopDelay::new();
34//! # let expectations = [
35//! # // Request the sensor serial number.
36//! # Transaction::write(0x44, vec![0x89]),
37//! # // Receive a fake sensor serial number.
38//! # Transaction::read(0x44, vec![0x01, 0x02, 0x17, 0x3, 0x4, 0x68]),
39//! # // Request a high-precision read.
40//! # Transaction::write(0x44, vec![0xFD]),
41//! # // Receive a fake temp & humidity measurement.
42//! # Transaction::read(0x44, vec![0x12, 0x34, 0x37, 0x56, 0x78, 0x7D])
43//! # ];
44//! # let i2c = Mock::new(&expectations);
45//! let mut sensor = SHT4x::new(i2c, Default::default());
46//! let serial_number = sensor.serial_number()?;
47//! let measurement = sensor.measure(&mut delay)?;
48//!
49//! defmt::info!(
50//! "SHT4x sensor with serial {}, currently: {}°C, {}%RH",
51//! serial_number,
52//! measurement.celsius(),
53//! measurement.humidity()
54//! );
55//! # sensor.destroy().done(); // Call done on the I2C mock.
56//! # Ok(())
57//! # }
58//! ```
59//!
60//! ## Driver operation
61//!
62//! Construct the driver by passing in an [I2C interface] and configuration struct
63//! (used to set defaults for [`SHT4x::measure()`]). You can retrieve the I2C
64//! interface with [`SHT4x::destroy()`].
65//!
66//! You can choose the type of measurement conducted (varying in repeatability
67//! and heater use) with [`ReadingMode`]. The default value of [`Config`] is set
68//! for high-repeatability measurements.
69//!
70//! When reading measurements from the sensor (or performing a soft reset), pass
71//! in an implementation of [`embedded_hal::delay::DelayNs`]. (This is done to avoid
72//! the driver having to take ownership of the delay struct, as it can be less easy
73//! to share these than I2C interfaces.) The length of the delay is controlled by
74//! [`DelayMode`].
75//!
76//! Temperature and humidity measurements are provided through [`Measurement`],
77//! which has methods for converting the raw two-byte sensor measurement into
78//! recognisable units. The raw measurements can also be accessed, and the
79//! conversion functions are available in the [`conversions`] module.
80//!
81//! Data is read from the sensor as two groups of three bytes: two data bytes and
82//! one CRC byte for error detection. These CRC bytes are always checked before the
83//! data bytes are made available for conversion. Should an error be detected in
84//! the data read from the sensor, the [`Error`] enum will contain the bytes in
85//! question (both data bytes and the CRC byte read from the sensor).
86//!
87//! [I2C interface]: embedded_hal::i2c::I2c
88//! [`SHT4x::destroy()`]: crate::blocking::SHT4x::destroy()
89//! [`SHT4x::measure()`]: crate::blocking::SHT4x::measure()
90//! [`ReadingMode`]: crate::common::ReadingMode
91//! [`Measurement`]: crate::common::Measurement
92//! [`conversions`]: crate::conversions
93//! [`Error`]: crate::error::Error
94//! [`Config`]: crate::common::Config
95//! [`DelayMode`]: crate::common::DelayMode
96//!
97//! ## Sensor I2C address
98//!
99//! The sensor struct uses a default I2C address of `0x44`, as this appears to be
100//! the most common. However, sensors with part numbers including `-B` and `-C`
101//! have I2C addresses of `0x45` and `0x46`, respectively. See section 9 of the
102//! [datasheet].
103//!
104//! Should you need to use an address other than `0x44`, instantiate the struct
105//! as normal and write to its `address` field, as so:
106//!
107//! ```
108//! # use sht4x_rjw::blocking::SHT4x;
109//! # let i2c = embedded_hal_mock::eh1::i2c::Mock::new(&[]);
110//! let mut sensor = SHT4x::new(i2c, Default::default());
111//! sensor.address = 0x46;
112//! # sensor.destroy().done()
113//! ```
114//!
115//! 10-bit I2C addresses are not supported.
116//!
117//! ## Sensor variant support
118//!
119//! There are (as of this writing) four parts in the SHT4x line: the [SHT40], [SHT41],
120//! [SHT43] and [SHT45]. There is also the SHT4x**A** line of automotive parts. All of
121//! these sensors share the same I2C interface, so this library _should_ work with
122//! all of them, though at the moment it has only been tested with the SHT40.
123//!
124//! **Note** that there appear to be some differences in the characteristics of the
125//! automotive parts (slower timings, for instance) which are not accounted for at
126//! present. If this affects you please open an issue.
127//!
128//! ## Similar crates
129//!
130//! You may prefer to use the following drivers for the SHT4x:
131//!
132//! - [`sht4x`](https://github.com/sirhcel/sht4x)
133//! - [`sensor-temp-humidity-sht40`](https://github.com/lc525/sensor-temp-humidity-sht40-rs)
134//!
135//! ## License
136//!
137//! The `sht4x_rjw` crate is copyright 2025 the sht4x_rjw contributors, and is licensed
138//! under the [Apache License, Version 2.0], or the [MIT License], at your option.
139//!
140//! [`embedded-hal`]: https://docs.rs/embedded-hal/latest/embedded_hal/
141//! [`embedded-hal-async`]: https://docs.rs/embedded-hal-async/latest/embedded_hal_async/
142//! [`no_std`]: https://doc.rust-lang.org/reference/names/preludes.html#the-no_std-attribute
143//! [sht4x]: https://developer.sensirion.com/product-support/sht4x-humidity-and-temperature-sensor
144//! [datasheet]: https://sensirion.com/media/documents/33FD6951/67EB9032/HT_DS_Datasheet_SHT4x_5.pdf
145//! [SHT40]: https://sensirion.com/products/catalog/SHT40
146//! [SHT41]: https://sensirion.com/products/catalog/SHT41
147//! [SHT43]: https://sensirion.com/products/catalog/SHT43
148//! [SHT45]: https://sensirion.com/products/catalog/SHT45
149//! [Apache License, Version 2.0]: https://opensource.org/license/apache-2-0
150//! [MIT License]: https://opensource.org/license/mit
151
152#![no_std]
153
154#[cfg(feature = "async")]
155pub mod asynch;
156#[cfg(feature = "blocking")]
157pub mod blocking;
158pub mod common;
159pub mod conversions;
160pub mod error;
161
162mod crc;