Skip to content

Commit

Permalink
Make library no_std compatible (#5)
Browse files Browse the repository at this point in the history
* Use embedded_hal::blocking::delay::DelayMs instead of std::thread::sleep
* Make thiserror dependency an optional feature

Co-authored-by: Timo <[email protected]>
  • Loading branch information
t-moe and Timo authored Oct 27, 2023
1 parent f6f3e09 commit 7349166
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 42 deletions.
7 changes: 3 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "sht31"
description = "A library for the SHT31 temperature and humidity sensor"
version = "0.1.1"
version = "0.2.0"
edition = "2021"
license = "MIT"
repository = "https://github.com/FloppyDisck/SHT31-rs"
Expand All @@ -11,11 +11,10 @@ categories = ["embedded"]

[features]
esp32-fix = []
thiserror = ["dep:thiserror"]

[dependencies]
embedded-svc = "0.22.0"
embedded-hal = "0.2.7"

crc = "3.0.0"
anyhow = "1"
thiserror = "1.0.38"
thiserror = {version= "1.0.38", optional = true}
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ the current thread until the sensor does a reading.
use sht31::prelude::*;

fn main() -> Result<()> {
// Requires an 12c connection only
let sht = SHT31::new(i2c);
// Requires an i2c connection + delay (both from embedded_hal::blocking)
let sht = SHT31::new(i2c, delay);

loop {
let reading = sht.read()?;
Expand Down
21 changes: 10 additions & 11 deletions src/error.rs
Original file line number Diff line number Diff line change
@@ -1,36 +1,35 @@
use thiserror::Error;
pub type Result<T> = core::result::Result<T, SHTError>;

pub type Result<T> = std::result::Result<T, SHTError>;

#[derive(Error, Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq)]
#[cfg_attr(feature = "thiserror", derive(thiserror::Error))]
#[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq)]
pub enum SHTError {
#[error("Write Read I2C Error")]
#[cfg_attr(feature = "thiserror", error("Write Read I2C Error"))]
WriteReadI2CError,
#[error("Write I2C Error")]
#[cfg_attr(feature = "thiserror", error("Write I2C Error")) ]
WriteI2CError,
#[error("Humidity bytes [{bytes_start:#x}, {bytes_end:#x}] expected {expected_checksum:#x} but got the checksum {calculated_checksum:#x}")]
#[cfg_attr(feature = "thiserror", error("Humidity bytes [{bytes_start:#x}, {bytes_end:#x}] expected {expected_checksum:#x} but got the checksum {calculated_checksum:#x}"))]
InvalidHumidityChecksumError {
bytes_start: u8,
bytes_end: u8,
expected_checksum: u8,
calculated_checksum: u8,
},
#[error("Temperature bytes [{bytes_start:#x}, {bytes_end:#x}] expected {expected_checksum:#x} but got the checksum {calculated_checksum:#x}")]
#[cfg_attr(feature = "thiserror", error("Temperature bytes [{bytes_start:#x}, {bytes_end:#x}] expected {expected_checksum:#x} but got the checksum {calculated_checksum:#x}"))]
InvalidTemperatureChecksumError {
bytes_start: u8,
bytes_end: u8,
expected_checksum: u8,
calculated_checksum: u8,
},
#[error("Status bytes [{bytes_start:#x}, {bytes_end:#x}] expected {expected_checksum:#x} but got the checksum {calculated_checksum:#x}")]
#[cfg_attr(feature = "thiserror", error("Status bytes [{bytes_start:#x}, {bytes_end:#x}] expected {expected_checksum:#x} but got the checksum {calculated_checksum:#x}"))]
InvalidStatusChecksumError {
bytes_start: u8,
bytes_end: u8,
expected_checksum: u8,
calculated_checksum: u8,
},
#[error("Single shot reading timeout")]
#[cfg_attr(feature = "thiserror", error("Single shot reading timeout"))]
ReadingTimeoutError,
#[error("This error should not happen")]
#[cfg_attr(feature = "thiserror", error("This error should not happen"))]
PlaceholderError,
}
24 changes: 15 additions & 9 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
#![no_std]
use core::prelude::v1::*;

pub mod error;
pub mod mode;

use crate::mode::SimpleSingleShot;
use crc::{Algorithm, Crc};
use embedded_hal::blocking::i2c;
use embedded_hal::blocking::{i2c, delay::DelayMs};

pub use crate::error::{Result, SHTError};
pub mod prelude {
Expand Down Expand Up @@ -163,15 +166,16 @@ impl<Mode, I2C> SHT31<Mode, I2C> {
}

#[allow(dead_code)]
impl<I2C> SHT31<SimpleSingleShot, I2C>
impl<I2C, D> SHT31<SimpleSingleShot<D>, I2C>
where
I2C: i2c::WriteRead + i2c::Write,
D: DelayMs<u32>
{
/// Create a new sensor
/// I2C clock frequency must must be between 0 and 1000 kHz
pub fn new(i2c: I2C) -> Self {
pub fn new(i2c: I2C, delay: D) -> Self {
Self {
mode: SimpleSingleShot::new(),
mode: SimpleSingleShot::new(delay),
i2c,
address: DeviceAddr::default() as u8,
unit: TemperatureUnit::default(),
Expand Down Expand Up @@ -292,6 +296,11 @@ where
self.i2c_write(&[0x30, 0x41])
}

/// Consumes the instance and returns the i2c
pub fn destroy(self) -> I2C {
self.i2c
}

fn i2c_write(&mut self, bytes: &[u8]) -> Result<()> {
match self.i2c.write(self.address, bytes) {
Ok(res) => Ok(res),
Expand Down Expand Up @@ -366,27 +375,24 @@ mod test {
assert_eq!(
verify_reading(corrupt_temperature)
.err()
.unwrap()
.to_string(),
.unwrap(),
SHTError::InvalidTemperatureChecksumError {
bytes_start: 98,
bytes_end: 153,
expected_checksum: 180,
calculated_checksum: 188
}
.to_string()
);

let corrupt_humidity = [98, 153, 188, 98, 32, 180];
assert_eq!(
verify_reading(corrupt_humidity).err().unwrap().to_string(),
verify_reading(corrupt_humidity).err().unwrap(),
SHTError::InvalidHumidityChecksumError {
bytes_start: 98,
bytes_end: 32,
expected_checksum: 180,
calculated_checksum: 139
}
.to_string()
);
}

Expand Down
28 changes: 12 additions & 16 deletions src/mode/simple_single_shot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,23 @@ use crate::{
mode::{single_shot::single_shot_read, Sht31Reader},
Accuracy, Reading, SHT31,
};
use embedded_hal::blocking::i2c;
use std::{thread::sleep, time::Duration};
use embedded_hal::blocking::{i2c, delay::DelayMs};

/// A simple reading that blocks until the measurement is obtained
#[derive(Copy, Clone, Debug)]
pub struct SimpleSingleShot {
pub struct SimpleSingleShot <D: DelayMs<u32>>{
max_retries: u8,
ms_delay: u64,
ms_delay: u32,
delay: D
}

impl Default for SimpleSingleShot {
fn default() -> Self {
Self::new()
}
}

impl SimpleSingleShot {
impl <D> SimpleSingleShot<D> where D: DelayMs<u32> {
#[allow(dead_code)]
pub fn new() -> Self {
pub fn new(delay: D) -> Self {
Self {
max_retries: 8,
ms_delay: 100,
delay
}
}
/// Sets the max number of retries to read a sensor before giving up
Expand All @@ -37,19 +32,20 @@ impl SimpleSingleShot {
self
}
/// Sets the millisecond delay between each try
pub fn set_delay(&mut self, ms_delay: u64) {
pub fn set_delay(&mut self, ms_delay: u32) {
self.ms_delay = ms_delay
}
/// Sets the millisecond delay between each try
pub fn with_delay(mut self, ms_delay: u64) -> Self {
pub fn with_delay(mut self, ms_delay: u32) -> Self {
self.set_delay(ms_delay);
self
}
}

impl<I2C> Sht31Reader for SHT31<SimpleSingleShot, I2C>
impl<I2C, D> Sht31Reader for SHT31<SimpleSingleShot<D>, I2C>
where
I2C: i2c::WriteRead + i2c::Write,
D: DelayMs<u32>
{
/// It will initiate a read and wont stop until its either exhausted its retries or a reading is found
fn read(&mut self) -> Result<Reading> {
Expand All @@ -69,7 +65,7 @@ where
read_attempt = single_shot_read(self);

if read_attempt.is_err() {
sleep(Duration::from_millis(self.mode.ms_delay))
self.mode.delay.delay_ms(self.mode.ms_delay);
} else {
return read_attempt;
}
Expand Down

0 comments on commit 7349166

Please sign in to comment.