tangled
alpha
login
or
join now
sachy.dev
/
sachy-embed-core
0
fork
atom
Repo of no-std crates for my personal embedded projects
0
fork
atom
overview
issues
pulls
pipelines
Refactor power mode API
sachy.dev
3 months ago
da0ffed8
02e4e7d9
+65
-60
1 changed file
expand all
collapse all
unified
split
sachy-shtc3
src
lib.rs
+65
-60
sachy-shtc3/src/lib.rs
···
35
35
//! use sachy_shtc3::ShtC3;
36
36
//!
37
37
//! let dev = I2cdev::new("/dev/i2c-1").unwrap();
38
38
-
//! let mut sht = ShtC3::new(dev);
38
38
+
//! let mut sht = ShtC3::new(dev, Default::default());
39
39
//! ```
40
40
//!
41
41
//! ### Device Info
···
45
45
//! ```no_run
46
46
//! use linux_embedded_hal::{Delay, I2cdev};
47
47
//! use sachy_shtc3::ShtC3;
48
48
-
//! let mut sht = ShtC3::new(I2cdev::new("/dev/i2c-1").unwrap());
48
48
+
//! let mut sht = ShtC3::new(I2cdev::new("/dev/i2c-1").unwrap(), Default::default());
49
49
//! let device_id = sht.device_identifier().unwrap();
50
50
//! let raw_id = sht.raw_id_register().unwrap();
51
51
//! ```
···
59
59
//! use linux_embedded_hal::{Delay, I2cdev};
60
60
//! use sachy_shtc3::{ShtC3, PowerMode};
61
61
//!
62
62
-
//! let mut sht = ShtC3::new(I2cdev::new("/dev/i2c-1").unwrap());
62
62
+
//! let mut sht = ShtC3::new(I2cdev::new("/dev/i2c-1").unwrap(), Default::default());
63
63
//! let mut delay = Delay;
64
64
//!
65
65
-
//! let temperature = sht.measure_temperature(PowerMode::NormalMode, &mut delay).unwrap();
66
66
-
//! let humidity = sht.measure_humidity(PowerMode::NormalMode, &mut delay).unwrap();
67
67
-
//! let combined = sht.measure(PowerMode::NormalMode, &mut delay).unwrap();
65
65
+
//! let temperature = sht.measure_temperature(&mut delay).unwrap();
66
66
+
//! let humidity = sht.measure_humidity(&mut delay).unwrap();
67
67
+
//! let combined = sht.measure(&mut delay).unwrap();
68
68
//!
69
69
//! println!("Temperature: {} °C", temperature.as_degrees_celsius());
70
70
//! println!("Humidity: {} %RH", humidity.as_percent());
···
82
82
//! ```no_run
83
83
//! use linux_embedded_hal::{Delay, I2cdev};
84
84
//! use sachy_shtc3::{ShtC3, PowerMode};
85
85
-
//! let mut sht = ShtC3::new(I2cdev::new("/dev/i2c-1").unwrap());
85
85
+
//! let mut sht = ShtC3::new(I2cdev::new("/dev/i2c-1").unwrap(), PowerMode::LowPower);
86
86
//! let mut delay = Delay;
87
87
-
//! let measurement = sht.measure(PowerMode::LowPower, &mut delay).unwrap();
87
87
+
//! let measurement = sht.measure(&mut delay).unwrap();
88
88
//! ```
89
89
//!
90
90
//! ### Measurements (Non-Blocking)
···
97
97
//! use linux_embedded_hal::I2cdev;
98
98
//! use sachy_shtc3::{ShtC3, PowerMode};
99
99
//!
100
100
-
//! let mut sht = ShtC3::new(I2cdev::new("/dev/i2c-1").unwrap());
100
100
+
//! let mut sht = ShtC3::new(I2cdev::new("/dev/i2c-1").unwrap(), PowerMode::NormalMode);
101
101
//!
102
102
-
//! sht.start_measurement(PowerMode::NormalMode).unwrap();
102
102
+
//! sht.start_measurement().unwrap();
103
103
//! // Wait for at least `max_measurement_duration(&sht, PowerMode::NormalMode)` µs
104
104
//! let result = sht.get_measurement_result().unwrap();
105
105
//! ```
···
129
129
//! ```no_run
130
130
//! use linux_embedded_hal::{Delay, I2cdev};
131
131
//! use sachy_shtc3::{ShtC3, PowerMode};
132
132
-
//! let mut sht = ShtC3::new(I2cdev::new("/dev/i2c-1").unwrap());
132
132
+
//! let mut sht = ShtC3::new(I2cdev::new("/dev/i2c-1").unwrap(), PowerMode::NormalMode);
133
133
//! let mut delay = Delay;
134
134
//! sht.reset(&mut delay).unwrap();
135
135
//! ```
···
169
169
/// note][an-low-power] by Sensirion.
170
170
///
171
171
/// [an-low-power]: https://www.sensirion.com/fileadmin/user_upload/customers/sensirion/Dokumente/2_Humidity_Sensors/Sensirion_Humidity_Sensors_SHTC3_Low_Power_Measurement_Mode.pdf
172
172
-
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
172
172
+
#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
173
173
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
174
174
pub enum PowerMode {
175
175
/// Normal measurement.
176
176
+
#[default]
176
177
NormalMode,
177
178
/// Low power measurement: Less energy consumption, but repeatability and
178
179
/// accuracy of measurements are negatively impacted.
···
262
263
i2c: I2C,
263
264
/// The I²C device address.
264
265
address: u8,
266
266
+
mode: PowerMode,
265
267
}
266
268
267
269
impl<I2C> ShtC3<I2C> {
268
270
/// Create a new instance of the driver for the SHTC3.
269
271
#[inline]
270
270
-
pub const fn new(i2c: I2C) -> Self {
271
271
-
Self { i2c, address: 0x70 }
272
272
+
pub const fn new(i2c: I2C, mode: PowerMode) -> Self {
273
273
+
Self {
274
274
+
i2c,
275
275
+
address: 0x70,
276
276
+
mode,
277
277
+
}
272
278
}
273
279
274
280
/// Get the device's wakeup delay duration in microseconds
···
289
295
/// - Normal mode: 12.1 ms
290
296
/// - Low power mode: 0.8 ms
291
297
#[inline(always)]
292
292
-
pub const fn max_measurement_duration(&self, mode: PowerMode) -> u32 {
293
293
-
match mode {
298
298
+
pub const fn max_measurement_duration(&self) -> u32 {
299
299
+
match self.mode {
294
300
PowerMode::NormalMode => 12100,
295
301
PowerMode::LowPower => 800,
296
302
}
···
421
427
})
422
428
.await?;
423
429
424
424
-
delay.delay_us(self.max_measurement_duration(mode)).await;
430
430
+
delay.delay_us(self.max_measurement_duration()).await;
425
431
426
432
let mut buf = [0; 6];
427
433
self.read_with_crc_async(&mut buf).await?;
···
543
549
}
544
550
545
551
/// Start a combined temperature / humidity measurement.
546
546
-
pub fn start_measurement(&mut self, mode: PowerMode) -> Result<(), Error<I2C::Error>> {
547
547
-
self.start_measure_partial(mode, MeasurementOrder::TemperatureFirst)
552
552
+
pub fn start_measurement(&mut self) -> Result<(), Error<I2C::Error>> {
553
553
+
self.start_measure_partial(self.mode, MeasurementOrder::TemperatureFirst)
548
554
}
549
555
550
556
/// Start a temperature measurement.
551
551
-
pub fn start_temperature_measurement(
552
552
-
&mut self,
553
553
-
mode: PowerMode,
554
554
-
) -> Result<(), Error<I2C::Error>> {
555
555
-
self.start_measure_partial(mode, MeasurementOrder::TemperatureFirst)
557
557
+
pub fn start_temperature_measurement(&mut self) -> Result<(), Error<I2C::Error>> {
558
558
+
self.start_measure_partial(self.mode, MeasurementOrder::TemperatureFirst)
556
559
}
557
560
558
561
/// Start a humidity measurement.
559
559
-
pub fn start_humidity_measurement(&mut self, mode: PowerMode) -> Result<(), Error<I2C::Error>> {
560
560
-
self.start_measure_partial(mode, MeasurementOrder::HumidityFirst)
562
562
+
pub fn start_humidity_measurement(&mut self) -> Result<(), Error<I2C::Error>> {
563
563
+
self.start_measure_partial(self.mode, MeasurementOrder::HumidityFirst)
561
564
}
562
565
563
566
/// Read the result of a temperature / humidity measurement.
···
609
612
I2C: I2c<SevenBitAddress>,
610
613
{
611
614
/// Wait the maximum time needed for the given measurement mode
612
612
-
pub fn wait_for_measurement(&mut self, mode: PowerMode, delay: &mut impl BlockingDelayNs) {
613
613
-
delay.delay_us(self.max_measurement_duration(mode));
615
615
+
pub fn wait_for_measurement(&mut self, delay: &mut impl BlockingDelayNs) {
616
616
+
delay.delay_us(self.max_measurement_duration());
614
617
}
615
618
616
619
/// Run a temperature/humidity measurement and return the combined result.
···
618
621
/// This is a blocking function call.
619
622
pub fn measure(
620
623
&mut self,
621
621
-
mode: PowerMode,
622
624
delay: &mut impl BlockingDelayNs,
623
625
) -> Result<Measurement, Error<I2C::Error>> {
624
624
-
self.start_measurement(mode)?;
625
625
-
self.wait_for_measurement(mode, delay);
626
626
+
self.start_measurement()?;
627
627
+
self.wait_for_measurement(delay);
626
628
self.get_measurement_result()
627
629
}
628
630
···
634
636
/// and only read the first half of the measurement response.
635
637
pub fn measure_temperature(
636
638
&mut self,
637
637
-
mode: PowerMode,
638
639
delay: &mut impl BlockingDelayNs,
639
640
) -> Result<Temperature, Error<I2C::Error>> {
640
640
-
self.start_temperature_measurement(mode)?;
641
641
-
self.wait_for_measurement(mode, delay);
641
641
+
self.start_temperature_measurement()?;
642
642
+
self.wait_for_measurement(delay);
642
643
self.get_temperature_measurement_result()
643
644
}
644
645
···
650
651
/// and only read the first half of the measurement response.
651
652
pub fn measure_humidity(
652
653
&mut self,
653
653
-
mode: PowerMode,
654
654
delay: &mut impl BlockingDelayNs,
655
655
) -> Result<Humidity, Error<I2C::Error>> {
656
656
-
self.start_humidity_measurement(mode)?;
657
657
-
self.wait_for_measurement(mode, delay);
656
656
+
self.start_humidity_measurement()?;
657
657
+
self.wait_for_measurement(delay);
658
658
self.get_humidity_measurement_result()
659
659
}
660
660
}
···
683
683
[Transaction::write(SHT_ADDR, alloc::vec![0xef, 0xc8])
684
684
.with_error(ErrorKind::Other)];
685
685
let mock = I2cMock::new(&expectations);
686
686
-
let mut sht = ShtC3::new(mock);
686
686
+
let mut sht = ShtC3::new(mock, PowerMode::NormalMode);
687
687
let err = sht.send_command(Command::ReadIdRegister).unwrap_err();
688
688
assert_eq!(err, Error::I2c(ErrorKind::Other));
689
689
sht.destroy().done();
···
693
693
#[test]
694
694
fn validate_crc() {
695
695
let mock = I2cMock::new(&[]);
696
696
-
let sht = ShtC3::new(mock);
696
696
+
let sht = ShtC3::new(mock, PowerMode::NormalMode);
697
697
698
698
// Not enough data
699
699
sht.validate_crc(&[]).unwrap();
···
730
730
// Valid CRC
731
731
let expectations = [Transaction::read(SHT_ADDR, alloc::vec![0xbe, 0xef, 0x92])];
732
732
let mock = I2cMock::new(&expectations);
733
733
-
let mut sht = ShtC3::new(mock);
733
733
+
let mut sht = ShtC3::new(mock, PowerMode::NormalMode);
734
734
sht.read_with_crc(&mut buf).unwrap();
735
735
assert_eq!(buf, [0xbe, 0xef, 0x92]);
736
736
sht.destroy().done();
···
738
738
// Invalid CRC
739
739
let expectations = [Transaction::read(SHT_ADDR, alloc::vec![0xbe, 0xef, 0x00])];
740
740
let mock = I2cMock::new(&expectations);
741
741
-
let mut sht = ShtC3::new(mock);
741
741
+
let mut sht = ShtC3::new(mock, PowerMode::NormalMode);
742
742
match sht.read_with_crc(&mut buf) {
743
743
Err(Error::Crc) => {}
744
744
Err(_) => panic!("Invalid error: Must be Crc"),
···
755
755
#[test]
756
756
fn new_shtc3() {
757
757
let mock = I2cMock::new(&[]);
758
758
-
let sht = ShtC3::new(mock);
758
758
+
let sht = ShtC3::new(mock, PowerMode::NormalMode);
759
759
assert_eq!(sht.address, 0x70);
760
760
sht.destroy().done();
761
761
}
···
775
775
Transaction::read(SHT_ADDR, alloc::vec![msb, lsb, crc]),
776
776
];
777
777
let mock = I2cMock::new(&expectations);
778
778
-
let mut sht = ShtC3::new(mock);
778
778
+
let mut sht = ShtC3::new(mock, PowerMode::NormalMode);
779
779
let val = sht.raw_id_register().unwrap();
780
780
assert_eq!(val, (msb as u16) << 8 | (lsb as u16));
781
781
sht.destroy().done();
···
792
792
Transaction::read(SHT_ADDR, alloc::vec![msb, lsb, crc]),
793
793
];
794
794
let mock = I2cMock::new(&expectations);
795
795
-
let mut sht = ShtC3::new(mock);
795
795
+
let mut sht = ShtC3::new(mock, PowerMode::NormalMode);
796
796
let ident = sht.device_identifier().unwrap();
797
797
assert_eq!(ident, 0b01000111);
798
798
sht.destroy().done();
···
823
823
),
824
824
];
825
825
let mock = I2cMock::new(&expectations);
826
826
-
let mut sht = ShtC3::new(mock);
826
826
+
let mut sht = ShtC3::new(mock, PowerMode::NormalMode);
827
827
let mut delay = NoopDelay;
828
828
-
let measurement = sht.measure(PowerMode::NormalMode, &mut delay).unwrap();
828
828
+
let measurement = sht.measure(&mut delay).unwrap();
829
829
assert_eq!(measurement.temperature.as_millidegrees_celsius(), 23_730); // 23.7°C
830
830
assert_eq!(measurement.humidity.as_millipercent(), 62_968); // 62.9 %RH
831
831
sht.destroy().done();
···
852
852
),
853
853
];
854
854
let mock = I2cMock::new(&expectations);
855
855
-
let mut sht = ShtC3::new(mock);
855
855
+
let mut sht = ShtC3::new(mock, PowerMode::LowPower);
856
856
let mut delay = NoopDelay;
857
857
-
let measurement = sht.measure(PowerMode::LowPower, &mut delay).unwrap();
857
857
+
let measurement = sht.measure(&mut delay).unwrap();
858
858
assert_eq!(measurement.temperature.as_millidegrees_celsius(), 23_730); // 23.7°C
859
859
assert_eq!(measurement.humidity.as_millipercent(), 62_968); // 62.9 %RH
860
860
sht.destroy().done();
···
871
871
Transaction::read(SHT_ADDR, alloc::vec![0b0110_0100, 0b1000_1011, 0b1100_0111]),
872
872
];
873
873
let mock = I2cMock::new(&expectations);
874
874
-
let mut sht = ShtC3::new(mock);
874
874
+
let mut sht = ShtC3::new(mock, PowerMode::NormalMode);
875
875
let mut delay = NoopDelay;
876
876
let temperature = sht
877
877
-
.measure_temperature(PowerMode::NormalMode, &mut delay)
877
877
+
.measure_temperature(&mut delay)
878
878
.unwrap();
879
879
assert_eq!(temperature.as_millidegrees_celsius(), 23_730); // 23.7°C
880
880
sht.destroy().done();
···
891
891
Transaction::read(SHT_ADDR, alloc::vec![0b1010_0001, 0b0011_0011, 0b0001_1100]),
892
892
];
893
893
let mock = I2cMock::new(&expectations);
894
894
-
let mut sht = ShtC3::new(mock);
894
894
+
let mut sht = ShtC3::new(mock, PowerMode::NormalMode);
895
895
let mut delay = NoopDelay;
896
896
let humidity = sht
897
897
-
.measure_humidity(PowerMode::NormalMode, &mut delay)
897
897
+
.measure_humidity(&mut delay)
898
898
.unwrap();
899
899
assert_eq!(humidity.as_millipercent(), 62_968); // 62.9 %RH
900
900
sht.destroy().done();
···
907
907
[Transaction::write(SHT_ADDR, alloc::vec![0x60, 0x9C])
908
908
.with_error(ErrorKind::Other)];
909
909
let mock = I2cMock::new(&expectations);
910
910
-
let mut sht = ShtC3::new(mock);
910
910
+
let mut sht = ShtC3::new(mock, PowerMode::LowPower);
911
911
let err = sht
912
912
-
.measure(PowerMode::LowPower, &mut NoopDelay)
912
912
+
.measure(&mut NoopDelay)
913
913
.unwrap_err();
914
914
assert_eq!(err, Error::I2c(ErrorKind::Other));
915
915
sht.destroy().done();
···
924
924
fn sleep() {
925
925
let expectations = [Transaction::write(SHT_ADDR, alloc::vec![0xB0, 0x98])];
926
926
let mock = I2cMock::new(&expectations);
927
927
-
let mut sht = ShtC3::new(mock);
927
927
+
let mut sht = ShtC3::new(mock, PowerMode::NormalMode);
928
928
sht.sleep().unwrap();
929
929
sht.destroy().done();
930
930
}
···
934
934
fn wakeup() {
935
935
let expectations = [Transaction::write(SHT_ADDR, alloc::vec![0x35, 0x17])];
936
936
let mock = I2cMock::new(&expectations);
937
937
-
let mut sht = ShtC3::new(mock);
937
937
+
let mut sht = ShtC3::new(mock, PowerMode::NormalMode);
938
938
sht.wakeup(&mut NoopDelay).unwrap();
939
939
sht.destroy().done();
940
940
}
···
944
944
fn reset() {
945
945
let expectations = [Transaction::write(SHT_ADDR, alloc::vec![0x80, 0x5D])];
946
946
let mock = I2cMock::new(&expectations);
947
947
-
let mut sht = ShtC3::new(mock);
947
947
+
let mut sht = ShtC3::new(mock, PowerMode::NormalMode);
948
948
sht.reset(&mut NoopDelay).unwrap();
949
949
sht.destroy().done();
950
950
}
···
955
955
956
956
#[test]
957
957
fn shortcut_function() {
958
958
-
let c3 = ShtC3::new(I2cMock::new(&[]));
958
958
+
let c3 = ShtC3::new(I2cMock::new(&[]), PowerMode::NormalMode);
959
959
+
960
960
+
assert_eq!(c3.max_measurement_duration(), 12100);
961
961
+
962
962
+
let i2c = c3.destroy();
963
963
+
964
964
+
let c3 = ShtC3::new(i2c, PowerMode::LowPower);
959
965
960
960
-
assert_eq!(c3.max_measurement_duration(PowerMode::NormalMode), 12100);
961
961
-
assert_eq!(c3.max_measurement_duration(PowerMode::LowPower), 800);
966
966
+
assert_eq!(c3.max_measurement_duration(), 800);
962
967
963
968
c3.destroy().done();
964
969
}