2017-10-16 15:47:44 +02:00
|
|
|
from .constants import *
|
2017-10-15 12:29:51 +02:00
|
|
|
import math
|
2017-10-16 15:47:44 +02:00
|
|
|
import time
|
2017-10-15 12:29:51 +02:00
|
|
|
|
2017-12-04 11:37:52 +01:00
|
|
|
__version__ = '1.0.4'
|
2017-10-17 13:50:26 +02:00
|
|
|
|
2017-10-16 15:47:44 +02:00
|
|
|
class BME680(BME680Data):
|
2017-10-17 13:28:06 +02:00
|
|
|
"""BOSCH BME680
|
|
|
|
|
|
|
|
Gas, pressure, temperature and humidity sensor.
|
|
|
|
|
|
|
|
:param i2c_addr: One of I2C_ADDR_PRIMARY (0x76) or I2C_ADDR_SECONDARY (0x77)
|
|
|
|
:param i2c_device: Optional smbus or compatible instance for facilitating i2c communications.
|
|
|
|
|
|
|
|
"""
|
2017-10-16 15:47:44 +02:00
|
|
|
def __init__(self, i2c_addr=I2C_ADDR_PRIMARY, i2c_device=None):
|
|
|
|
BME680Data.__init__(self)
|
2017-10-15 12:29:51 +02:00
|
|
|
|
2017-10-16 15:47:44 +02:00
|
|
|
self.i2c_addr = i2c_addr
|
|
|
|
self._i2c = i2c_device
|
|
|
|
if self._i2c is None:
|
2017-10-17 13:28:06 +02:00
|
|
|
import smbus
|
2017-10-16 15:47:44 +02:00
|
|
|
self._i2c = smbus.SMBus(1)
|
2017-10-15 12:29:51 +02:00
|
|
|
|
2017-10-16 15:47:44 +02:00
|
|
|
self.chip_id = self._get_regs(CHIP_ID_ADDR, 1)
|
|
|
|
if self.chip_id != CHIP_ID:
|
|
|
|
raise RuntimeError("BME680 Not Found. Invalid CHIP ID: 0x{0:02x}".format(self.chip_id))
|
2017-10-15 12:29:51 +02:00
|
|
|
|
2017-10-16 15:47:44 +02:00
|
|
|
self.soft_reset()
|
|
|
|
self.set_power_mode(SLEEP_MODE)
|
2017-10-15 12:29:51 +02:00
|
|
|
|
2017-10-16 15:47:44 +02:00
|
|
|
self._get_calibration_data()
|
|
|
|
|
|
|
|
self.set_humidity_oversample(OS_2X)
|
|
|
|
self.set_pressure_oversample(OS_4X)
|
|
|
|
self.set_temperature_oversample(OS_8X)
|
|
|
|
self.set_filter(FILTER_SIZE_3)
|
|
|
|
self.set_gas_status(ENABLE_GAS_MEAS)
|
2018-05-28 23:18:20 +02:00
|
|
|
self.set_temp_offset(0)
|
2017-10-16 15:47:44 +02:00
|
|
|
self.get_sensor_data()
|
|
|
|
|
2017-10-17 12:23:41 +02:00
|
|
|
def _get_calibration_data(self):
|
|
|
|
"""Retrieves the sensor calibration data and stores it in .calibration_data"""
|
|
|
|
calibration = self._get_regs(COEFF_ADDR1, COEFF_ADDR1_LEN)
|
|
|
|
calibration += self._get_regs(COEFF_ADDR2, COEFF_ADDR2_LEN)
|
|
|
|
|
|
|
|
heat_range = self._get_regs(ADDR_RES_HEAT_RANGE_ADDR, 1)
|
|
|
|
heat_value = twos_comp(self._get_regs(ADDR_RES_HEAT_VAL_ADDR, 1), bits=8)
|
|
|
|
sw_error = twos_comp(self._get_regs(ADDR_RANGE_SW_ERR_ADDR, 1), bits=8)
|
|
|
|
|
|
|
|
self.calibration_data.set_from_array(calibration)
|
|
|
|
self.calibration_data.set_other(heat_range, heat_value, sw_error)
|
|
|
|
|
2017-10-16 15:47:44 +02:00
|
|
|
def soft_reset(self):
|
2017-10-17 12:23:41 +02:00
|
|
|
"""Initiate a soft reset"""
|
2017-10-16 15:47:44 +02:00
|
|
|
self._set_regs(SOFT_RESET_ADDR, SOFT_RESET_CMD)
|
|
|
|
time.sleep(RESET_PERIOD / 1000.0)
|
|
|
|
|
2018-05-28 23:18:20 +02:00
|
|
|
def set_temp_offset(self, value):
|
|
|
|
"""Set temperature offset in celsius
|
|
|
|
|
|
|
|
If set, the temperature t_fine will be increased by given value in celsius.
|
2018-05-31 10:21:14 +02:00
|
|
|
:param value: Temperature offset in Celsius, eg. 4, -8, 1.25
|
2018-05-28 23:18:20 +02:00
|
|
|
"""
|
|
|
|
if value == 0:
|
|
|
|
self.offset_temp_in_t_fine = 0
|
|
|
|
elif value < 0:
|
2018-05-31 10:21:14 +02:00
|
|
|
self.offset_temp_in_t_fine = int(math.copysign((((int(abs(value) * 100)) << 8) - 128) / 5, value))
|
2018-05-28 23:18:20 +02:00
|
|
|
|
2017-10-16 15:47:44 +02:00
|
|
|
def set_humidity_oversample(self, value):
|
2017-10-17 13:28:06 +02:00
|
|
|
"""Set humidity oversampling
|
|
|
|
|
|
|
|
A higher oversampling value means more stable sensor readings,
|
|
|
|
with less noise and jitter.
|
|
|
|
|
|
|
|
However each step of oversampling adds about 2ms to the latency,
|
|
|
|
causing a slower response time to fast transients.
|
|
|
|
|
|
|
|
:param value: Oversampling value, one of: OS_NONE, OS_1X, OS_2X, OS_4X, OS_8X, OS_16X
|
|
|
|
|
|
|
|
"""
|
2017-10-16 15:47:44 +02:00
|
|
|
self.tph_settings.os_hum = value
|
2017-10-17 12:23:41 +02:00
|
|
|
self._set_bits(CONF_OS_H_ADDR, OSH_MSK, OSH_POS, value)
|
|
|
|
|
|
|
|
def get_humidity_oversample(self):
|
|
|
|
"""Get humidity oversampling"""
|
|
|
|
return (self._get_regs(CONF_OS_H_ADDR, 1) & OSH_MSK) >> OSH_POS
|
2017-10-16 15:47:44 +02:00
|
|
|
|
|
|
|
def set_pressure_oversample(self, value):
|
2017-10-17 13:28:06 +02:00
|
|
|
"""Set temperature oversampling
|
|
|
|
|
|
|
|
A higher oversampling value means more stable sensor readings,
|
|
|
|
with less noise and jitter.
|
|
|
|
|
|
|
|
However each step of oversampling adds about 2ms to the latency,
|
|
|
|
causing a slower response time to fast transients.
|
|
|
|
|
|
|
|
:param value: Oversampling value, one of: OS_NONE, OS_1X, OS_2X, OS_4X, OS_8X, OS_16X
|
|
|
|
|
|
|
|
"""
|
2017-10-16 15:47:44 +02:00
|
|
|
self.tph_settings.os_pres = value
|
2017-10-17 12:23:41 +02:00
|
|
|
self._set_bits(CONF_T_P_MODE_ADDR, OSP_MSK, OSP_POS, value)
|
|
|
|
|
|
|
|
def get_pressure_oversample(self):
|
|
|
|
"""Get pressure oversampling"""
|
|
|
|
return (self._get_regs(CONF_T_P_MODE_ADDR, 1) & OSP_MSK) >> OSP_POS
|
2017-10-16 15:47:44 +02:00
|
|
|
|
|
|
|
def set_temperature_oversample(self, value):
|
2017-10-17 13:28:06 +02:00
|
|
|
"""Set pressure oversampling
|
|
|
|
|
|
|
|
A higher oversampling value means more stable sensor readings,
|
|
|
|
with less noise and jitter.
|
|
|
|
|
|
|
|
However each step of oversampling adds about 2ms to the latency,
|
|
|
|
causing a slower response time to fast transients.
|
|
|
|
|
|
|
|
:param value: Oversampling value, one of: OS_NONE, OS_1X, OS_2X, OS_4X, OS_8X, OS_16X
|
|
|
|
|
|
|
|
"""
|
2017-10-16 15:47:44 +02:00
|
|
|
self.tph_settings.os_temp = value
|
2017-10-17 12:23:41 +02:00
|
|
|
self._set_bits(CONF_T_P_MODE_ADDR, OST_MSK, OST_POS, value)
|
|
|
|
|
|
|
|
def get_temperature_oversample(self):
|
|
|
|
"""Get temperature oversampling"""
|
|
|
|
return (self._get_regs(CONF_T_P_MODE_ADDR, 1) & OST_MSK) >> OST_POS
|
2017-10-16 15:47:44 +02:00
|
|
|
|
|
|
|
def set_filter(self, value):
|
2017-10-17 13:28:06 +02:00
|
|
|
"""Set IIR filter size
|
|
|
|
|
|
|
|
Optionally remove short term fluctuations from the temperature and pressure readings,
|
|
|
|
increasing their resolution but reducing their bandwidth.
|
|
|
|
|
|
|
|
Enabling the IIR filter does not slow down the time a reading takes, but will slow
|
|
|
|
down the BME680s response to changes in temperature and pressure.
|
|
|
|
|
|
|
|
When the IIR filter is enabled, the temperature and pressure resolution is effectively 20bit.
|
|
|
|
When it is disabled, it is 16bit + oversampling-1 bits.
|
|
|
|
|
|
|
|
"""
|
2017-10-16 15:47:44 +02:00
|
|
|
self.tph_settings.filter = value
|
2017-10-17 12:23:41 +02:00
|
|
|
self._set_bits(CONF_ODR_FILT_ADDR, FILTER_MSK, FILTER_POS, value)
|
|
|
|
|
|
|
|
def get_filter(self):
|
|
|
|
"""Get filter size"""
|
|
|
|
return (self._get_regs(CONF_ODR_FILT_ADDR, 1) & FILTER_MSK) >> FILTER_POS
|
2017-10-16 15:47:44 +02:00
|
|
|
|
2017-10-17 13:28:06 +02:00
|
|
|
def select_gas_heater_profile(self, value):
|
|
|
|
"""Set current gas sensor conversion profile: 0 to 9
|
|
|
|
|
|
|
|
Select one of the 10 configured heating durations/set points.
|
|
|
|
|
|
|
|
"""
|
|
|
|
if value > NBCONV_MAX or value < NBCONV_MIN:
|
|
|
|
raise ValueError("Profile '{}' should be between {} and {}".format(value, NBCONV_MIN, NBCONV_MAX))
|
|
|
|
|
|
|
|
self.gas_settings.nb_conv = value
|
|
|
|
self._set_bits(CONF_ODR_RUN_GAS_NBC_ADDR, NBCONV_MSK, NBCONV_POS, value)
|
|
|
|
|
|
|
|
def get_gas_heater_profile(self):
|
|
|
|
"""Get gas sensor conversion profile: 0 to 9"""
|
|
|
|
return self._get_regs(CONF_ODR_RUN_GAS_NBC_ADDR, 1) & NBCONV_MSK
|
|
|
|
|
2017-10-16 15:47:44 +02:00
|
|
|
def set_gas_status(self, value):
|
2017-10-17 12:23:41 +02:00
|
|
|
"""Enable/disable gas sensor"""
|
2017-10-16 15:47:44 +02:00
|
|
|
self.gas_settings.run_gas = value
|
2017-10-17 12:23:41 +02:00
|
|
|
self._set_bits(CONF_ODR_RUN_GAS_NBC_ADDR, RUN_GAS_MSK, RUN_GAS_POS, value)
|
|
|
|
|
|
|
|
def get_gas_status(self):
|
|
|
|
"""Get the current gas status"""
|
|
|
|
return (self._get_regs(CONF_ODR_RUN_GAS_NBC_ADDR, 1) & RUN_GAS_MSK) >> RUN_GAS_POS
|
2017-10-16 15:47:44 +02:00
|
|
|
|
2017-10-17 13:28:06 +02:00
|
|
|
def set_gas_heater_profile(self, temperature, duration, nb_profile=0):
|
|
|
|
"""Set temperature and duration of gas sensor heater
|
|
|
|
|
|
|
|
:param temperature: Target temperature in degrees celsius, between 200 and 400
|
|
|
|
:param durarion: Target duration in milliseconds, between 1 and 4032
|
|
|
|
:param nb_profile: Target profile, between 0 and 9
|
|
|
|
|
|
|
|
"""
|
|
|
|
self.set_gas_heater_temperature(temperature, nb_profile=nb_profile)
|
|
|
|
self.set_gas_heater_duration(duration, nb_profile=nb_profile)
|
|
|
|
|
|
|
|
def set_gas_heater_temperature(self, value, nb_profile=0):
|
|
|
|
"""Set gas sensor heater temperature
|
|
|
|
|
|
|
|
:param value: Target temperature in degrees celsius, between 200 and 400
|
|
|
|
|
|
|
|
When setting an nb_profile other than 0,
|
|
|
|
make sure to select it with select_gas_heater_profile.
|
|
|
|
|
|
|
|
"""
|
|
|
|
if nb_profile > NBCONV_MAX or value < NBCONV_MIN:
|
|
|
|
raise ValueError("Profile '{}' should be between {} and {}".format(nb_profile, NBCONV_MIN, NBCONV_MAX))
|
|
|
|
|
2017-10-16 15:47:44 +02:00
|
|
|
self.gas_settings.heatr_temp = value
|
2017-10-18 14:10:17 +02:00
|
|
|
temp = int(self._calc_heater_resistance(self.gas_settings.heatr_temp))
|
2017-10-17 13:28:06 +02:00
|
|
|
self._set_regs(RES_HEAT0_ADDR + nb_profile, temp)
|
|
|
|
|
|
|
|
def set_gas_heater_duration(self, value, nb_profile=0):
|
|
|
|
"""Set gas sensor heater duration
|
|
|
|
|
|
|
|
Heating durations between 1 ms and 4032 ms can be configured.
|
2017-10-17 13:29:06 +02:00
|
|
|
Approximately 20-30 ms are necessary for the heater to reach the intended target temperature.
|
|
|
|
|
2017-10-17 13:28:06 +02:00
|
|
|
:param value: Heating duration in milliseconds.
|
|
|
|
|
|
|
|
When setting an nb_profile other than 0,
|
|
|
|
make sure to select it with select_gas_heater_profile.
|
|
|
|
|
|
|
|
"""
|
|
|
|
if nb_profile > NBCONV_MAX or value < NBCONV_MIN:
|
|
|
|
raise ValueError("Profile '{}' should be between {} and {}".format(nb_profile, NBCONV_MIN, NBCONV_MAX))
|
2017-10-16 15:47:44 +02:00
|
|
|
|
|
|
|
self.gas_settings.heatr_dur = value
|
|
|
|
temp = self._calc_heater_duration(self.gas_settings.heatr_dur)
|
2017-10-17 13:28:06 +02:00
|
|
|
self._set_regs(GAS_WAIT0_ADDR + nb_profile, temp)
|
2017-10-16 15:47:44 +02:00
|
|
|
|
|
|
|
def set_power_mode(self, value, blocking=True):
|
2017-10-17 12:23:41 +02:00
|
|
|
"""Set power mode"""
|
2017-10-16 15:47:44 +02:00
|
|
|
if value not in (SLEEP_MODE, FORCED_MODE):
|
|
|
|
print("Power mode should be one of SLEEP_MODE or FORCED_MODE")
|
|
|
|
|
|
|
|
self.power_mode = value
|
|
|
|
|
2017-10-17 12:23:41 +02:00
|
|
|
self._set_bits(CONF_T_P_MODE_ADDR, MODE_MSK, MODE_POS, value)
|
2017-10-16 15:47:44 +02:00
|
|
|
|
|
|
|
while blocking and self.get_power_mode() != self.power_mode:
|
|
|
|
time.sleep(POLL_PERIOD_MS / 1000.0)
|
|
|
|
|
|
|
|
def get_power_mode(self):
|
2017-10-17 12:23:41 +02:00
|
|
|
"""Get power mode"""
|
2017-10-16 15:47:44 +02:00
|
|
|
self.power_mode = self._get_regs(CONF_T_P_MODE_ADDR, 1)
|
|
|
|
return self.power_mode
|
2017-10-15 12:29:51 +02:00
|
|
|
|
2017-10-16 15:47:44 +02:00
|
|
|
def get_sensor_data(self):
|
2017-10-17 12:23:41 +02:00
|
|
|
"""Get sensor data.
|
|
|
|
|
|
|
|
Stores data in .data and returns True upon success.
|
|
|
|
|
|
|
|
"""
|
2017-10-16 15:47:44 +02:00
|
|
|
self.set_power_mode(FORCED_MODE)
|
|
|
|
|
2017-10-17 13:28:06 +02:00
|
|
|
for attempt in range(10):
|
2017-10-17 13:32:55 +02:00
|
|
|
status = self._get_regs(FIELD0_ADDR, 1)
|
|
|
|
|
|
|
|
if (status & NEW_DATA_MSK) == 0:
|
|
|
|
time.sleep(POLL_PERIOD_MS / 1000.0)
|
|
|
|
continue
|
|
|
|
|
2017-10-16 15:47:44 +02:00
|
|
|
regs = self._get_regs(FIELD0_ADDR, FIELD_LENGTH)
|
|
|
|
|
|
|
|
self.data.status = regs[0] & NEW_DATA_MSK
|
2017-10-17 13:28:06 +02:00
|
|
|
# Contains the nb_profile used to obtain the current measurement
|
2017-10-16 15:47:44 +02:00
|
|
|
self.data.gas_index = regs[0] & GAS_INDEX_MSK
|
|
|
|
self.data.meas_index = regs[1]
|
|
|
|
|
|
|
|
adc_pres = (regs[2] << 12) | (regs[3] << 4) | (regs[4] >> 4)
|
|
|
|
adc_temp = (regs[5] << 12) | (regs[6] << 4) | (regs[7] >> 4)
|
|
|
|
adc_hum = (regs[8] << 8) | regs[9]
|
|
|
|
adc_gas_res = (regs[13] << 2) | (regs[14] >> 6)
|
|
|
|
gas_range = regs[14] & GAS_RANGE_MSK
|
|
|
|
|
|
|
|
self.data.status |= regs[14] & GASM_VALID_MSK
|
|
|
|
self.data.status |= regs[14] & HEAT_STAB_MSK
|
|
|
|
|
2017-10-17 11:47:31 +02:00
|
|
|
self.data.heat_stable = (self.data.status & HEAT_STAB_MSK) > 0
|
|
|
|
|
2017-10-17 13:32:55 +02:00
|
|
|
temperature = self._calc_temperature(adc_temp)
|
|
|
|
self.data.temperature = temperature / 100.0
|
|
|
|
self.ambient_temperature = temperature # Saved for heater calc
|
2017-10-17 11:55:05 +02:00
|
|
|
|
2017-10-17 13:45:28 +02:00
|
|
|
self.data.pressure = self._calc_pressure(adc_pres) / 100.0
|
2017-10-17 13:32:55 +02:00
|
|
|
self.data.humidity = self._calc_humidity(adc_hum) / 1000.0
|
|
|
|
self.data.gas_resistance = self._calc_gas_resistance(adc_gas_res, gas_range)
|
|
|
|
return True
|
2017-10-16 15:47:44 +02:00
|
|
|
|
|
|
|
return False
|
|
|
|
|
2017-10-17 12:23:41 +02:00
|
|
|
def _set_bits(self, register, mask, position, value):
|
|
|
|
"""Mask out and set one or more bits in a register"""
|
|
|
|
temp = self._get_regs(register, 1)
|
|
|
|
temp &= ~mask
|
|
|
|
temp |= value << position
|
|
|
|
self._set_regs(register, temp)
|
|
|
|
|
2017-10-16 15:47:44 +02:00
|
|
|
def _set_regs(self, register, value):
|
2017-10-17 12:23:41 +02:00
|
|
|
"""Set one or more registers"""
|
2017-10-16 15:47:44 +02:00
|
|
|
if isinstance(value, int):
|
|
|
|
self._i2c.write_byte_data(self.i2c_addr, register, value)
|
|
|
|
else:
|
|
|
|
self._i2c.write_i2c_block_data(self.i2c_addr, register, value)
|
|
|
|
|
|
|
|
def _get_regs(self, register, length):
|
2017-10-17 12:23:41 +02:00
|
|
|
"""Get one or more registers"""
|
2017-10-16 15:47:44 +02:00
|
|
|
if length == 1:
|
|
|
|
return self._i2c.read_byte_data(self.i2c_addr, register)
|
|
|
|
else:
|
|
|
|
return self._i2c.read_i2c_block_data(self.i2c_addr, register, length)
|
2017-10-15 12:29:51 +02:00
|
|
|
|
|
|
|
def _calc_temperature(self, temperature_adc):
|
2017-11-17 12:29:48 +01:00
|
|
|
var1 = (temperature_adc >> 3) - (self.calibration_data.par_t1 << 1)
|
|
|
|
var2 = (var1 * self.calibration_data.par_t2) >> 11
|
|
|
|
var3 = ((var1 >> 1) * (var1 >> 1)) >> 12
|
|
|
|
var3 = ((var3) * (self.calibration_data.par_t3 << 4)) >> 14
|
2017-10-15 12:29:51 +02:00
|
|
|
|
|
|
|
# Save teperature data for pressure calculations
|
2018-05-28 23:18:20 +02:00
|
|
|
self.calibration_data.t_fine = (var2 + var3) + self.offset_temp_in_t_fine
|
2017-11-17 12:29:48 +01:00
|
|
|
calc_temp = (((self.calibration_data.t_fine * 5) + 128) >> 8)
|
2017-10-15 12:29:51 +02:00
|
|
|
|
|
|
|
return calc_temp
|
|
|
|
|
|
|
|
def _calc_pressure(self, pressure_adc):
|
2017-11-17 12:29:48 +01:00
|
|
|
var1 = ((self.calibration_data.t_fine) >> 1) - 64000
|
|
|
|
var2 = ((((var1 >> 2) * (var1 >> 2)) >> 11) *
|
|
|
|
self.calibration_data.par_p6) >> 2
|
|
|
|
var2 = var2 + ((var1 * self.calibration_data.par_p5) << 1)
|
|
|
|
var2 = (var2 >> 2) + (self.calibration_data.par_p4 << 16)
|
2017-11-21 22:16:27 +01:00
|
|
|
var1 = (((((var1 >> 2) * (var1 >> 2)) >> 13 ) *
|
|
|
|
((self.calibration_data.par_p3 << 5)) >> 3) +
|
|
|
|
((self.calibration_data.par_p2 * var1) >> 1))
|
2017-11-17 12:29:48 +01:00
|
|
|
var1 = var1 >> 18
|
|
|
|
|
|
|
|
var1 = ((32768 + var1) * self.calibration_data.par_p1) >> 15
|
|
|
|
calc_pressure = 1048576 - pressure_adc
|
|
|
|
calc_pressure = ((calc_pressure - (var2 >> 12)) * (3125))
|
|
|
|
|
|
|
|
if calc_pressure >= (1 << 31):
|
2017-11-19 18:10:27 +01:00
|
|
|
calc_pressure = ((calc_pressure // var1) << 1)
|
2017-11-17 12:29:48 +01:00
|
|
|
else:
|
2017-11-19 18:10:27 +01:00
|
|
|
calc_pressure = ((calc_pressure << 1) // var1)
|
2017-11-17 12:29:48 +01:00
|
|
|
|
|
|
|
var1 = (self.calibration_data.par_p9 * (((calc_pressure >> 3) *
|
|
|
|
(calc_pressure >> 3)) >> 13)) >> 12
|
|
|
|
var2 = ((calc_pressure >> 2) *
|
|
|
|
self.calibration_data.par_p8) >> 13
|
|
|
|
var3 = ((calc_pressure >> 8) * (calc_pressure >> 8) *
|
|
|
|
(calc_pressure >> 8) *
|
|
|
|
self.calibration_data.par_p10) >> 17
|
|
|
|
|
|
|
|
calc_pressure = (calc_pressure) + ((var1 + var2 + var3 +
|
|
|
|
(self.calibration_data.par_p7 << 7)) >> 4)
|
|
|
|
|
|
|
|
return calc_pressure
|
2017-10-15 12:29:51 +02:00
|
|
|
|
|
|
|
def _calc_humidity(self, humidity_adc):
|
2017-11-17 12:29:48 +01:00
|
|
|
temp_scaled = ((self.calibration_data.t_fine * 5) + 128) >> 8
|
2017-10-15 12:29:51 +02:00
|
|
|
var1 = (humidity_adc - ((self.calibration_data.par_h1 * 16))) \
|
2017-11-19 18:10:27 +01:00
|
|
|
- (((temp_scaled * self.calibration_data.par_h3) // (100)) >> 1)
|
2017-10-15 12:29:51 +02:00
|
|
|
var2 = (self.calibration_data.par_h2
|
2017-11-19 18:10:27 +01:00
|
|
|
* (((temp_scaled * self.calibration_data.par_h4) // (100))
|
|
|
|
+ (((temp_scaled * ((temp_scaled * self.calibration_data.par_h5) // (100))) >> 6)
|
|
|
|
// (100)) + (1 * 16384))) >> 10
|
2017-10-15 12:29:51 +02:00
|
|
|
var3 = var1 * var2
|
2017-11-17 12:29:48 +01:00
|
|
|
var4 = self.calibration_data.par_h6 << 7
|
2017-11-19 18:10:27 +01:00
|
|
|
var4 = ((var4) + ((temp_scaled * self.calibration_data.par_h7) // (100))) >> 4
|
2017-11-17 12:29:48 +01:00
|
|
|
var5 = ((var3 >> 14) * (var3 >> 14)) >> 10
|
|
|
|
var6 = (var4 * var5) >> 1
|
|
|
|
calc_hum = (((var3 + var6) >> 10) * (1000)) >> 12
|
2017-10-15 12:29:51 +02:00
|
|
|
|
|
|
|
return min(max(calc_hum,0),100000)
|
|
|
|
|
|
|
|
def _calc_gas_resistance(self, gas_res_adc, gas_range):
|
2017-11-17 12:29:48 +01:00
|
|
|
var1 = ((1340 + (5 * self.calibration_data.range_sw_err)) * (lookupTable1[gas_range])) >> 16
|
|
|
|
var2 = (((gas_res_adc << 15) - (16777216)) + var1)
|
|
|
|
var3 = ((lookupTable2[gas_range] * var1) >> 9)
|
|
|
|
calc_gas_res = ((var3 + (var2 >> 1)) / var2)
|
2017-10-15 12:29:51 +02:00
|
|
|
|
2017-12-01 15:08:40 +01:00
|
|
|
if calc_gas_res < 0:
|
|
|
|
calc_gas_res = (1<<32) + calc_gas_res
|
|
|
|
|
2017-10-15 12:29:51 +02:00
|
|
|
return calc_gas_res
|
|
|
|
|
|
|
|
def _calc_heater_resistance(self, temperature):
|
|
|
|
temperature = min(max(temperature,200),400)
|
|
|
|
|
|
|
|
var1 = ((self.ambient_temperature * self.calibration_data.par_gh3) / 1000) * 256
|
|
|
|
var2 = (self.calibration_data.par_gh1 + 784) * (((((self.calibration_data.par_gh2 + 154009) * temperature * 5) / 100) + 3276800) / 10)
|
|
|
|
var3 = var1 + (var2 / 2)
|
|
|
|
var4 = (var3 / (self.calibration_data.res_heat_range + 4))
|
|
|
|
var5 = (131 * self.calibration_data.res_heat_val) + 65536
|
|
|
|
heatr_res_x100 = (((var4 / var5) - 250) * 34)
|
|
|
|
heatr_res = ((heatr_res_x100 + 50) / 100)
|
|
|
|
|
2017-10-17 12:23:41 +02:00
|
|
|
return heatr_res
|
2017-10-15 12:29:51 +02:00
|
|
|
|
|
|
|
def _calc_heater_duration(self, duration):
|
|
|
|
if duration < 0xfc0:
|
|
|
|
factor = 0
|
|
|
|
|
|
|
|
while duration > 0x3f:
|
|
|
|
duration /= 4
|
|
|
|
factor += 1
|
|
|
|
|
|
|
|
return int(duration + (factor * 64))
|
|
|
|
|
|
|
|
return 0xff
|