diff --git a/examples/reading_temperature.rs b/examples/reading_temperature.rs index bd10b0b..0805f36 100644 --- a/examples/reading_temperature.rs +++ b/examples/reading_temperature.rs @@ -30,7 +30,7 @@ fn main() -> result::Result< sensor_settings.tph_sett.filter = Some(2); sensor_settings.gas_sett.run_gas = Some(0x01); - sensor_settings.gas_sett.heatr_dur = Some(1500); + sensor_settings.gas_sett.heatr_dur = Some(Duration::from_millis(1500)); sensor_settings.gas_sett.heatr_temp = Some(320); let settings_sel = DesiredSensorSettings::OST_SEL | DesiredSensorSettings::OSP_SEL @@ -38,7 +38,7 @@ fn main() -> result::Result< | DesiredSensorSettings::GAS_SENSOR_SEL; let profile_dur = dev.get_profile_dur(&sensor_settings)?; - info!("Duration {}", profile_dur); + info!("Duration {:?}", profile_dur); info!("Setting sensor settings"); dev.set_sensor_settings(settings_sel, &sensor_settings)?; info!("Setting forced power modes"); @@ -54,11 +54,10 @@ fn main() -> result::Result< info!("Setting forced power modes"); dev.set_sensor_mode(PowerMode::ForcedMode)?; info!("Retrieving sensor data"); - let (data, state) = dev.get_sensor_data()?; + let (data, _state) = dev.get_sensor_data()?; info!("Sensor Data {:?}", data); info!("Temperature {}°C", data.temperature_celsius()); info!("Pressure {}hPa", data.pressure_hpa()); info!("Humidity {}%", data.humidity_percent()); } - Ok(()) } diff --git a/src/calc.rs b/src/calc.rs index 44c1720..319385c 100644 --- a/src/calc.rs +++ b/src/calc.rs @@ -1,17 +1,17 @@ use CalibData; +use std::time::Duration; pub struct Calc {} impl Calc { - pub fn calc_heater_res(calib: &CalibData, amb_temp: i8, temp: u16) -> u8 { // cap temperature let temp = if temp <= 400 { temp } else { 400 }; let var1 = amb_temp as (i32) * calib.par_gh3 as (i32) / 1000i32 * 256i32; let var2 = (calib.par_gh1 as (i32) + 784i32) - * (((calib.par_gh2 as (i32) + 154009i32) * temp as (i32) * 5i32 / 100i32 - + 3276800i32) / 10i32); + * (((calib.par_gh2 as (i32) + 154009i32) * temp as (i32) * 5i32 / 100i32 + 3276800i32) + / 10i32); let var3 = var1 + var2 / 2i32; let var4 = var3 / (calib.res_heat_range as (i32) + 4i32); let var5 = 131i32 * calib.res_heat_val as (i32) + 65536i32; @@ -19,22 +19,25 @@ impl Calc { ((heatr_res_x100 + 50i32) / 100i32) as (u8) } - pub fn calc_heater_dur(dur: u16) -> u8 { + pub fn calc_heater_dur(duration: Duration) -> u8 { let mut factor: u8 = 0u8; - let mut dur = dur; - let durval = - if dur as (i32) >= 0xfc0i32 { - 0xffu8 // Max duration - } else { - loop { - if !(dur as (i32) > 0x3fi32) { - break; - } - dur = (dur as (i32) / 4i32) as (u16); - factor = (factor as (i32) + 1i32) as (u8); - } - (dur as (i32) + factor as (i32) * 64i32) as (u8) - }; + // TODO replace once https://github.com/rust-lang/rust/pull/50167 has been merged + const MILLIS_PER_SEC: u64 = 1_000; + const NANOS_PER_MILLI: u64 = 1_000_000; + let mut dur = (duration.as_secs() as u64 * MILLIS_PER_SEC) + + (duration.subsec_nanos() as u64 / NANOS_PER_MILLI); + let durval = if dur as (i32) >= 0xfc0i32 { + 0xffu8 // Max duration + } else { + loop { + if !(dur as (i32) > 0x3fi32) { + break; + } + dur = (dur as (i32) / 4i32) as (u64); + factor = (factor as (i32) + 1i32) as (u8); + } + (dur as (i32) + factor as (i32) * 64i32) as (u8) + }; durval } @@ -65,8 +68,8 @@ impl Calc { } else { pressure_comp = ((pressure_comp << 1i32) as (u32)).wrapping_div(var1 as (u32)) as (i32); } - var1 = calib.par_p9 as (i32) - * ((pressure_comp >> 3i32) * (pressure_comp >> 3i32) >> 13i32) >> 12i32; + var1 = calib.par_p9 as (i32) * ((pressure_comp >> 3i32) * (pressure_comp >> 3i32) >> 13i32) + >> 12i32; var2 = (pressure_comp >> 2i32) * calib.par_p8 as (i32) >> 13i32; let var3: i32 = (pressure_comp >> 8i32) * (pressure_comp >> 8i32) * (pressure_comp >> 8i32) * calib.par_p10 as (i32) >> 17i32; @@ -81,8 +84,8 @@ impl Calc { - (temp_scaled * calib.par_h3 as (i32) / 100i32 >> 1i32); let var2: i32 = calib.par_h2 as (i32) * (temp_scaled * calib.par_h4 as (i32) / 100i32 - + (temp_scaled * (temp_scaled * calib.par_h5 as (i32) / 100i32) >> 6i32) - / 100i32 + (1i32 << 14i32)) >> 10i32; + + (temp_scaled * (temp_scaled * calib.par_h5 as (i32) / 100i32) >> 6i32) / 100i32 + + (1i32 << 14i32)) >> 10i32; let var3: i32 = var1 * var2; let var4: i32 = calib.par_h6 as (i32) << 7i32; let var4: i32 = var4 + temp_scaled * calib.par_h7 as (i32) / 100i32 >> 4i32; @@ -134,8 +137,8 @@ impl Calc { 250000u32, 125000u32, ]; - let var1: i64 = (1340 + 5 * calib.range_sw_err as i64) - * lookup_table1[gas_range as usize] as i64 >> 16; + let var1: i64 = + (1340 + 5 * calib.range_sw_err as i64) * lookup_table1[gas_range as usize] as i64 >> 16; let var2: u64 = (((gas_res_adc as i64) << 15) - 16777216 + var1) as (u64); 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); diff --git a/src/lib.rs b/src/lib.rs index 6c694f9..d5da638 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -10,6 +10,7 @@ use calc::Calc; use hal::blocking::delay::DelayMs; use hal::blocking::i2c::{Read, Write}; use std::result; +use std::time::Duration; /** BME680 General config */ pub const BME680_POLL_PERIOD_MS: u8 = 10; @@ -262,7 +263,7 @@ pub struct GasSett { pub heatr_ctrl: Option, pub run_gas: Option, pub heatr_temp: Option, - pub heatr_dur: Option, + pub heatr_dur: Option, } impl Clone for GasSett { @@ -747,33 +748,39 @@ where Ok(PowerMode::from(mode)) } - pub fn bme680_set_profile_dur(&mut self, tph_sett: TphSett, duration: u16) { + pub fn bme680_set_profile_dur(&mut self, tph_sett: TphSett, duration: Duration) { let os_to_meas_cycles: [u8; 6] = [0u8, 1u8, 2u8, 4u8, 8u8, 16u8]; // TODO check if the following unwrap_ors do not change behaviour + // TODO replace once https://github.com/rust-lang/rust/pull/50167 has been merged + const MILLIS_PER_SEC: u64 = 1_000; + const NANOS_PER_MILLI: u64 = 1_000_000; + let millis = (duration.as_secs() as u64 * MILLIS_PER_SEC) + + (duration.subsec_nanos() as u64 / NANOS_PER_MILLI); + let mut meas_cycles = os_to_meas_cycles [tph_sett.os_temp.unwrap_or(OversamplingSetting::OSNone) as (usize)] - as (u32); + as (u64); meas_cycles = meas_cycles.wrapping_add( os_to_meas_cycles[tph_sett.os_pres.unwrap_or(OversamplingSetting::OSNone) as (usize)] - as (u32), + as (u64), ); meas_cycles = meas_cycles.wrapping_add( os_to_meas_cycles[tph_sett.os_hum.unwrap_or(OversamplingSetting::OSNone) as (usize)] - as (u32), + as (u64), ); - let mut tph_dur = meas_cycles.wrapping_mul(1963u32); - tph_dur = tph_dur.wrapping_add(477u32.wrapping_mul(4u32)); - tph_dur = tph_dur.wrapping_add(477u32.wrapping_mul(5u32)); - tph_dur = tph_dur.wrapping_add(500u32); - tph_dur = tph_dur.wrapping_div(1000u32); - tph_dur = tph_dur.wrapping_add(1u32); - self.gas_sett.heatr_dur = Some((duration as (i32) - tph_dur as (u16) as (i32)) as (u16)); + let mut tph_dur = meas_cycles.wrapping_mul(1963u64); + tph_dur = tph_dur.wrapping_add(477u64.wrapping_mul(4u64)); + tph_dur = tph_dur.wrapping_add(477u64.wrapping_mul(5u64)); + tph_dur = tph_dur.wrapping_add(500u64); + tph_dur = tph_dur.wrapping_div(1000u64); + tph_dur = tph_dur.wrapping_add(1u64); + self.gas_sett.heatr_dur = Some(Duration::from_millis(millis - tph_dur)); } pub fn get_profile_dur( &self, sensor_settings: &SensorSettings, - ) -> Result::Error, ::Error> { + ) -> Result::Error, ::Error> { let os_to_meas_cycles: [u8; 6] = [0u8, 1u8, 2u8, 4u8, 8u8, 16u8]; // TODO check if the following unwrap_ors do not change behaviour let mut meas_cycles = os_to_meas_cycles[sensor_settings @@ -802,7 +809,7 @@ where tph_dur = tph_dur.wrapping_add(500u32); tph_dur = tph_dur.wrapping_div(1000u32); tph_dur = tph_dur.wrapping_add(1u32); - let mut duration = tph_dur as (u16); + let mut duration = Duration::from_millis(tph_dur as u64); if sensor_settings.gas_sett.run_gas.unwrap_or(0) != 0 { duration = duration + sensor_settings.gas_sett.heatr_dur.expect("Heatrdur"); } @@ -903,7 +910,7 @@ where ), ( BME680_GAS_WAIT0_ADDR, - Calc::calc_heater_dur(gas_sett.heatr_dur.unwrap_or(0)), + Calc::calc_heater_dur(gas_sett.heatr_dur.unwrap_or(Duration::from_secs(0))), ), ]; @@ -914,15 +921,17 @@ where fn get_gas_config(&mut self) -> Result::Error, ::Error> { // TODO move both GasSett fields to new struct let mut gas_sett: GasSett = Default::default(); + // TODO figure out if heat_temp and dur can be u8 gas_sett.heatr_temp = Some( I2CUtil::read_byte(&mut self.i2c, self.dev_id, BME680_ADDR_SENS_CONF_START)? as u16, ); - gas_sett.heatr_dur = - Some( - I2CUtil::read_byte(&mut self.i2c, self.dev_id, BME680_ADDR_GAS_CONF_START)? as u16, - ); + + let heatr_dur_ms = + I2CUtil::read_byte(&mut self.i2c, self.dev_id, BME680_ADDR_GAS_CONF_START)? as u64; + gas_sett.heatr_dur = Some(Duration::from_millis(heatr_dur_ms)); + Ok(gas_sett) }