Replace heat_dur u32 with Duration

This commit is contained in:
marcelbuesing 2018-05-24 22:02:23 +02:00
parent a8a7426888
commit d1fe4a972a
No known key found for this signature in database
GPG key ID: EF3934305E975944
3 changed files with 58 additions and 47 deletions

View file

@ -30,7 +30,7 @@ fn main() -> result::Result<
sensor_settings.tph_sett.filter = Some(2); sensor_settings.tph_sett.filter = Some(2);
sensor_settings.gas_sett.run_gas = Some(0x01); 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); sensor_settings.gas_sett.heatr_temp = Some(320);
let settings_sel = DesiredSensorSettings::OST_SEL | DesiredSensorSettings::OSP_SEL let settings_sel = DesiredSensorSettings::OST_SEL | DesiredSensorSettings::OSP_SEL
@ -38,7 +38,7 @@ fn main() -> result::Result<
| DesiredSensorSettings::GAS_SENSOR_SEL; | DesiredSensorSettings::GAS_SENSOR_SEL;
let profile_dur = dev.get_profile_dur(&sensor_settings)?; let profile_dur = dev.get_profile_dur(&sensor_settings)?;
info!("Duration {}", profile_dur); info!("Duration {:?}", profile_dur);
info!("Setting sensor settings"); info!("Setting sensor settings");
dev.set_sensor_settings(settings_sel, &sensor_settings)?; dev.set_sensor_settings(settings_sel, &sensor_settings)?;
info!("Setting forced power modes"); info!("Setting forced power modes");
@ -54,11 +54,10 @@ fn main() -> result::Result<
info!("Setting forced power modes"); info!("Setting forced power modes");
dev.set_sensor_mode(PowerMode::ForcedMode)?; dev.set_sensor_mode(PowerMode::ForcedMode)?;
info!("Retrieving sensor data"); info!("Retrieving sensor data");
let (data, state) = dev.get_sensor_data()?; let (data, _state) = dev.get_sensor_data()?;
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());
info!("Humidity {}%", data.humidity_percent()); info!("Humidity {}%", data.humidity_percent());
} }
Ok(())
} }

View file

@ -1,17 +1,17 @@
use CalibData; use CalibData;
use std::time::Duration;
pub struct Calc {} pub struct Calc {}
impl Calc { impl Calc {
pub fn calc_heater_res(calib: &CalibData, amb_temp: i8, temp: u16) -> u8 { pub fn calc_heater_res(calib: &CalibData, amb_temp: i8, temp: u16) -> u8 {
// cap temperature // cap temperature
let temp = if temp <= 400 { temp } else { 400 }; let temp = if temp <= 400 { temp } else { 400 };
let var1 = amb_temp as (i32) * calib.par_gh3 as (i32) / 1000i32 * 256i32; let var1 = amb_temp as (i32) * calib.par_gh3 as (i32) / 1000i32 * 256i32;
let var2 = (calib.par_gh1 as (i32) + 784i32) let var2 = (calib.par_gh1 as (i32) + 784i32)
* (((calib.par_gh2 as (i32) + 154009i32) * temp as (i32) * 5i32 / 100i32 * (((calib.par_gh2 as (i32) + 154009i32) * temp as (i32) * 5i32 / 100i32 + 3276800i32)
+ 3276800i32) / 10i32); / 10i32);
let var3 = var1 + var2 / 2i32; let var3 = var1 + var2 / 2i32;
let var4 = var3 / (calib.res_heat_range as (i32) + 4i32); let var4 = var3 / (calib.res_heat_range as (i32) + 4i32);
let var5 = 131i32 * calib.res_heat_val as (i32) + 65536i32; let var5 = 131i32 * calib.res_heat_val as (i32) + 65536i32;
@ -19,22 +19,25 @@ impl Calc {
((heatr_res_x100 + 50i32) / 100i32) as (u8) ((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 factor: u8 = 0u8;
let mut dur = dur; // TODO replace once https://github.com/rust-lang/rust/pull/50167 has been merged
let durval = const MILLIS_PER_SEC: u64 = 1_000;
if dur as (i32) >= 0xfc0i32 { const NANOS_PER_MILLI: u64 = 1_000_000;
0xffu8 // Max duration let mut dur = (duration.as_secs() as u64 * MILLIS_PER_SEC)
} else { + (duration.subsec_nanos() as u64 / NANOS_PER_MILLI);
loop { let durval = if dur as (i32) >= 0xfc0i32 {
if !(dur as (i32) > 0x3fi32) { 0xffu8 // Max duration
break; } else {
} loop {
dur = (dur as (i32) / 4i32) as (u16); if !(dur as (i32) > 0x3fi32) {
factor = (factor as (i32) + 1i32) as (u8); break;
} }
(dur as (i32) + factor as (i32) * 64i32) as (u8) dur = (dur as (i32) / 4i32) as (u64);
}; factor = (factor as (i32) + 1i32) as (u8);
}
(dur as (i32) + factor as (i32) * 64i32) as (u8)
};
durval durval
} }
@ -65,8 +68,8 @@ impl Calc {
} else { } else {
pressure_comp = ((pressure_comp << 1i32) as (u32)).wrapping_div(var1 as (u32)) as (i32); pressure_comp = ((pressure_comp << 1i32) as (u32)).wrapping_div(var1 as (u32)) as (i32);
} }
var1 = calib.par_p9 as (i32) var1 = calib.par_p9 as (i32) * ((pressure_comp >> 3i32) * (pressure_comp >> 3i32) >> 13i32)
* ((pressure_comp >> 3i32) * (pressure_comp >> 3i32) >> 13i32) >> 12i32; >> 12i32;
var2 = (pressure_comp >> 2i32) * calib.par_p8 as (i32) >> 13i32; var2 = (pressure_comp >> 2i32) * calib.par_p8 as (i32) >> 13i32;
let var3: i32 = (pressure_comp >> 8i32) * (pressure_comp >> 8i32) * (pressure_comp >> 8i32) let var3: i32 = (pressure_comp >> 8i32) * (pressure_comp >> 8i32) * (pressure_comp >> 8i32)
* calib.par_p10 as (i32) >> 17i32; * calib.par_p10 as (i32) >> 17i32;
@ -81,8 +84,8 @@ impl Calc {
- (temp_scaled * calib.par_h3 as (i32) / 100i32 >> 1i32); - (temp_scaled * calib.par_h3 as (i32) / 100i32 >> 1i32);
let var2: i32 = calib.par_h2 as (i32) let var2: i32 = calib.par_h2 as (i32)
* (temp_scaled * calib.par_h4 as (i32) / 100i32 * (temp_scaled * calib.par_h4 as (i32) / 100i32
+ (temp_scaled * (temp_scaled * calib.par_h5 as (i32) / 100i32) >> 6i32) + (temp_scaled * (temp_scaled * calib.par_h5 as (i32) / 100i32) >> 6i32) / 100i32
/ 100i32 + (1i32 << 14i32)) >> 10i32; + (1i32 << 14i32)) >> 10i32;
let var3: i32 = var1 * var2; let var3: i32 = var1 * var2;
let var4: i32 = calib.par_h6 as (i32) << 7i32; let var4: i32 = calib.par_h6 as (i32) << 7i32;
let var4: i32 = var4 + temp_scaled * calib.par_h7 as (i32) / 100i32 >> 4i32; let var4: i32 = var4 + temp_scaled * calib.par_h7 as (i32) / 100i32 >> 4i32;
@ -134,8 +137,8 @@ impl Calc {
250000u32, 250000u32,
125000u32, 125000u32,
]; ];
let var1: i64 = (1340 + 5 * calib.range_sw_err as i64) let var1: i64 =
* lookup_table1[gas_range as usize] as i64 >> 16; (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 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 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);

View file

@ -10,6 +10,7 @@ use calc::Calc;
use hal::blocking::delay::DelayMs; use hal::blocking::delay::DelayMs;
use hal::blocking::i2c::{Read, Write}; use hal::blocking::i2c::{Read, Write};
use std::result; use std::result;
use std::time::Duration;
/** BME680 General config */ /** BME680 General config */
pub const BME680_POLL_PERIOD_MS: u8 = 10; pub const BME680_POLL_PERIOD_MS: u8 = 10;
@ -262,7 +263,7 @@ pub struct GasSett {
pub heatr_ctrl: Option<u8>, pub heatr_ctrl: Option<u8>,
pub run_gas: Option<u8>, pub run_gas: Option<u8>,
pub heatr_temp: Option<u16>, pub heatr_temp: Option<u16>,
pub heatr_dur: Option<u16>, pub heatr_dur: Option<Duration>,
} }
impl Clone for GasSett { impl Clone for GasSett {
@ -747,33 +748,39 @@ where
Ok(PowerMode::from(mode)) 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]; 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 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 let mut meas_cycles = os_to_meas_cycles
[tph_sett.os_temp.unwrap_or(OversamplingSetting::OSNone) as (usize)] [tph_sett.os_temp.unwrap_or(OversamplingSetting::OSNone) as (usize)]
as (u32); as (u64);
meas_cycles = meas_cycles.wrapping_add( meas_cycles = meas_cycles.wrapping_add(
os_to_meas_cycles[tph_sett.os_pres.unwrap_or(OversamplingSetting::OSNone) as (usize)] os_to_meas_cycles[tph_sett.os_pres.unwrap_or(OversamplingSetting::OSNone) as (usize)]
as (u32), as (u64),
); );
meas_cycles = meas_cycles.wrapping_add( meas_cycles = meas_cycles.wrapping_add(
os_to_meas_cycles[tph_sett.os_hum.unwrap_or(OversamplingSetting::OSNone) as (usize)] 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); let mut tph_dur = meas_cycles.wrapping_mul(1963u64);
tph_dur = tph_dur.wrapping_add(477u32.wrapping_mul(4u32)); tph_dur = tph_dur.wrapping_add(477u64.wrapping_mul(4u64));
tph_dur = tph_dur.wrapping_add(477u32.wrapping_mul(5u32)); tph_dur = tph_dur.wrapping_add(477u64.wrapping_mul(5u64));
tph_dur = tph_dur.wrapping_add(500u32); tph_dur = tph_dur.wrapping_add(500u64);
tph_dur = tph_dur.wrapping_div(1000u32); tph_dur = tph_dur.wrapping_div(1000u64);
tph_dur = tph_dur.wrapping_add(1u32); tph_dur = tph_dur.wrapping_add(1u64);
self.gas_sett.heatr_dur = Some((duration as (i32) - tph_dur as (u16) as (i32)) as (u16)); self.gas_sett.heatr_dur = Some(Duration::from_millis(millis - tph_dur));
} }
pub fn get_profile_dur( pub fn get_profile_dur(
&self, &self,
sensor_settings: &SensorSettings, sensor_settings: &SensorSettings,
) -> Result<u16, <I2C as Read>::Error, <I2C as Write>::Error> { ) -> Result<Duration, <I2C as Read>::Error, <I2C as Write>::Error> {
let os_to_meas_cycles: [u8; 6] = [0u8, 1u8, 2u8, 4u8, 8u8, 16u8]; 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 check if the following unwrap_ors do not change behaviour
let mut meas_cycles = os_to_meas_cycles[sensor_settings 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_add(500u32);
tph_dur = tph_dur.wrapping_div(1000u32); tph_dur = tph_dur.wrapping_div(1000u32);
tph_dur = tph_dur.wrapping_add(1u32); 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 { if sensor_settings.gas_sett.run_gas.unwrap_or(0) != 0 {
duration = duration + sensor_settings.gas_sett.heatr_dur.expect("Heatrdur"); duration = duration + sensor_settings.gas_sett.heatr_dur.expect("Heatrdur");
} }
@ -903,7 +910,7 @@ where
), ),
( (
BME680_GAS_WAIT0_ADDR, 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<GasSett, <I2C as Read>::Error, <I2C as Write>::Error> { fn get_gas_config(&mut self) -> Result<GasSett, <I2C as Read>::Error, <I2C as Write>::Error> {
// TODO move both GasSett fields to new struct // TODO move both GasSett fields to new struct
let mut gas_sett: GasSett = Default::default(); let mut gas_sett: GasSett = Default::default();
// TODO figure out if heat_temp and dur can be u8 // TODO figure out if heat_temp and dur can be u8
gas_sett.heatr_temp = gas_sett.heatr_temp =
Some( Some(
I2CUtil::read_byte(&mut self.i2c, self.dev_id, BME680_ADDR_SENS_CONF_START)? as u16, I2CUtil::read_byte(&mut self.i2c, self.dev_id, BME680_ADDR_SENS_CONF_START)? as u16,
); );
gas_sett.heatr_dur =
Some( let heatr_dur_ms =
I2CUtil::read_byte(&mut self.i2c, self.dev_id, BME680_ADDR_GAS_CONF_START)? as u16, 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) Ok(gas_sett)
} }