commit
ebb40f0047
8 changed files with 585 additions and 490 deletions
13
.github/workflows/ci.yml
vendored
13
.github/workflows/ci.yml
vendored
|
@ -48,16 +48,3 @@ jobs:
|
||||||
with:
|
with:
|
||||||
command: clippy
|
command: clippy
|
||||||
args: -- -D warnings
|
args: -- -D warnings
|
||||||
|
|
||||||
license-check:
|
|
||||||
name: Check Licenses and Security Advisories
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
checks:
|
|
||||||
- advisories bans licenses sources
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
- uses: EmbarkStudios/cargo-deny-action@v1
|
|
||||||
with:
|
|
||||||
command: check ${{ matrix.checks }}
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ embedded-hal = "=1.0.0"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
serde = { version = "1.0", optional = true, default-features = false, features = ["derive"] }
|
serde = { version = "1.0", optional = true, default-features = false, features = ["derive"] }
|
||||||
linux-embedded-hal = "0.4.0"
|
linux-embedded-hal = "0.4.0"
|
||||||
|
anyhow = "1.0.80"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
env_logger = "0.9"
|
env_logger = "0.9"
|
|
@ -10,7 +10,7 @@ To use this library, create a new project and add it as a dependency:
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bme680 = {git = "https://github.com/dnutiu/bme680-rust.git", version = "0.7.0"}
|
bme680 = {git = "https://github.com/dnutiu/bme680-rust.git", version = "0.8.0"}
|
||||||
```
|
```
|
||||||
|
|
||||||
# Alternative
|
# Alternative
|
||||||
|
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
@ -1,23 +1,21 @@
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
use bme680::{Bme680, Error, I2CAddress, IIRFilterSize, OversamplingSetting, PowerMode, SettingsBuilder};
|
use bme680::i2c::Address;
|
||||||
use core::result;
|
use bme680::{Bme680, IIRFilterSize, OversamplingSetting, PowerMode, SettingsBuilder};
|
||||||
use core::time::Duration;
|
use core::time::Duration;
|
||||||
use embedded_hal::delay::DelayNs;
|
use embedded_hal::delay::DelayNs;
|
||||||
use linux_embedded_hal as hal;
|
use linux_embedded_hal as hal;
|
||||||
use linux_embedded_hal::{Delay, I2CError};
|
use linux_embedded_hal::Delay;
|
||||||
use log::info;
|
use log::info;
|
||||||
|
|
||||||
|
|
||||||
// Please export RUST_LOG=info in order to see logs in the console.
|
// Please export RUST_LOG=info in order to see logs in the console.
|
||||||
fn main() -> result::Result<(), Error<I2CError>>
|
fn main() -> Result<(), anyhow::Error> {
|
||||||
{
|
|
||||||
env_logger::init();
|
env_logger::init();
|
||||||
|
|
||||||
let i2c = hal::I2cdev::new("/dev/i2c-1").unwrap();
|
let i2c = hal::I2cdev::new("/dev/i2c-1").unwrap();
|
||||||
let mut delayer = Delay {};
|
let mut delayer = Delay {};
|
||||||
|
|
||||||
let mut dev = Bme680::init(i2c, &mut delayer, I2CAddress::Primary)?;
|
let mut dev = Bme680::init(i2c, &mut delayer, Address::Primary)?;
|
||||||
let mut delay = Delay {};
|
let mut delay = Delay {};
|
||||||
|
|
||||||
let settings = SettingsBuilder::new()
|
let settings = SettingsBuilder::new()
|
||||||
|
@ -25,12 +23,11 @@ fn main() -> result::Result<(), Error<I2CError>>
|
||||||
.with_pressure_oversampling(OversamplingSetting::OS4x)
|
.with_pressure_oversampling(OversamplingSetting::OS4x)
|
||||||
.with_temperature_oversampling(OversamplingSetting::OS8x)
|
.with_temperature_oversampling(OversamplingSetting::OS8x)
|
||||||
.with_temperature_filter(IIRFilterSize::Size3)
|
.with_temperature_filter(IIRFilterSize::Size3)
|
||||||
.with_gas_measurement(Duration::from_millis(1500), 320, 25)
|
.with_gas_measurement(Duration::from_millis(1500), 320, 23)
|
||||||
.with_temperature_offset(-2.2)
|
|
||||||
.with_run_gas(true)
|
.with_run_gas(true)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
let profile_dur = dev.get_profile_dur(&settings.0)?;
|
let profile_dur = dev.get_profile_duration(&settings.0)?;
|
||||||
info!("Profile duration {:?}", profile_dur);
|
info!("Profile duration {:?}", profile_dur);
|
||||||
info!("Setting sensor settings");
|
info!("Setting sensor settings");
|
||||||
dev.set_sensor_settings(&mut delayer, settings)?;
|
dev.set_sensor_settings(&mut delayer, settings)?;
|
||||||
|
@ -47,7 +44,7 @@ fn main() -> result::Result<(), Error<I2CError>>
|
||||||
info!("Setting forced power modes");
|
info!("Setting forced power modes");
|
||||||
dev.set_sensor_mode(&mut delayer, PowerMode::ForcedMode)?;
|
dev.set_sensor_mode(&mut delayer, PowerMode::ForcedMode)?;
|
||||||
info!("Retrieving sensor data");
|
info!("Retrieving sensor data");
|
||||||
let (data, _state) = dev.get_sensor_data(&mut delayer)?;
|
let (data, _state) = dev.get_measurement(&mut delayer)?;
|
||||||
info!("Sensor Data {:?}", data);
|
info!("Sensor Data {:?}", data);
|
||||||
info!("Temperature {}°C", data.temperature_celsius());
|
info!("Temperature {}°C", data.temperature_celsius());
|
||||||
info!("Pressure {}hPa", data.pressure_hpa());
|
info!("Pressure {}hPa", data.pressure_hpa());
|
||||||
|
|
|
@ -5,14 +5,27 @@ use core::time::Duration;
|
||||||
pub struct Calculation {}
|
pub struct Calculation {}
|
||||||
|
|
||||||
impl Calculation {
|
impl Calculation {
|
||||||
pub fn heater_resistance(calibration_data: &CalibrationData, ambient_temperature: i8, temperature: u16) -> u8 {
|
/// Calculates and returns the sensor's heater resistance.
|
||||||
|
/// * `calibration_data` - The calibration data of the sensor.
|
||||||
|
/// * `ambient_temperature` - The ambient temperature.
|
||||||
|
/// * `heater_temperature` - The heater temperature.
|
||||||
|
pub fn heater_resistance(
|
||||||
|
calibration_data: &CalibrationData,
|
||||||
|
ambient_temperature: i8,
|
||||||
|
heater_temperature: u16,
|
||||||
|
) -> u8 {
|
||||||
// cap temperature
|
// cap temperature
|
||||||
let temp = if temperature <= 400 { temperature } else { 400 };
|
let temp = if heater_temperature <= 400 {
|
||||||
|
heater_temperature
|
||||||
|
} else {
|
||||||
|
400
|
||||||
|
};
|
||||||
|
|
||||||
let var1 = ambient_temperature as i32 * calibration_data.par_gh3 as i32 / 1000i32 * 256i32;
|
let var1 = ambient_temperature as i32 * calibration_data.par_gh3 as i32 / 1000i32 * 256i32;
|
||||||
let var2 = (calibration_data.par_gh1 as i32 + 784i32)
|
let var2 = (calibration_data.par_gh1 as i32 + 784i32)
|
||||||
* (((calibration_data.par_gh2 as i32 + 154009i32) * temp as i32 * 5i32 / 100i32 + 3276800i32)
|
* (((calibration_data.par_gh2 as i32 + 154009i32) * temp as i32 * 5i32 / 100i32
|
||||||
/ 10i32);
|
+ 3276800i32)
|
||||||
|
/ 10i32);
|
||||||
let var3 = var1 + var2 / 2i32;
|
let var3 = var1 + var2 / 2i32;
|
||||||
let var4 = var3 / (calibration_data.res_heat_range as i32 + 4i32);
|
let var4 = var3 / (calibration_data.res_heat_range as i32 + 4i32);
|
||||||
let var5 = 131i32 * calibration_data.res_heat_val as i32 + 65536i32;
|
let var5 = 131i32 * calibration_data.res_heat_val as i32 + 65536i32;
|
||||||
|
@ -20,12 +33,13 @@ impl Calculation {
|
||||||
((heatr_res_x100 + 50i32) / 100i32) as u8
|
((heatr_res_x100 + 50i32) / 100i32) as u8
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Calculates and returns the heater duration.
|
||||||
|
/// * `duration` The duration time
|
||||||
pub fn heater_duration(duration: Duration) -> u8 {
|
pub fn heater_duration(duration: Duration) -> u8 {
|
||||||
let mut factor: u8 = 0u8;
|
let mut factor: u8 = 0u8;
|
||||||
// TODO replace once https://github.com/rust-lang/rust/pull/50167 has been merged
|
|
||||||
const MILLIS_PER_SEC: u64 = 1_000;
|
const MILLIS_PER_SEC: u64 = 1_000;
|
||||||
const NANOS_PER_MILLI: u64 = 1_000_000;
|
const NANOS_PER_MILLI: u64 = 1_000_000;
|
||||||
let mut dur = (duration.as_secs() as u64 * MILLIS_PER_SEC)
|
let mut dur = (duration.as_secs() * MILLIS_PER_SEC)
|
||||||
+ (duration.subsec_nanos() as u64 / NANOS_PER_MILLI);
|
+ (duration.subsec_nanos() as u64 / NANOS_PER_MILLI);
|
||||||
if dur as i32 >= 0xfc0i32 {
|
if dur as i32 >= 0xfc0i32 {
|
||||||
0xffu8 // Max duration
|
0xffu8 // Max duration
|
||||||
|
@ -41,9 +55,9 @@ impl Calculation {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
/// Calculates and returns the sensor temperature.
|
||||||
/// * `calib` - Calibration data used during initalization
|
/// * `calibration_data` - Calibration data used during initialization
|
||||||
/// * `temp_adc`
|
/// * `temp_adc` - The temperature reading of the analog to digital converter.
|
||||||
/// * `temp_offset` - If set, the temperature t_fine will be increased by given
|
/// * `temp_offset` - If set, the temperature t_fine will be increased by given
|
||||||
/// value in celsius. Temperature offset in Celsius, e.g. 4, -8, 1.25
|
/// value in celsius. Temperature offset in Celsius, e.g. 4, -8, 1.25
|
||||||
pub fn temperature(
|
pub fn temperature(
|
||||||
|
@ -70,17 +84,23 @@ impl Calculation {
|
||||||
(calc_temp, t_fine)
|
(calc_temp, t_fine)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pressure(calibration_data: &CalibrationData, t_fine: i32, pres_adc: u32) -> u32 {
|
/// Calculates and returns the pressure of the sensor.
|
||||||
|
///
|
||||||
|
/// * `t_fine` - The resolution temperature obtained after applying calibration data.
|
||||||
|
/// * `pressure_adc` - The pressure value as returned by the analog to digital converter.
|
||||||
|
pub fn pressure(calibration_data: &CalibrationData, t_fine: i32, pressure_adc: u32) -> u32 {
|
||||||
let mut var1: i32 = (t_fine >> 1) - 64000;
|
let mut var1: i32 = (t_fine >> 1) - 64000;
|
||||||
let mut var2: i32 = ((((var1 >> 2) * (var1 >> 2)) >> 11) * calibration_data.par_p6 as i32) >> 2;
|
let mut var2: i32 =
|
||||||
|
((((var1 >> 2) * (var1 >> 2)) >> 11) * calibration_data.par_p6 as i32) >> 2;
|
||||||
var2 += (var1 * (calibration_data.par_p5 as i32)) << 1;
|
var2 += (var1 * (calibration_data.par_p5 as i32)) << 1;
|
||||||
var2 = (var2 >> 2i32) + ((calibration_data.par_p4 as i32) << 16i32);
|
var2 = (var2 >> 2i32) + ((calibration_data.par_p4 as i32) << 16i32);
|
||||||
var1 = (((((var1 >> 2i32) * (var1 >> 2i32)) >> 13i32) * ((calibration_data.par_p3 as i32) << 5i32))
|
var1 = (((((var1 >> 2i32) * (var1 >> 2i32)) >> 13i32)
|
||||||
|
* ((calibration_data.par_p3 as i32) << 5i32))
|
||||||
>> 3i32)
|
>> 3i32)
|
||||||
+ ((calibration_data.par_p2 as i32 * var1) >> 1i32);
|
+ ((calibration_data.par_p2 as i32 * var1) >> 1i32);
|
||||||
var1 >>= 18i32;
|
var1 >>= 18i32;
|
||||||
var1 = ((32768i32 + var1) * calibration_data.par_p1 as i32) >> 15i32;
|
var1 = ((32768i32 + var1) * calibration_data.par_p1 as i32) >> 15i32;
|
||||||
let mut pressure_comp: i32 = 1048576u32.wrapping_sub(pres_adc) as i32;
|
let mut pressure_comp: i32 = 1048576u32.wrapping_sub(pressure_adc) as i32;
|
||||||
pressure_comp = ((pressure_comp - (var2 >> 12i32)) as u32).wrapping_mul(3125u32) as i32;
|
pressure_comp = ((pressure_comp - (var2 >> 12i32)) as u32).wrapping_mul(3125u32) as i32;
|
||||||
if pressure_comp >= 0x40000000i32 {
|
if pressure_comp >= 0x40000000i32 {
|
||||||
pressure_comp = ((pressure_comp as u32).wrapping_div(var1 as u32) << 1i32) as i32;
|
pressure_comp = ((pressure_comp as u32).wrapping_div(var1 as u32) << 1i32) as i32;
|
||||||
|
@ -100,15 +120,21 @@ impl Calculation {
|
||||||
pressure_comp as u32
|
pressure_comp as u32
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn humidity(calibration_data: &CalibrationData, t_fine: i32, hum_adc: u16) -> u32 {
|
/// Calculates and returns the humidity of the sensor.
|
||||||
|
///
|
||||||
|
/// * `t_fine` - The resolution temperature obtained after applying calibration data.
|
||||||
|
/// * `humidity_adc` - The humidity value as returned by the analog to digital converter.
|
||||||
|
pub fn humidity(calibration_data: &CalibrationData, t_fine: i32, humidity_adc: u16) -> u32 {
|
||||||
let temp_scaled: i32 = (t_fine * 5i32 + 128i32) >> 8i32;
|
let temp_scaled: i32 = (t_fine * 5i32 + 128i32) >> 8i32;
|
||||||
let var1: i32 = hum_adc as i32
|
let var1: i32 = humidity_adc as i32
|
||||||
- calibration_data.par_h1 as i32 * 16i32
|
- calibration_data.par_h1 as i32 * 16i32
|
||||||
- ((temp_scaled * calibration_data.par_h3 as i32 / 100i32) >> 1i32);
|
- ((temp_scaled * calibration_data.par_h3 as i32 / 100i32) >> 1i32);
|
||||||
let var2: i32 = (calibration_data.par_h2 as i32
|
let var2: i32 = (calibration_data.par_h2 as i32
|
||||||
* (temp_scaled * calibration_data.par_h4 as i32 / 100i32
|
* (temp_scaled * calibration_data.par_h4 as i32 / 100i32
|
||||||
+ ((temp_scaled * (temp_scaled * calibration_data.par_h5 as i32 / 100i32)) >> 6i32) / 100i32
|
+ ((temp_scaled * (temp_scaled * calibration_data.par_h5 as i32 / 100i32))
|
||||||
+ (1i32 << 14i32)))
|
>> 6i32)
|
||||||
|
/ 100i32
|
||||||
|
+ (1i32 << 14i32)))
|
||||||
>> 10i32;
|
>> 10i32;
|
||||||
let var3: i32 = var1 * var2;
|
let var3: i32 = var1 * var2;
|
||||||
let var4: i32 = (calibration_data.par_h6 as i32) << 7i32;
|
let var4: i32 = (calibration_data.par_h6 as i32) << 7i32;
|
||||||
|
@ -124,7 +150,15 @@ impl Calculation {
|
||||||
calc_hum as u32
|
calc_hum as u32
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn gas_resistance(calibration_data: &CalibrationData, gas_res_adc: u16, gas_range: u8) -> u32 {
|
/// Calculates and returns the gas resistance.
|
||||||
|
///
|
||||||
|
/// * `gas_resistance_adc` - The gas resistance reading from the analog to digital converter.
|
||||||
|
/// * `gas_range` - The lookup table gas range.
|
||||||
|
pub fn gas_resistance(
|
||||||
|
calibration_data: &CalibrationData,
|
||||||
|
gas_resistance_adc: u16,
|
||||||
|
gas_range: u8,
|
||||||
|
) -> u32 {
|
||||||
let lookup_table1: [u32; 16] = [
|
let lookup_table1: [u32; 16] = [
|
||||||
2147483647u32,
|
2147483647u32,
|
||||||
2147483647u32,
|
2147483647u32,
|
||||||
|
@ -164,7 +198,7 @@ impl Calculation {
|
||||||
let var1: i64 = ((1340 + 5 * calibration_data.range_sw_err as i64)
|
let var1: i64 = ((1340 + 5 * calibration_data.range_sw_err as i64)
|
||||||
* lookup_table1[gas_range as usize] as i64)
|
* lookup_table1[gas_range as usize] as i64)
|
||||||
>> 16;
|
>> 16;
|
||||||
let var2: u64 = (((gas_res_adc as i64) << 15) - 16777216 + var1) as u64;
|
let var2: u64 = (((gas_resistance_adc as i64) << 15) - 16777216 + var1) as u64;
|
||||||
let var3: i64 = (lookup_table2[gas_range as usize] as i64 * var1) >> 9;
|
let var3: i64 = (lookup_table2[gas_range as usize] as i64 * var1) >> 9;
|
||||||
let calc_gas_res: u32 = ((var3 + ((var2 as i64) >> 1i64)) / var2 as i64) as u32;
|
let calc_gas_res: u32 = ((var3 + ((var2 as i64) >> 1i64)) / var2 as i64) as u32;
|
||||||
calc_gas_res
|
calc_gas_res
|
||||||
|
|
105
src/i2c.rs
Normal file
105
src/i2c.rs
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
use anyhow::anyhow;
|
||||||
|
use core::fmt::{Display, Formatter};
|
||||||
|
use embedded_hal::i2c::I2c;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Represents the I2C address of the BME680 Sensor.
|
||||||
|
///
|
||||||
|
#[derive(Debug, Clone, Copy, Default)]
|
||||||
|
pub enum Address {
|
||||||
|
/// Primary Address 0x76
|
||||||
|
#[default]
|
||||||
|
Primary,
|
||||||
|
/// Secondary Address 0x77
|
||||||
|
Secondary,
|
||||||
|
/// Alternative address
|
||||||
|
Other(u8),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Address {
|
||||||
|
pub fn addr(&self) -> u8 {
|
||||||
|
match &self {
|
||||||
|
Address::Primary => 0x76u8,
|
||||||
|
Address::Secondary => 0x77u8,
|
||||||
|
Address::Other(addr) => *addr,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for Address {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
|
||||||
|
write!(f, "Address={:#01x}", self.addr())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// I2CUtility is a simple wrapper over the I2c trait to make reading and writing data easier.
|
||||||
|
pub(crate) struct I2CUtility {}
|
||||||
|
|
||||||
|
impl I2CUtility {
|
||||||
|
/// Reads a byte from the I2C bus.
|
||||||
|
pub fn read_byte<I2C: I2c>(
|
||||||
|
i2c_handle: &mut I2C,
|
||||||
|
device_address: u8,
|
||||||
|
register_address: u8,
|
||||||
|
) -> Result<u8, anyhow::Error> {
|
||||||
|
let mut buf = [0; 1];
|
||||||
|
|
||||||
|
i2c_handle
|
||||||
|
.write(device_address, &[register_address])
|
||||||
|
.map_err(|e| {
|
||||||
|
anyhow!(
|
||||||
|
"Failed to write a byte {} to device {}: {:?}",
|
||||||
|
register_address,
|
||||||
|
device_address,
|
||||||
|
e
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
|
||||||
|
match i2c_handle.read(device_address, &mut buf) {
|
||||||
|
Ok(()) => Ok(buf[0]),
|
||||||
|
Err(_e) => Err(anyhow!(
|
||||||
|
"Failed to read byte {} from device {}",
|
||||||
|
register_address,
|
||||||
|
device_address
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Reads bytes from the I2C bus.
|
||||||
|
pub fn read_bytes<I2C: I2c>(
|
||||||
|
i2c_handle: &mut I2C,
|
||||||
|
device_address: u8,
|
||||||
|
register_address: u8,
|
||||||
|
buffer: &mut [u8],
|
||||||
|
) -> Result<(), anyhow::Error> {
|
||||||
|
i2c_handle
|
||||||
|
.write(device_address, &[register_address])
|
||||||
|
.map_err(|_e| {
|
||||||
|
anyhow!(
|
||||||
|
"Failed to write a byte {} from device {}",
|
||||||
|
register_address,
|
||||||
|
device_address
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
|
||||||
|
match i2c_handle.read(device_address, buffer) {
|
||||||
|
Ok(()) => Ok(()),
|
||||||
|
Err(_e) => Err(anyhow!(
|
||||||
|
"Failed to read bytes from register {} and device {}",
|
||||||
|
register_address,
|
||||||
|
device_address
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Writes bytes to the I2C bus.
|
||||||
|
pub fn write_bytes<I2C: I2c>(
|
||||||
|
i2c_handle: &mut I2C,
|
||||||
|
device_address: u8,
|
||||||
|
buffer: &[u8],
|
||||||
|
) -> Result<(), anyhow::Error> {
|
||||||
|
i2c_handle
|
||||||
|
.write(device_address, buffer)
|
||||||
|
.map_err(|_e| anyhow!("Failed to write bytes to address {}", device_address))
|
||||||
|
}
|
||||||
|
}
|
747
src/lib.rs
747
src/lib.rs
File diff suppressed because it is too large
Load diff
116
src/settings.rs
116
src/settings.rs
|
@ -14,16 +14,15 @@ pub enum OversamplingSetting {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl OversamplingSetting {
|
impl OversamplingSetting {
|
||||||
// TODO replace with TryFrom once stabilized
|
pub fn from_u8(value: u8) -> OversamplingSetting {
|
||||||
pub fn from_u8(os: u8) -> OversamplingSetting {
|
match value {
|
||||||
match os {
|
|
||||||
0 => OversamplingSetting::OSNone,
|
0 => OversamplingSetting::OSNone,
|
||||||
1 => OversamplingSetting::OS1x,
|
1 => OversamplingSetting::OS1x,
|
||||||
2 => OversamplingSetting::OS2x,
|
2 => OversamplingSetting::OS2x,
|
||||||
3 => OversamplingSetting::OS4x,
|
3 => OversamplingSetting::OS4x,
|
||||||
4 => OversamplingSetting::OS8x,
|
4 => OversamplingSetting::OS8x,
|
||||||
5 => OversamplingSetting::OS16x,
|
5 => OversamplingSetting::OS16x,
|
||||||
_ => panic!("Unknown oversampling setting: {}", os),
|
_ => panic!("Unknown oversampling setting: {}", value),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -43,9 +42,8 @@ pub enum IIRFilterSize {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IIRFilterSize {
|
impl IIRFilterSize {
|
||||||
// TODO replace with TryFrom once stabilized
|
pub fn from_u8(value: u8) -> IIRFilterSize {
|
||||||
pub fn from_u8(os: u8) -> IIRFilterSize {
|
match value {
|
||||||
match os {
|
|
||||||
0 => IIRFilterSize::Size0,
|
0 => IIRFilterSize::Size0,
|
||||||
1 => IIRFilterSize::Size1,
|
1 => IIRFilterSize::Size1,
|
||||||
2 => IIRFilterSize::Size3,
|
2 => IIRFilterSize::Size3,
|
||||||
|
@ -54,7 +52,7 @@ impl IIRFilterSize {
|
||||||
5 => IIRFilterSize::Size31,
|
5 => IIRFilterSize::Size31,
|
||||||
6 => IIRFilterSize::Size63,
|
6 => IIRFilterSize::Size63,
|
||||||
7 => IIRFilterSize::Size127,
|
7 => IIRFilterSize::Size127,
|
||||||
_ => panic!("Unknown IIRFilterSize: {}", os),
|
_ => panic!("Unknown IIRFilterSize: {}", value),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -62,20 +60,20 @@ impl IIRFilterSize {
|
||||||
/// Temperature settings
|
/// Temperature settings
|
||||||
#[derive(Debug, Default, Copy)]
|
#[derive(Debug, Default, Copy)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct TphSett {
|
pub struct TemperatureSettings {
|
||||||
/// Humidity oversampling
|
/// Humidity oversampling
|
||||||
pub os_hum: Option<OversamplingSetting>,
|
pub humidity_oversampling: Option<OversamplingSetting>,
|
||||||
/// Temperature oversampling
|
/// Temperature oversampling
|
||||||
pub os_temp: Option<OversamplingSetting>,
|
pub temperature_oversampling: Option<OversamplingSetting>,
|
||||||
/// Pressure oversampling
|
/// Pressure oversampling
|
||||||
pub os_pres: Option<OversamplingSetting>,
|
pub pressure_oversampling: Option<OversamplingSetting>,
|
||||||
/// Filter coefficient
|
/// Filter coefficient
|
||||||
pub filter: Option<IIRFilterSize>,
|
pub filter_size: Option<IIRFilterSize>,
|
||||||
/// If set, the temperature t_fine will be increased by the given value in celsius.
|
/// If set, the temperature t_fine will be increased by the given value in celsius.
|
||||||
pub temperature_offset: Option<f32>,
|
pub temperature_offset: Option<f32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Clone for TphSett {
|
impl Clone for TemperatureSettings {
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
*self
|
*self
|
||||||
}
|
}
|
||||||
|
@ -84,20 +82,22 @@ impl Clone for TphSett {
|
||||||
/// Gas measurement settings
|
/// Gas measurement settings
|
||||||
#[derive(Debug, Default, Copy)]
|
#[derive(Debug, Default, Copy)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct GasSett {
|
pub struct GasSettings {
|
||||||
|
/// nb_conv is used to select heater set-points of the sensor.
|
||||||
pub nb_conv: u8,
|
pub nb_conv: u8,
|
||||||
/// Heater control
|
/// Heater control
|
||||||
pub heatr_ctrl: Option<u8>,
|
pub heater_control: Option<u8>,
|
||||||
/// Enable measurement of gas, disabled by default
|
/// Enable measurement of gas, disabled by default
|
||||||
pub run_gas_measurement: bool,
|
pub enable_gas_measurement: bool,
|
||||||
/// Heater temperature
|
/// The heater temperature
|
||||||
pub heatr_temp: Option<u16>,
|
pub heater_temperature: Option<u16>,
|
||||||
/// Profile duration
|
/// The Heating duration
|
||||||
pub heatr_dur: Option<Duration>,
|
pub heater_duration: Option<Duration>,
|
||||||
|
/// The ambient temperature.
|
||||||
pub ambient_temperature: i8,
|
pub ambient_temperature: i8,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Clone for GasSett {
|
impl Clone for GasSettings {
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
*self
|
*self
|
||||||
}
|
}
|
||||||
|
@ -107,9 +107,9 @@ impl Clone for GasSett {
|
||||||
#[derive(Debug, Default, Copy)]
|
#[derive(Debug, Default, Copy)]
|
||||||
pub struct SensorSettings {
|
pub struct SensorSettings {
|
||||||
/// Gas settings
|
/// Gas settings
|
||||||
pub gas_sett: GasSett,
|
pub gas_settings: GasSettings,
|
||||||
/// Temperature settings
|
/// Temperature settings
|
||||||
pub tph_sett: TphSett,
|
pub temperature_settings: TemperatureSettings,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Clone for SensorSettings {
|
impl Clone for SensorSettings {
|
||||||
|
@ -132,9 +132,9 @@ bitflags! {
|
||||||
/// To set gas measurement setting.
|
/// To set gas measurement setting.
|
||||||
const GAS_MEAS_SEL = 8;
|
const GAS_MEAS_SEL = 8;
|
||||||
/// To set filter setting.
|
/// To set filter setting.
|
||||||
const FILTER_SEL = 16;
|
const FILTER_SIZE_SEL = 16;
|
||||||
/// To set humidity control setting.
|
/// To set humidity control setting.
|
||||||
const HCNTRL_SEL = 32;
|
const HUMIDITY_CONTROL_SEL = 32;
|
||||||
/// To set run gas setting.
|
/// To set run gas setting.
|
||||||
const RUN_GAS_SEL = 64;
|
const RUN_GAS_SEL = 64;
|
||||||
/// To set NB conversion setting.
|
/// To set NB conversion setting.
|
||||||
|
@ -171,74 +171,96 @@ pub struct SettingsBuilder {
|
||||||
pub type Settings = (SensorSettings, DesiredSensorSettings);
|
pub type Settings = (SensorSettings, DesiredSensorSettings);
|
||||||
|
|
||||||
impl SettingsBuilder {
|
impl SettingsBuilder {
|
||||||
|
/// Constructs a new instance of the SettingsBuilder.
|
||||||
pub fn new() -> SettingsBuilder {
|
pub fn new() -> SettingsBuilder {
|
||||||
SettingsBuilder::default()
|
SettingsBuilder::default()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_temperature_filter(mut self, filter: IIRFilterSize) -> SettingsBuilder {
|
/// With temperature filter.
|
||||||
self.sensor_settings.tph_sett.filter = Some(filter);
|
pub fn with_temperature_filter(mut self, filter_size: IIRFilterSize) -> SettingsBuilder {
|
||||||
self.desired_settings |= DesiredSensorSettings::FILTER_SEL;
|
self.sensor_settings.temperature_settings.filter_size = Some(filter_size);
|
||||||
|
self.desired_settings |= DesiredSensorSettings::FILTER_SIZE_SEL;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_humidity_control(mut self, heatr_control: u8) -> SettingsBuilder {
|
/// With gas heater control.
|
||||||
self.sensor_settings.gas_sett.heatr_ctrl = Some(heatr_control);
|
pub fn with_gas_heater_control(mut self, heater_control: u8) -> SettingsBuilder {
|
||||||
self.desired_settings |= DesiredSensorSettings::HCNTRL_SEL;
|
self.sensor_settings.gas_settings.heater_control = Some(heater_control);
|
||||||
|
self.desired_settings |= DesiredSensorSettings::HUMIDITY_CONTROL_SEL;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// With temperature oversampling
|
||||||
pub fn with_temperature_oversampling(
|
pub fn with_temperature_oversampling(
|
||||||
mut self,
|
mut self,
|
||||||
os_temp: OversamplingSetting,
|
temperature_oversampling: OversamplingSetting,
|
||||||
) -> SettingsBuilder {
|
) -> SettingsBuilder {
|
||||||
self.sensor_settings.tph_sett.os_temp = Some(os_temp);
|
self.sensor_settings
|
||||||
|
.temperature_settings
|
||||||
|
.temperature_oversampling = Some(temperature_oversampling);
|
||||||
self.desired_settings |= DesiredSensorSettings::OST_SEL;
|
self.desired_settings |= DesiredSensorSettings::OST_SEL;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_pressure_oversampling(mut self, os_pres: OversamplingSetting) -> SettingsBuilder {
|
/// With pressure oversampling.
|
||||||
self.sensor_settings.tph_sett.os_pres = Some(os_pres);
|
pub fn with_pressure_oversampling(
|
||||||
|
mut self,
|
||||||
|
pressure_oversampling: OversamplingSetting,
|
||||||
|
) -> SettingsBuilder {
|
||||||
|
self.sensor_settings
|
||||||
|
.temperature_settings
|
||||||
|
.pressure_oversampling = Some(pressure_oversampling);
|
||||||
self.desired_settings |= DesiredSensorSettings::OSP_SEL;
|
self.desired_settings |= DesiredSensorSettings::OSP_SEL;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_humidity_oversampling(mut self, os_hum: OversamplingSetting) -> SettingsBuilder {
|
/// With humidity oversampling.
|
||||||
self.sensor_settings.tph_sett.os_hum = Some(os_hum);
|
pub fn with_humidity_oversampling(
|
||||||
|
mut self,
|
||||||
|
humidity_oversampling: OversamplingSetting,
|
||||||
|
) -> SettingsBuilder {
|
||||||
|
self.sensor_settings
|
||||||
|
.temperature_settings
|
||||||
|
.humidity_oversampling = Some(humidity_oversampling);
|
||||||
self.desired_settings |= DesiredSensorSettings::OSH_SEL;
|
self.desired_settings |= DesiredSensorSettings::OSH_SEL;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// With gas measurement.
|
||||||
pub fn with_gas_measurement(
|
pub fn with_gas_measurement(
|
||||||
mut self,
|
mut self,
|
||||||
heatr_dur: Duration,
|
heater_duration: Duration,
|
||||||
heatr_temp: u16,
|
heater_temperature: u16,
|
||||||
ambient_temperature: i8,
|
ambient_temperature: i8,
|
||||||
) -> SettingsBuilder {
|
) -> SettingsBuilder {
|
||||||
self.sensor_settings.gas_sett.heatr_dur = Some(heatr_dur);
|
self.sensor_settings.gas_settings.heater_duration = Some(heater_duration);
|
||||||
self.sensor_settings.gas_sett.heatr_temp = Some(heatr_temp);
|
self.sensor_settings.gas_settings.heater_temperature = Some(heater_temperature);
|
||||||
self.sensor_settings.gas_sett.ambient_temperature = ambient_temperature;
|
self.sensor_settings.gas_settings.ambient_temperature = ambient_temperature;
|
||||||
self.desired_settings |= DesiredSensorSettings::GAS_SENSOR_SEL;
|
self.desired_settings |= DesiredSensorSettings::GAS_SENSOR_SEL;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// With nb_conv.
|
||||||
pub fn with_nb_conv(mut self, nb_conv: u8) -> SettingsBuilder {
|
pub fn with_nb_conv(mut self, nb_conv: u8) -> SettingsBuilder {
|
||||||
self.sensor_settings.gas_sett.nb_conv = nb_conv;
|
self.sensor_settings.gas_settings.nb_conv = nb_conv;
|
||||||
self.desired_settings |= DesiredSensorSettings::GAS_SENSOR_SEL;
|
self.desired_settings |= DesiredSensorSettings::GAS_SENSOR_SEL;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// With run gas.
|
||||||
pub fn with_run_gas(mut self, run_gas: bool) -> SettingsBuilder {
|
pub fn with_run_gas(mut self, run_gas: bool) -> SettingsBuilder {
|
||||||
self.sensor_settings.gas_sett.run_gas_measurement = run_gas;
|
self.sensor_settings.gas_settings.enable_gas_measurement = run_gas;
|
||||||
self.desired_settings |= DesiredSensorSettings::GAS_SENSOR_SEL;
|
self.desired_settings |= DesiredSensorSettings::GAS_SENSOR_SEL;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Temperature offset in Celsius, e.g. 4, -8, 1.25
|
/// With temperature offset in Celsius, e.g. 4, -8, 1.25
|
||||||
pub fn with_temperature_offset(mut self, offset: f32) -> SettingsBuilder {
|
pub fn with_temperature_offset(mut self, offset: f32) -> SettingsBuilder {
|
||||||
self.sensor_settings.tph_sett.temperature_offset = Some(offset);
|
self.sensor_settings.temperature_settings.temperature_offset = Some(offset);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Builds the settings object
|
||||||
pub fn build(self) -> Settings {
|
pub fn build(self) -> Settings {
|
||||||
(self.sensor_settings, self.desired_settings)
|
(self.sensor_settings, self.desired_settings)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue