2017-01-28 13:41:01 +00:00
/*
2019-10-27 10:13:24 +00:00
xsns_09_bmp . ino - BMP pressure , temperature , humidity and gas sensor support for Tasmota
2017-05-13 12:02:10 +01:00
2021-01-01 12:44:04 +00:00
Copyright ( C ) 2021 Heiko Krupp and Theo Arends
2017-05-13 12:02:10 +01:00
This program is free software : you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation , either version 3 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2017-01-28 13:41:01 +00:00
*/
# ifdef USE_I2C
# ifdef USE_BMP
/*********************************************************************************************\
2017-12-06 16:14:41 +00:00
* BMP085 , BMP180 , BMP280 , BME280 , BME680 - Pressure , Temperature , Humidity ( BME280 / BME680 ) and gas ( BME680 )
2017-01-28 13:41:01 +00:00
*
* Source : Heiko Krupp and Adafruit Industries
2017-11-11 11:33:30 +00:00
*
* I2C Address : 0x76 or 0x77
2017-01-28 13:41:01 +00:00
\ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2018-11-06 16:33:51 +00:00
# define XSNS_09 9
2019-11-03 16:54:39 +00:00
# define XI2C_10 10 // See I2CDEVICES.md
2018-11-06 16:33:51 +00:00
2022-01-19 16:05:39 +00:00
# ifdef USE_BME680
# define USE_BME68X
# endif
2018-10-29 14:46:03 +00:00
# define BMP_ADDR1 0x76
# define BMP_ADDR2 0x77
2017-01-28 13:41:01 +00:00
2017-10-23 11:18:15 +01:00
# define BMP180_CHIPID 0x55
# define BMP280_CHIPID 0x58
# define BME280_CHIPID 0x60
2017-12-06 16:14:41 +00:00
# define BME680_CHIPID 0x61
2017-01-28 13:41:01 +00:00
2017-10-23 11:18:15 +01:00
# define BMP_REGISTER_CHIPID 0xD0
2017-01-28 13:41:01 +00:00
2020-01-02 20:38:18 +00:00
# define BMP_REGISTER_RESET 0xE0 // Register to reset to power on defaults (used for sleep)
# define BMP_CMND_RESET 0xB6 // I2C Parameter for RESET to put BMP into reset state
2018-10-29 14:46:03 +00:00
# define BMP_MAX_SENSORS 2
2017-11-11 11:33:30 +00:00
2018-10-29 14:46:03 +00:00
const char kBmpTypes [ ] PROGMEM = " BMP180|BMP280|BME280|BME680 " ;
2018-12-21 10:36:55 +00:00
typedef struct {
2018-10-29 14:46:03 +00:00
uint8_t bmp_address ; // I2C bus address
char bmp_name [ 7 ] ; // Sensor name - "BMPXXX"
2018-12-21 15:17:06 +00:00
uint8_t bmp_type ;
uint8_t bmp_model ;
2022-01-19 16:05:39 +00:00
# ifdef USE_BME68X
2018-12-21 15:17:06 +00:00
uint8_t bme680_state ;
float bmp_gas_resistance ;
2022-01-19 16:05:39 +00:00
# endif // USE_BME68X
2018-12-21 15:17:06 +00:00
float bmp_temperature ;
float bmp_pressure ;
float bmp_humidity ;
2018-12-21 10:36:55 +00:00
} bmp_sensors_t ;
uint8_t bmp_addresses [ ] = { BMP_ADDR1 , BMP_ADDR2 } ;
uint8_t bmp_count = 0 ;
uint8_t bmp_once = 1 ;
2019-03-26 17:26:50 +00:00
bmp_sensors_t * bmp_sensors = nullptr ;
2018-07-11 13:21:11 +01:00
2017-01-28 13:41:01 +00:00
/*********************************************************************************************\
* BMP085 and BME180
\ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2017-10-23 11:18:15 +01:00
# define BMP180_REG_CONTROL 0xF4
# define BMP180_REG_RESULT 0xF6
# define BMP180_TEMPERATURE 0x2E
# define BMP180_PRESSURE3 0xF4 // Max. oversampling -> OSS = 3
# define BMP180_AC1 0xAA
# define BMP180_AC2 0xAC
# define BMP180_AC3 0xAE
# define BMP180_AC4 0xB0
# define BMP180_AC5 0xB2
# define BMP180_AC6 0xB4
# define BMP180_VB1 0xB6
# define BMP180_VB2 0xB8
# define BMP180_MB 0xBA
# define BMP180_MC 0xBC
# define BMP180_MD 0xBE
# define BMP180_OSS 3
2018-12-21 10:36:55 +00:00
typedef struct {
2018-10-30 14:20:19 +00:00
int16_t cal_ac1 ;
int16_t cal_ac2 ;
int16_t cal_ac3 ;
int16_t cal_b1 ;
int16_t cal_b2 ;
int16_t cal_mc ;
int16_t cal_md ;
uint16_t cal_ac4 ;
uint16_t cal_ac5 ;
uint16_t cal_ac6 ;
2018-12-21 10:36:55 +00:00
} bmp180_cal_data_t ;
2019-03-26 17:26:50 +00:00
bmp180_cal_data_t * bmp180_cal_data = nullptr ;
2018-10-30 14:20:19 +00:00
2019-01-28 13:08:33 +00:00
bool Bmp180Calibration ( uint8_t bmp_idx )
2017-01-28 13:41:01 +00:00
{
2018-12-21 10:36:55 +00:00
if ( ! bmp180_cal_data ) {
bmp180_cal_data = ( bmp180_cal_data_t * ) malloc ( BMP_MAX_SENSORS * sizeof ( bmp180_cal_data_t ) ) ;
}
if ( ! bmp180_cal_data ) { return false ; }
2018-10-30 14:20:19 +00:00
bmp180_cal_data [ bmp_idx ] . cal_ac1 = I2cRead16 ( bmp_sensors [ bmp_idx ] . bmp_address , BMP180_AC1 ) ;
bmp180_cal_data [ bmp_idx ] . cal_ac2 = I2cRead16 ( bmp_sensors [ bmp_idx ] . bmp_address , BMP180_AC2 ) ;
bmp180_cal_data [ bmp_idx ] . cal_ac3 = I2cRead16 ( bmp_sensors [ bmp_idx ] . bmp_address , BMP180_AC3 ) ;
bmp180_cal_data [ bmp_idx ] . cal_ac4 = I2cRead16 ( bmp_sensors [ bmp_idx ] . bmp_address , BMP180_AC4 ) ;
bmp180_cal_data [ bmp_idx ] . cal_ac5 = I2cRead16 ( bmp_sensors [ bmp_idx ] . bmp_address , BMP180_AC5 ) ;
bmp180_cal_data [ bmp_idx ] . cal_ac6 = I2cRead16 ( bmp_sensors [ bmp_idx ] . bmp_address , BMP180_AC6 ) ;
bmp180_cal_data [ bmp_idx ] . cal_b1 = I2cRead16 ( bmp_sensors [ bmp_idx ] . bmp_address , BMP180_VB1 ) ;
bmp180_cal_data [ bmp_idx ] . cal_b2 = I2cRead16 ( bmp_sensors [ bmp_idx ] . bmp_address , BMP180_VB2 ) ;
bmp180_cal_data [ bmp_idx ] . cal_mc = I2cRead16 ( bmp_sensors [ bmp_idx ] . bmp_address , BMP180_MC ) ;
bmp180_cal_data [ bmp_idx ] . cal_md = I2cRead16 ( bmp_sensors [ bmp_idx ] . bmp_address , BMP180_MD ) ;
2017-01-28 13:41:01 +00:00
// Check for Errors in calibration data. Value never is 0x0000 or 0xFFFF
2018-10-30 14:20:19 +00:00
if ( ! bmp180_cal_data [ bmp_idx ] . cal_ac1 |
! bmp180_cal_data [ bmp_idx ] . cal_ac2 |
! bmp180_cal_data [ bmp_idx ] . cal_ac3 |
! bmp180_cal_data [ bmp_idx ] . cal_ac4 |
! bmp180_cal_data [ bmp_idx ] . cal_ac5 |
! bmp180_cal_data [ bmp_idx ] . cal_ac6 |
! bmp180_cal_data [ bmp_idx ] . cal_b1 |
! bmp180_cal_data [ bmp_idx ] . cal_b2 |
! bmp180_cal_data [ bmp_idx ] . cal_mc |
! bmp180_cal_data [ bmp_idx ] . cal_md ) {
2017-04-25 17:24:42 +01:00
return false ;
}
2018-10-30 14:20:19 +00:00
if ( ( bmp180_cal_data [ bmp_idx ] . cal_ac1 = = ( int16_t ) 0xFFFF ) |
( bmp180_cal_data [ bmp_idx ] . cal_ac2 = = ( int16_t ) 0xFFFF ) |
( bmp180_cal_data [ bmp_idx ] . cal_ac3 = = ( int16_t ) 0xFFFF ) |
( bmp180_cal_data [ bmp_idx ] . cal_ac4 = = 0xFFFF ) |
( bmp180_cal_data [ bmp_idx ] . cal_ac5 = = 0xFFFF ) |
( bmp180_cal_data [ bmp_idx ] . cal_ac6 = = 0xFFFF ) |
( bmp180_cal_data [ bmp_idx ] . cal_b1 = = ( int16_t ) 0xFFFF ) |
( bmp180_cal_data [ bmp_idx ] . cal_b2 = = ( int16_t ) 0xFFFF ) |
( bmp180_cal_data [ bmp_idx ] . cal_mc = = ( int16_t ) 0xFFFF ) |
( bmp180_cal_data [ bmp_idx ] . cal_md = = ( int16_t ) 0xFFFF ) ) {
2017-04-25 17:24:42 +01:00
return false ;
}
2017-01-28 13:41:01 +00:00
return true ;
}
2018-10-30 14:20:19 +00:00
void Bmp180Read ( uint8_t bmp_idx )
2017-01-28 13:41:01 +00:00
{
2018-12-21 10:36:55 +00:00
if ( ! bmp180_cal_data ) { return ; }
2018-10-29 14:46:03 +00:00
I2cWrite8 ( bmp_sensors [ bmp_idx ] . bmp_address , BMP180_REG_CONTROL , BMP180_TEMPERATURE ) ;
2017-01-28 13:41:01 +00:00
delay ( 5 ) ; // 5ms conversion time
2018-10-29 14:46:03 +00:00
int ut = I2cRead16 ( bmp_sensors [ bmp_idx ] . bmp_address , BMP180_REG_RESULT ) ;
2018-10-30 14:20:19 +00:00
int32_t xt1 = ( ut - ( int32_t ) bmp180_cal_data [ bmp_idx ] . cal_ac6 ) * ( ( int32_t ) bmp180_cal_data [ bmp_idx ] . cal_ac5 ) > > 15 ;
int32_t xt2 = ( ( int32_t ) bmp180_cal_data [ bmp_idx ] . cal_mc < < 11 ) / ( xt1 + ( int32_t ) bmp180_cal_data [ bmp_idx ] . cal_md ) ;
2018-07-11 13:39:07 +01:00
int32_t bmp180_b5 = xt1 + xt2 ;
2022-04-19 14:44:53 +01:00
bmp_sensors [ bmp_idx ] . bmp_temperature = ( ( bmp180_b5 + 8 ) > > 4 ) / 10.0f ;
2017-01-28 13:41:01 +00:00
2018-10-29 14:46:03 +00:00
I2cWrite8 ( bmp_sensors [ bmp_idx ] . bmp_address , BMP180_REG_CONTROL , BMP180_PRESSURE3 ) ; // Highest resolution
2017-10-23 11:18:15 +01:00
delay ( 2 + ( 4 < < BMP180_OSS ) ) ; // 26ms conversion time at ultra high resolution
2018-10-29 14:46:03 +00:00
uint32_t up = I2cRead24 ( bmp_sensors [ bmp_idx ] . bmp_address , BMP180_REG_RESULT ) ;
2017-01-28 13:41:01 +00:00
up > > = ( 8 - BMP180_OSS ) ;
int32_t b6 = bmp180_b5 - 4000 ;
2018-10-30 14:20:19 +00:00
int32_t x1 = ( ( int32_t ) bmp180_cal_data [ bmp_idx ] . cal_b2 * ( ( b6 * b6 ) > > 12 ) ) > > 11 ;
int32_t x2 = ( ( int32_t ) bmp180_cal_data [ bmp_idx ] . cal_ac2 * b6 ) > > 11 ;
2017-01-28 13:41:01 +00:00
int32_t x3 = x1 + x2 ;
2018-10-30 14:20:19 +00:00
int32_t b3 = ( ( ( ( int32_t ) bmp180_cal_data [ bmp_idx ] . cal_ac1 * 4 + x3 ) < < BMP180_OSS ) + 2 ) > > 2 ;
2017-01-28 13:41:01 +00:00
2018-10-30 14:20:19 +00:00
x1 = ( ( int32_t ) bmp180_cal_data [ bmp_idx ] . cal_ac3 * b6 ) > > 13 ;
x2 = ( ( int32_t ) bmp180_cal_data [ bmp_idx ] . cal_b1 * ( ( b6 * b6 ) > > 12 ) ) > > 16 ;
2017-01-28 13:41:01 +00:00
x3 = ( ( x1 + x2 ) + 2 ) > > 2 ;
2018-10-30 14:20:19 +00:00
uint32_t b4 = ( ( uint32_t ) bmp180_cal_data [ bmp_idx ] . cal_ac4 * ( uint32_t ) ( x3 + 32768 ) ) > > 15 ;
2017-10-08 15:51:05 +01:00
uint32_t b7 = ( ( uint32_t ) up - b3 ) * ( uint32_t ) ( 50000UL > > BMP180_OSS ) ;
2017-01-28 13:41:01 +00:00
2018-07-11 13:21:11 +01:00
int32_t p ;
2017-01-28 13:41:01 +00:00
if ( b7 < 0x80000000 ) {
p = ( b7 * 2 ) / b4 ;
2017-10-08 15:51:05 +01:00
}
else {
2017-01-28 13:41:01 +00:00
p = ( b7 / b4 ) * 2 ;
}
x1 = ( p > > 8 ) * ( p > > 8 ) ;
x1 = ( x1 * 3038 ) > > 16 ;
x2 = ( - 7357 * p ) > > 16 ;
2017-10-08 15:51:05 +01:00
p + = ( ( x1 + x2 + ( int32_t ) 3791 ) > > 4 ) ;
2022-04-19 14:44:53 +01:00
bmp_sensors [ bmp_idx ] . bmp_pressure = ( float ) p / 100.0f ; // convert to mbar
2017-01-28 13:41:01 +00:00
}
/*********************************************************************************************\
* BMP280 and BME280
*
* Programmer : BMP280 / BME280 Datasheet and Adafruit with changes by Theo Arends
\ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2017-10-23 11:18:15 +01:00
# define BME280_REGISTER_CONTROLHUMID 0xF2
# define BME280_REGISTER_CONTROL 0xF4
2017-12-03 15:17:47 +00:00
# define BME280_REGISTER_CONFIG 0xF5
2017-10-23 11:18:15 +01:00
# define BME280_REGISTER_PRESSUREDATA 0xF7
# define BME280_REGISTER_TEMPDATA 0xFA
# define BME280_REGISTER_HUMIDDATA 0xFD
# define BME280_REGISTER_DIG_T1 0x88
# define BME280_REGISTER_DIG_T2 0x8A
# define BME280_REGISTER_DIG_T3 0x8C
# define BME280_REGISTER_DIG_P1 0x8E
# define BME280_REGISTER_DIG_P2 0x90
# define BME280_REGISTER_DIG_P3 0x92
# define BME280_REGISTER_DIG_P4 0x94
# define BME280_REGISTER_DIG_P5 0x96
# define BME280_REGISTER_DIG_P6 0x98
# define BME280_REGISTER_DIG_P7 0x9A
# define BME280_REGISTER_DIG_P8 0x9C
# define BME280_REGISTER_DIG_P9 0x9E
# define BME280_REGISTER_DIG_H1 0xA1
# define BME280_REGISTER_DIG_H2 0xE1
# define BME280_REGISTER_DIG_H3 0xE3
# define BME280_REGISTER_DIG_H4 0xE4
# define BME280_REGISTER_DIG_H5 0xE5
# define BME280_REGISTER_DIG_H6 0xE7
2017-01-28 13:41:01 +00:00
2018-12-21 10:36:55 +00:00
typedef struct {
2017-01-28 13:41:01 +00:00
uint16_t dig_T1 ;
2017-10-23 11:18:15 +01:00
int16_t dig_T2 ;
int16_t dig_T3 ;
2017-01-28 13:41:01 +00:00
uint16_t dig_P1 ;
2017-10-23 11:18:15 +01:00
int16_t dig_P2 ;
int16_t dig_P3 ;
int16_t dig_P4 ;
int16_t dig_P5 ;
int16_t dig_P6 ;
int16_t dig_P7 ;
int16_t dig_P8 ;
int16_t dig_P9 ;
int16_t dig_H2 ;
int16_t dig_H4 ;
int16_t dig_H5 ;
2018-10-30 14:20:19 +00:00
uint8_t dig_H1 ;
uint8_t dig_H3 ;
2017-10-23 11:18:15 +01:00
int8_t dig_H6 ;
2018-12-21 10:36:55 +00:00
} Bme280CalibrationData_t ;
2019-03-26 17:26:50 +00:00
Bme280CalibrationData_t * Bme280CalibrationData = nullptr ;
2017-01-28 13:41:01 +00:00
2019-01-28 13:08:33 +00:00
bool Bmx280Calibrate ( uint8_t bmp_idx )
2017-01-28 13:41:01 +00:00
{
2017-10-18 17:22:34 +01:00
// if (I2cRead8(bmp_address, BMP_REGISTER_CHIPID) != BME280_CHIPID) return false;
2018-12-21 10:36:55 +00:00
if ( ! Bme280CalibrationData ) {
Bme280CalibrationData = ( Bme280CalibrationData_t * ) malloc ( BMP_MAX_SENSORS * sizeof ( Bme280CalibrationData_t ) ) ;
}
if ( ! Bme280CalibrationData ) { return false ; }
2018-10-30 14:20:19 +00:00
Bme280CalibrationData [ bmp_idx ] . dig_T1 = I2cRead16LE ( bmp_sensors [ bmp_idx ] . bmp_address , BME280_REGISTER_DIG_T1 ) ;
Bme280CalibrationData [ bmp_idx ] . dig_T2 = I2cReadS16_LE ( bmp_sensors [ bmp_idx ] . bmp_address , BME280_REGISTER_DIG_T2 ) ;
Bme280CalibrationData [ bmp_idx ] . dig_T3 = I2cReadS16_LE ( bmp_sensors [ bmp_idx ] . bmp_address , BME280_REGISTER_DIG_T3 ) ;
Bme280CalibrationData [ bmp_idx ] . dig_P1 = I2cRead16LE ( bmp_sensors [ bmp_idx ] . bmp_address , BME280_REGISTER_DIG_P1 ) ;
Bme280CalibrationData [ bmp_idx ] . dig_P2 = I2cReadS16_LE ( bmp_sensors [ bmp_idx ] . bmp_address , BME280_REGISTER_DIG_P2 ) ;
Bme280CalibrationData [ bmp_idx ] . dig_P3 = I2cReadS16_LE ( bmp_sensors [ bmp_idx ] . bmp_address , BME280_REGISTER_DIG_P3 ) ;
Bme280CalibrationData [ bmp_idx ] . dig_P4 = I2cReadS16_LE ( bmp_sensors [ bmp_idx ] . bmp_address , BME280_REGISTER_DIG_P4 ) ;
Bme280CalibrationData [ bmp_idx ] . dig_P5 = I2cReadS16_LE ( bmp_sensors [ bmp_idx ] . bmp_address , BME280_REGISTER_DIG_P5 ) ;
Bme280CalibrationData [ bmp_idx ] . dig_P6 = I2cReadS16_LE ( bmp_sensors [ bmp_idx ] . bmp_address , BME280_REGISTER_DIG_P6 ) ;
Bme280CalibrationData [ bmp_idx ] . dig_P7 = I2cReadS16_LE ( bmp_sensors [ bmp_idx ] . bmp_address , BME280_REGISTER_DIG_P7 ) ;
Bme280CalibrationData [ bmp_idx ] . dig_P8 = I2cReadS16_LE ( bmp_sensors [ bmp_idx ] . bmp_address , BME280_REGISTER_DIG_P8 ) ;
Bme280CalibrationData [ bmp_idx ] . dig_P9 = I2cReadS16_LE ( bmp_sensors [ bmp_idx ] . bmp_address , BME280_REGISTER_DIG_P9 ) ;
2018-10-29 14:46:03 +00:00
if ( BME280_CHIPID = = bmp_sensors [ bmp_idx ] . bmp_type ) { // #1051
2018-10-30 14:20:19 +00:00
Bme280CalibrationData [ bmp_idx ] . dig_H1 = I2cRead8 ( bmp_sensors [ bmp_idx ] . bmp_address , BME280_REGISTER_DIG_H1 ) ;
Bme280CalibrationData [ bmp_idx ] . dig_H2 = I2cReadS16_LE ( bmp_sensors [ bmp_idx ] . bmp_address , BME280_REGISTER_DIG_H2 ) ;
Bme280CalibrationData [ bmp_idx ] . dig_H3 = I2cRead8 ( bmp_sensors [ bmp_idx ] . bmp_address , BME280_REGISTER_DIG_H3 ) ;
Bme280CalibrationData [ bmp_idx ] . dig_H4 = ( I2cRead8 ( bmp_sensors [ bmp_idx ] . bmp_address , BME280_REGISTER_DIG_H4 ) < < 4 ) | ( I2cRead8 ( bmp_sensors [ bmp_idx ] . bmp_address , BME280_REGISTER_DIG_H4 + 1 ) & 0xF ) ;
Bme280CalibrationData [ bmp_idx ] . dig_H5 = ( I2cRead8 ( bmp_sensors [ bmp_idx ] . bmp_address , BME280_REGISTER_DIG_H5 + 1 ) < < 4 ) | ( I2cRead8 ( bmp_sensors [ bmp_idx ] . bmp_address , BME280_REGISTER_DIG_H5 ) > > 4 ) ;
Bme280CalibrationData [ bmp_idx ] . dig_H6 = ( int8_t ) I2cRead8 ( bmp_sensors [ bmp_idx ] . bmp_address , BME280_REGISTER_DIG_H6 ) ;
2018-10-29 14:46:03 +00:00
I2cWrite8 ( bmp_sensors [ bmp_idx ] . bmp_address , BME280_REGISTER_CONTROL , 0x00 ) ; // sleep mode since writes to config can be ignored in normal mode (Datasheet 5.4.5/6 page 27)
2017-12-03 15:17:47 +00:00
// Set before CONTROL_meas (DS 5.4.3)
2018-10-29 14:46:03 +00:00
I2cWrite8 ( bmp_sensors [ bmp_idx ] . bmp_address , BME280_REGISTER_CONTROLHUMID , 0x01 ) ; // 1x oversampling
I2cWrite8 ( bmp_sensors [ bmp_idx ] . bmp_address , BME280_REGISTER_CONFIG , 0xA0 ) ; // 1sec standby between measurements (to limit self heating), IIR filter off
I2cWrite8 ( bmp_sensors [ bmp_idx ] . bmp_address , BME280_REGISTER_CONTROL , 0x27 ) ; // 1x oversampling, normal mode
2017-12-03 15:17:47 +00:00
} else {
2018-10-29 14:46:03 +00:00
I2cWrite8 ( bmp_sensors [ bmp_idx ] . bmp_address , BME280_REGISTER_CONTROL , 0xB7 ) ; // 16x oversampling, normal mode (Adafruit)
2017-12-03 15:17:47 +00:00
}
2017-01-28 13:41:01 +00:00
return true ;
}
2018-10-30 14:20:19 +00:00
void Bme280Read ( uint8_t bmp_idx )
2017-01-28 13:41:01 +00:00
{
2018-12-21 10:36:55 +00:00
if ( ! Bme280CalibrationData ) { return ; }
2018-10-29 14:46:03 +00:00
int32_t adc_T = I2cRead24 ( bmp_sensors [ bmp_idx ] . bmp_address , BME280_REGISTER_TEMPDATA ) ;
2017-01-28 13:41:01 +00:00
adc_T > > = 4 ;
2018-10-30 14:20:19 +00:00
int32_t vart1 = ( ( ( ( adc_T > > 3 ) - ( ( int32_t ) Bme280CalibrationData [ bmp_idx ] . dig_T1 < < 1 ) ) ) * ( ( int32_t ) Bme280CalibrationData [ bmp_idx ] . dig_T2 ) ) > > 11 ;
int32_t vart2 = ( ( ( ( ( adc_T > > 4 ) - ( ( int32_t ) Bme280CalibrationData [ bmp_idx ] . dig_T1 ) ) * ( ( adc_T > > 4 ) - ( ( int32_t ) Bme280CalibrationData [ bmp_idx ] . dig_T1 ) ) ) > > 12 ) *
( ( int32_t ) Bme280CalibrationData [ bmp_idx ] . dig_T3 ) ) > > 14 ;
2018-07-11 13:21:11 +01:00
int32_t t_fine = vart1 + vart2 ;
2018-07-11 13:39:07 +01:00
float T = ( t_fine * 5 + 128 ) > > 8 ;
2022-04-19 14:44:53 +01:00
bmp_sensors [ bmp_idx ] . bmp_temperature = T / 100.0f ;
2017-01-28 13:41:01 +00:00
2018-10-29 14:46:03 +00:00
int32_t adc_P = I2cRead24 ( bmp_sensors [ bmp_idx ] . bmp_address , BME280_REGISTER_PRESSUREDATA ) ;
2017-01-28 13:41:01 +00:00
adc_P > > = 4 ;
2018-07-11 13:21:11 +01:00
int64_t var1 = ( ( int64_t ) t_fine ) - 128000 ;
2018-10-30 14:20:19 +00:00
int64_t var2 = var1 * var1 * ( int64_t ) Bme280CalibrationData [ bmp_idx ] . dig_P6 ;
var2 = var2 + ( ( var1 * ( int64_t ) Bme280CalibrationData [ bmp_idx ] . dig_P5 ) < < 17 ) ;
var2 = var2 + ( ( ( int64_t ) Bme280CalibrationData [ bmp_idx ] . dig_P4 ) < < 35 ) ;
var1 = ( ( var1 * var1 * ( int64_t ) Bme280CalibrationData [ bmp_idx ] . dig_P3 ) > > 8 ) + ( ( var1 * ( int64_t ) Bme280CalibrationData [ bmp_idx ] . dig_P2 ) < < 12 ) ;
var1 = ( ( ( ( ( int64_t ) 1 ) < < 47 ) + var1 ) ) * ( ( int64_t ) Bme280CalibrationData [ bmp_idx ] . dig_P1 ) > > 33 ;
2017-04-25 17:24:42 +01:00
if ( 0 = = var1 ) {
2018-07-11 13:21:11 +01:00
return ; // avoid exception caused by division by zero
2017-01-28 13:41:01 +00:00
}
2018-07-11 13:21:11 +01:00
int64_t p = 1048576 - adc_P ;
2017-01-28 13:41:01 +00:00
p = ( ( ( p < < 31 ) - var2 ) * 3125 ) / var1 ;
2018-10-30 14:20:19 +00:00
var1 = ( ( ( int64_t ) Bme280CalibrationData [ bmp_idx ] . dig_P9 ) * ( p > > 13 ) * ( p > > 13 ) ) > > 25 ;
var2 = ( ( ( int64_t ) Bme280CalibrationData [ bmp_idx ] . dig_P8 ) * p ) > > 19 ;
p = ( ( p + var1 + var2 ) > > 8 ) + ( ( ( int64_t ) Bme280CalibrationData [ bmp_idx ] . dig_P7 ) < < 4 ) ;
2022-04-19 14:44:53 +01:00
bmp_sensors [ bmp_idx ] . bmp_pressure = ( float ) p / 25600.0f ;
2017-01-28 13:41:01 +00:00
2018-10-29 14:46:03 +00:00
if ( BMP280_CHIPID = = bmp_sensors [ bmp_idx ] . bmp_type ) { return ; }
2017-01-28 13:41:01 +00:00
2018-10-29 14:46:03 +00:00
int32_t adc_H = I2cRead16 ( bmp_sensors [ bmp_idx ] . bmp_address , BME280_REGISTER_HUMIDDATA ) ;
2018-07-11 13:39:07 +01:00
int32_t v_x1_u32r = ( t_fine - ( ( int32_t ) 76800 ) ) ;
2018-10-30 14:20:19 +00:00
v_x1_u32r = ( ( ( ( ( adc_H < < 14 ) - ( ( ( int32_t ) Bme280CalibrationData [ bmp_idx ] . dig_H4 ) < < 20 ) -
( ( ( int32_t ) Bme280CalibrationData [ bmp_idx ] . dig_H5 ) * v_x1_u32r ) ) + ( ( int32_t ) 16384 ) ) > > 15 ) *
( ( ( ( ( ( ( v_x1_u32r * ( ( int32_t ) Bme280CalibrationData [ bmp_idx ] . dig_H6 ) ) > > 10 ) *
( ( ( v_x1_u32r * ( ( int32_t ) Bme280CalibrationData [ bmp_idx ] . dig_H3 ) ) > > 11 ) + ( ( int32_t ) 32768 ) ) ) > > 10 ) +
( ( int32_t ) 2097152 ) ) * ( ( int32_t ) Bme280CalibrationData [ bmp_idx ] . dig_H2 ) + 8192 ) > > 14 ) ) ;
2017-01-28 13:41:01 +00:00
v_x1_u32r = ( v_x1_u32r - ( ( ( ( ( v_x1_u32r > > 15 ) * ( v_x1_u32r > > 15 ) ) > > 7 ) *
2018-10-30 14:20:19 +00:00
( ( int32_t ) Bme280CalibrationData [ bmp_idx ] . dig_H1 ) ) > > 4 ) ) ;
2017-01-28 13:41:01 +00:00
v_x1_u32r = ( v_x1_u32r < 0 ) ? 0 : v_x1_u32r ;
v_x1_u32r = ( v_x1_u32r > 419430400 ) ? 419430400 : v_x1_u32r ;
2018-07-11 13:21:11 +01:00
float h = ( v_x1_u32r > > 12 ) ;
2022-04-19 14:44:53 +01:00
bmp_sensors [ bmp_idx ] . bmp_humidity = h / 1024.0f ;
2017-01-28 13:41:01 +00:00
}
2022-01-19 16:05:39 +00:00
# ifdef USE_BME68X
2017-01-28 13:41:01 +00:00
/*********************************************************************************************\
2022-01-19 16:05:39 +00:00
* BME68x support by Bosch https : //github.com/BoschSensortec/BME68x-Sensor-API
2017-01-28 13:41:01 +00:00
\ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2022-01-19 16:05:39 +00:00
//#define BME68X_DO_NOT_USE_FPU
2018-07-04 17:41:00 +01:00
2022-01-19 16:05:39 +00:00
# include <bme68x.h>
2018-07-04 17:41:00 +01:00
2022-01-20 14:01:52 +00:00
struct bme68x_dev * bme_dev = nullptr ;
2022-01-19 16:05:39 +00:00
struct bme68x_conf * bme_conf = nullptr ;
struct bme68x_heatr_conf * bme_heatr_conf = nullptr ;
static void Bme68x_Delayus ( uint32_t period , void * intf_ptr ) {
delayMicroseconds ( period ) ;
2018-07-04 17:41:00 +01:00
}
2022-01-19 16:05:39 +00:00
int8_t Bme68x_i2c_read ( uint8_t reg_addr , uint8_t * reg_data , uint32_t len , void * intf_ptr ) {
uint8_t dev_addr = * ( uint8_t * ) intf_ptr ;
return I2cReadBuffer ( dev_addr , reg_addr , reg_data , ( uint16_t ) len ) ;
}
int8_t Bme68x_i2c_write ( uint8_t reg_addr , const uint8_t * reg_data , uint32_t len , void * intf_ptr ) {
uint8_t dev_addr = * ( uint8_t * ) intf_ptr ;
return I2cWriteBuffer ( dev_addr , reg_addr , ( uint8_t * ) reg_data , ( uint16_t ) len ) ;
}
bool Bme680Init ( uint8_t bmp_idx ) {
2022-01-20 14:01:52 +00:00
if ( ! bme_dev ) {
2022-01-19 16:05:39 +00:00
bme_heatr_conf = ( bme68x_heatr_conf * ) malloc ( BMP_MAX_SENSORS * sizeof ( bme68x_heatr_conf ) ) ;
bme_conf = ( bme68x_conf * ) malloc ( BMP_MAX_SENSORS * sizeof ( bme68x_conf ) ) ;
2022-01-20 14:01:52 +00:00
bme_dev = ( bme68x_dev * ) malloc ( BMP_MAX_SENSORS * sizeof ( bme68x_dev ) ) ;
2018-12-21 10:36:55 +00:00
}
2022-01-20 14:01:52 +00:00
if ( ! bme_dev ) { return false ; }
2018-12-21 10:36:55 +00:00
2022-01-20 14:01:52 +00:00
bme_dev [ bmp_idx ] . intf_ptr = & bmp_sensors [ bmp_idx ] . bmp_address ;
bme_dev [ bmp_idx ] . intf = BME68X_I2C_INTF ;
bme_dev [ bmp_idx ] . read = Bme68x_i2c_read ;
bme_dev [ bmp_idx ] . write = Bme68x_i2c_write ;
bme_dev [ bmp_idx ] . delay_us = Bme68x_Delayus ;
2022-01-19 16:05:39 +00:00
// amb_temp can be set to 25 prior to configuring the gas sensor
// or by performing a few temperature readings without operating the gas sensor.
2022-01-20 14:01:52 +00:00
bme_dev [ bmp_idx ] . amb_temp = 25 ;
int8_t rslt = bme68x_init ( & bme_dev [ bmp_idx ] ) ;
2022-01-19 16:05:39 +00:00
if ( rslt ! = BME68X_OK ) { return false ; }
2022-01-20 14:01:52 +00:00
// AddLog(LOG_LEVEL_DEBUG, PSTR("BME: Gas variant %d"), bme_dev[bmp_idx].variant_id);
// rslt = bme68x_get_conf(&bme_conf[bmp_idx], &bme_dev[bmp_idx]);
2022-01-19 16:05:39 +00:00
// if (rslt != BME68X_OK) { return false; }
// Set the temperature, pressure and humidity settings
bme_conf [ bmp_idx ] . os_hum = BME68X_OS_2X ;
bme_conf [ bmp_idx ] . os_pres = BME68X_OS_4X ;
bme_conf [ bmp_idx ] . os_temp = BME68X_OS_8X ;
bme_conf [ bmp_idx ] . filter = BME68X_FILTER_SIZE_3 ;
bme_conf [ bmp_idx ] . odr = BME68X_ODR_NONE ; // This parameter defines the sleep duration after each profile
2022-01-20 14:01:52 +00:00
rslt = bme68x_set_conf ( & bme_conf [ bmp_idx ] , & bme_dev [ bmp_idx ] ) ;
2022-01-19 16:05:39 +00:00
if ( rslt ! = BME68X_OK ) { return false ; }
// Set the gas sensor settings
bme_heatr_conf [ bmp_idx ] . enable = BME68X_ENABLE ;
// Create a ramp heat waveform in 3 steps
bme_heatr_conf [ bmp_idx ] . heatr_temp = 320 ; // degree Celsius
bme_heatr_conf [ bmp_idx ] . heatr_dur = 150 ; // milliseconds
2022-01-20 14:01:52 +00:00
rslt = bme68x_set_heatr_conf ( BME68X_FORCED_MODE , & bme_heatr_conf [ bmp_idx ] , & bme_dev [ bmp_idx ] ) ;
2022-01-19 16:05:39 +00:00
if ( rslt ! = BME68X_OK ) { return false ; }
2018-07-04 17:41:00 +01:00
2018-10-29 14:46:03 +00:00
bmp_sensors [ bmp_idx ] . bme680_state = 0 ;
2018-07-04 17:41:00 +01:00
return true ;
}
2017-01-28 13:41:01 +00:00
2018-10-30 14:20:19 +00:00
void Bme680Read ( uint8_t bmp_idx )
2017-01-28 13:41:01 +00:00
{
2022-01-20 14:01:52 +00:00
if ( ! bme_dev ) { return ; }
2018-12-21 10:36:55 +00:00
2022-01-19 16:05:39 +00:00
int8_t rslt = BME68X_OK ;
2018-07-04 17:41:00 +01:00
2018-10-29 14:46:03 +00:00
if ( BME680_CHIPID = = bmp_sensors [ bmp_idx ] . bmp_type ) {
if ( 0 = = bmp_sensors [ bmp_idx ] . bme680_state ) {
2022-01-19 16:05:39 +00:00
// Trigger the next measurement if you would like to read data out continuously
2022-01-20 14:01:52 +00:00
rslt = bme68x_set_op_mode ( BME68X_FORCED_MODE , & bme_dev [ bmp_idx ] ) ;
2022-01-19 16:05:39 +00:00
if ( rslt ! = BME68X_OK ) { return ; }
2018-07-04 17:41:00 +01:00
2022-01-19 16:05:39 +00:00
// Calculate delay period in microseconds
// del_period = bme68x_get_meas_dur(BME68X_FORCED_MODE, &conf, &bme) + (heatr_conf.heatr_dur * 1000);
// bme.delay_us(del_period, bme.intf_ptr);
2018-07-04 17:41:00 +01:00
2018-10-29 14:46:03 +00:00
bmp_sensors [ bmp_idx ] . bme680_state = 1 ;
2018-07-04 17:41:00 +01:00
} else {
2018-10-29 14:46:03 +00:00
bmp_sensors [ bmp_idx ] . bme680_state = 0 ;
2018-07-04 17:41:00 +01:00
2022-01-19 16:05:39 +00:00
struct bme68x_data data ;
uint8_t n_fields ;
2022-01-20 14:01:52 +00:00
rslt = bme68x_get_data ( BME68X_FORCED_MODE , & data , & n_fields , & bme_dev [ bmp_idx ] ) ;
2022-01-19 16:05:39 +00:00
if ( rslt ! = BME68X_OK ) { return ; }
2018-07-04 17:41:00 +01:00
2022-01-19 16:05:39 +00:00
# ifdef BME68X_DO_NOT_USE_FPU
2022-04-19 14:44:53 +01:00
bmp_sensors [ bmp_idx ] . bmp_temperature = data . temperature / 100.0f ; // Temperature in degree celsius x100
bmp_sensors [ bmp_idx ] . bmp_humidity = data . humidity / 1000.0f ; // Humidity in % relative humidity x1000
2022-01-19 16:05:39 +00:00
# else
bmp_sensors [ bmp_idx ] . bmp_temperature = data . temperature ; // Temperature in degree celsius
bmp_sensors [ bmp_idx ] . bmp_humidity = data . humidity ; // Humidity in % relative humidity
# endif
2022-04-19 14:44:53 +01:00
bmp_sensors [ bmp_idx ] . bmp_pressure = data . pressure / 100.0f ; // Pressure in Pascal (converted to hPa)
2022-01-19 16:05:39 +00:00
// Avoid using measurements from an unstable heating setup
if ( data . status & BME68X_GASM_VALID_MSK ) {
2022-04-19 14:44:53 +01:00
bmp_sensors [ bmp_idx ] . bmp_gas_resistance = data . gas_resistance / 1000.0f ; // Gas resistance in Ohms (converted to kOhm)
2018-07-04 17:41:00 +01:00
} else {
2018-10-29 14:46:03 +00:00
bmp_sensors [ bmp_idx ] . bmp_gas_resistance = 0 ;
2018-07-04 17:41:00 +01:00
}
}
2017-10-08 15:51:05 +01:00
}
2018-07-04 17:41:00 +01:00
return ;
2017-01-28 13:41:01 +00:00
}
2022-01-19 16:05:39 +00:00
# endif // USE_BME68X
2017-01-28 13:41:01 +00:00
2017-11-04 15:36:51 +00:00
/********************************************************************************************/
2018-11-14 13:32:09 +00:00
void BmpDetect ( void )
2017-01-28 13:41:01 +00:00
{
2018-12-21 15:17:06 +00:00
int bmp_sensor_size = BMP_MAX_SENSORS * sizeof ( bmp_sensors_t ) ;
2018-12-21 10:36:55 +00:00
if ( ! bmp_sensors ) {
2018-12-21 15:17:06 +00:00
bmp_sensors = ( bmp_sensors_t * ) malloc ( bmp_sensor_size ) ;
2018-12-21 10:36:55 +00:00
}
if ( ! bmp_sensors ) { return ; }
2018-12-21 15:17:06 +00:00
memset ( bmp_sensors , 0 , bmp_sensor_size ) ; // Init defaults to 0
2018-12-21 10:36:55 +00:00
2019-06-30 15:44:36 +01:00
for ( uint32_t i = 0 ; i < BMP_MAX_SENSORS ; i + + ) {
2021-10-31 14:13:28 +00:00
if ( ! I2cSetDevice ( bmp_addresses [ i ] ) ) { continue ; }
2018-10-29 14:46:03 +00:00
uint8_t bmp_type = I2cRead8 ( bmp_addresses [ i ] , BMP_REGISTER_CHIPID ) ;
2017-11-11 11:33:30 +00:00
if ( bmp_type ) {
2018-10-29 14:46:03 +00:00
bmp_sensors [ bmp_count ] . bmp_address = bmp_addresses [ i ] ;
bmp_sensors [ bmp_count ] . bmp_type = bmp_type ;
bmp_sensors [ bmp_count ] . bmp_model = 0 ;
2019-01-28 13:08:33 +00:00
bool success = false ;
2018-10-29 14:46:03 +00:00
switch ( bmp_type ) {
case BMP180_CHIPID :
2018-10-30 14:20:19 +00:00
success = Bmp180Calibration ( bmp_count ) ;
2018-10-29 14:46:03 +00:00
break ;
case BME280_CHIPID :
bmp_sensors [ bmp_count ] . bmp_model + + ; // 2
case BMP280_CHIPID :
bmp_sensors [ bmp_count ] . bmp_model + + ; // 1
2018-10-30 14:20:19 +00:00
success = Bmx280Calibrate ( bmp_count ) ;
2018-10-29 14:46:03 +00:00
break ;
2022-01-19 16:05:39 +00:00
# ifdef USE_BME68X
2018-10-30 14:20:19 +00:00
case BME680_CHIPID :
bmp_sensors [ bmp_count ] . bmp_model = 3 ; // 3
success = Bme680Init ( bmp_count ) ;
break ;
2022-01-19 16:05:39 +00:00
# endif // USE_BME68X
2018-10-29 14:46:03 +00:00
}
if ( success ) {
GetTextIndexed ( bmp_sensors [ bmp_count ] . bmp_name , sizeof ( bmp_sensors [ bmp_count ] . bmp_name ) , bmp_sensors [ bmp_count ] . bmp_model , kBmpTypes ) ;
2019-11-09 17:34:22 +00:00
I2cSetActiveFound ( bmp_sensors [ bmp_count ] . bmp_address , bmp_sensors [ bmp_count ] . bmp_name ) ;
2018-10-29 14:46:03 +00:00
bmp_count + + ;
}
2017-11-11 11:33:30 +00:00
}
2017-01-28 13:41:01 +00:00
}
2018-10-29 14:46:03 +00:00
}
2018-11-14 13:32:09 +00:00
void BmpRead ( void )
2018-10-29 14:46:03 +00:00
{
2019-06-30 15:44:36 +01:00
for ( uint32_t bmp_idx = 0 ; bmp_idx < bmp_count ; bmp_idx + + ) {
2018-10-29 14:46:03 +00:00
switch ( bmp_sensors [ bmp_idx ] . bmp_type ) {
2017-11-11 11:33:30 +00:00
case BMP180_CHIPID :
2018-10-30 14:20:19 +00:00
Bmp180Read ( bmp_idx ) ;
2017-11-11 11:33:30 +00:00
break ;
2018-07-11 13:21:11 +01:00
case BMP280_CHIPID :
2018-10-29 14:46:03 +00:00
case BME280_CHIPID :
2018-10-30 14:20:19 +00:00
Bme280Read ( bmp_idx ) ;
2017-12-06 16:14:41 +00:00
break ;
2022-01-19 16:05:39 +00:00
# ifdef USE_BME68X
2018-10-30 14:20:19 +00:00
case BME680_CHIPID :
Bme680Read ( bmp_idx ) ;
break ;
2022-01-19 16:05:39 +00:00
# endif // USE_BME68X
2017-11-11 11:33:30 +00:00
}
2017-01-28 13:41:01 +00:00
}
2018-07-11 13:21:11 +01:00
}
2017-12-06 16:14:41 +00:00
2019-01-28 13:08:33 +00:00
void BmpShow ( bool json )
2018-07-11 13:21:11 +01:00
{
2019-06-30 15:44:36 +01:00
for ( uint32_t bmp_idx = 0 ; bmp_idx < bmp_count ; bmp_idx + + ) {
2018-10-29 14:46:03 +00:00
if ( bmp_sensors [ bmp_idx ] . bmp_type ) {
2020-10-29 09:34:44 +00:00
float bmp_sealevel = ConvertPressureForSeaLevel ( bmp_sensors [ bmp_idx ] . bmp_pressure ) ;
2018-11-04 15:55:12 +00:00
float bmp_temperature = ConvertTemp ( bmp_sensors [ bmp_idx ] . bmp_temperature ) ;
float bmp_pressure = ConvertPressure ( bmp_sensors [ bmp_idx ] . bmp_pressure ) ;
2018-10-29 14:46:03 +00:00
2018-12-21 15:17:06 +00:00
char name [ 10 ] ;
2019-03-08 18:24:02 +00:00
strlcpy ( name , bmp_sensors [ bmp_idx ] . bmp_name , sizeof ( name ) ) ;
2018-10-29 14:46:03 +00:00
if ( bmp_count > 1 ) {
2019-05-17 13:23:21 +01:00
snprintf_P ( name , sizeof ( name ) , PSTR ( " %s%c%02X " ) , name , IndexSeparator ( ) , bmp_sensors [ bmp_idx ] . bmp_address ) ; // BMXXXX-XX
2018-10-29 14:46:03 +00:00
}
2018-07-11 13:21:11 +01:00
2018-12-21 15:17:06 +00:00
char pressure [ 33 ] ;
2021-06-11 17:14:12 +01:00
dtostrfd ( bmp_pressure , Settings - > flag2 . pressure_resolution , pressure ) ;
2018-12-21 15:17:06 +00:00
char sea_pressure [ 33 ] ;
2021-06-11 17:14:12 +01:00
dtostrfd ( bmp_sealevel , Settings - > flag2 . pressure_resolution , sea_pressure ) ;
2020-03-18 10:23:00 +00:00
float bmp_humidity = ConvertHumidity ( bmp_sensors [ bmp_idx ] . bmp_humidity ) ;
2018-12-21 15:17:06 +00:00
char humidity [ 33 ] ;
2021-06-11 17:14:12 +01:00
dtostrfd ( bmp_humidity , Settings - > flag2 . humidity_resolution , humidity ) ;
2020-03-18 10:23:00 +00:00
float f_dewpoint = CalcTempHumToDew ( bmp_temperature , bmp_humidity ) ;
2020-03-17 10:10:39 +00:00
char dewpoint [ 33 ] ;
2021-06-11 17:14:12 +01:00
dtostrfd ( f_dewpoint , Settings - > flag2 . temperature_resolution , dewpoint ) ;
2022-01-19 16:05:39 +00:00
# ifdef USE_BME68X
2018-12-21 15:17:06 +00:00
char gas_resistance [ 33 ] ;
2018-10-29 14:46:03 +00:00
dtostrfd ( bmp_sensors [ bmp_idx ] . bmp_gas_resistance , 2 , gas_resistance ) ;
2022-01-19 16:05:39 +00:00
# endif // USE_BME68X
2017-11-04 15:36:51 +00:00
2018-10-29 14:46:03 +00:00
if ( json ) {
2020-03-17 10:10:39 +00:00
char json_humidity [ 80 ] ;
snprintf_P ( json_humidity , sizeof ( json_humidity ) , PSTR ( " , \" " D_JSON_HUMIDITY " \" :%s, \" " D_JSON_DEWPOINT " \" :%s " ) , humidity , dewpoint ) ;
2018-10-29 14:46:03 +00:00
char json_sealevel [ 40 ] ;
snprintf_P ( json_sealevel , sizeof ( json_sealevel ) , PSTR ( " , \" " D_JSON_PRESSUREATSEALEVEL " \" :%s " ) , sea_pressure ) ;
2022-01-19 16:05:39 +00:00
# ifdef USE_BME68X
2018-10-29 14:46:03 +00:00
char json_gas [ 40 ] ;
snprintf_P ( json_gas , sizeof ( json_gas ) , PSTR ( " , \" " D_JSON_GAS " \" :%s " ) , gas_resistance ) ;
2021-01-26 15:26:00 +00:00
ResponseAppend_P ( PSTR ( " , \" %s \" :{ \" " D_JSON_TEMPERATURE " \" :%*_f%s, \" " D_JSON_PRESSURE " \" :%s%s%s} " ) ,
2018-10-29 14:46:03 +00:00
name ,
2021-06-11 17:14:12 +01:00
Settings - > flag2 . temperature_resolution , & bmp_temperature ,
2018-10-29 14:46:03 +00:00
( bmp_sensors [ bmp_idx ] . bmp_model > = 2 ) ? json_humidity : " " ,
pressure ,
2021-06-11 17:14:12 +01:00
( Settings - > altitude ! = 0 ) ? json_sealevel : " " ,
2018-12-21 15:17:06 +00:00
( bmp_sensors [ bmp_idx ] . bmp_model > = 3 ) ? json_gas : " " ) ;
2017-12-06 16:14:41 +00:00
# else
2021-01-26 15:26:00 +00:00
ResponseAppend_P ( PSTR ( " , \" %s \" :{ \" " D_JSON_TEMPERATURE " \" :%*_f%s, \" " D_JSON_PRESSURE " \" :%s%s} " ) ,
2021-06-11 17:14:12 +01:00
name , Settings - > flag2 . temperature_resolution , & bmp_temperature , ( bmp_sensors [ bmp_idx ] . bmp_model > = 2 ) ? json_humidity : " " , pressure , ( Settings - > altitude ! = 0 ) ? json_sealevel : " " ) ;
2022-01-19 16:05:39 +00:00
# endif // USE_BME68X
2018-10-29 14:46:03 +00:00
2017-11-04 15:36:51 +00:00
# ifdef USE_DOMOTICZ
2020-10-29 12:37:09 +00:00
if ( ( 0 = = TasmotaGlobal . tele_period ) & & ( 0 = = bmp_idx ) ) { // We want the same first sensor to report to Domoticz in case a read is missed
2020-03-18 10:23:00 +00:00
DomoticzTempHumPressureSensor ( bmp_temperature , bmp_humidity , bmp_pressure ) ;
2022-01-19 16:05:39 +00:00
# ifdef USE_BME68X
2018-10-29 14:46:03 +00:00
if ( bmp_sensors [ bmp_idx ] . bmp_model > = 3 ) { DomoticzSensor ( DZ_AIRQUALITY , ( uint32_t ) bmp_sensors [ bmp_idx ] . bmp_gas_resistance ) ; }
2022-01-19 16:05:39 +00:00
# endif // USE_BME68X
2018-10-29 14:46:03 +00:00
}
2018-10-30 14:20:19 +00:00
# endif // USE_DOMOTICZ
2018-04-18 16:28:45 +01:00
# ifdef USE_KNX
2020-10-29 12:37:09 +00:00
if ( 0 = = TasmotaGlobal . tele_period ) {
2018-11-04 15:55:12 +00:00
KnxSensor ( KNX_TEMPERATURE , bmp_temperature ) ;
2020-03-18 10:23:00 +00:00
KnxSensor ( KNX_HUMIDITY , bmp_humidity ) ;
2018-10-29 14:46:03 +00:00
}
2018-04-18 16:28:45 +01:00
# endif // USE_KNX
2017-11-04 15:36:51 +00:00
# ifdef USE_WEBSERVER
2018-10-29 14:46:03 +00:00
} else {
2021-01-26 15:26:00 +00:00
WSContentSend_Temp ( name , bmp_temperature ) ;
2018-10-29 14:46:03 +00:00
if ( bmp_sensors [ bmp_idx ] . bmp_model > = 2 ) {
2019-03-19 16:31:43 +00:00
WSContentSend_PD ( HTTP_SNS_HUM , name , humidity ) ;
2020-03-17 10:10:39 +00:00
WSContentSend_PD ( HTTP_SNS_DEW , name , dewpoint , TempUnit ( ) ) ;
2018-10-29 14:46:03 +00:00
}
2019-03-19 16:31:43 +00:00
WSContentSend_PD ( HTTP_SNS_PRESSURE , name , pressure , PressureUnit ( ) . c_str ( ) ) ;
2021-06-11 17:14:12 +01:00
if ( Settings - > altitude ! = 0 ) {
2019-03-19 16:31:43 +00:00
WSContentSend_PD ( HTTP_SNS_SEAPRESSURE , name , sea_pressure , PressureUnit ( ) . c_str ( ) ) ;
2018-10-29 14:46:03 +00:00
}
2022-01-19 16:05:39 +00:00
# ifdef USE_BME68X
2018-10-29 14:46:03 +00:00
if ( bmp_sensors [ bmp_idx ] . bmp_model > = 3 ) {
2019-03-19 16:31:43 +00:00
WSContentSend_PD ( PSTR ( " {s}%s " D_GAS " {m}%s " D_UNIT_KILOOHM " {e} " ) , name , gas_resistance ) ;
2018-10-29 14:46:03 +00:00
}
2022-01-19 16:05:39 +00:00
# endif // USE_BME68X
2019-03-19 16:31:43 +00:00
2018-10-30 14:20:19 +00:00
# endif // USE_WEBSERVER
2018-10-29 14:46:03 +00:00
}
2017-10-08 15:51:05 +01:00
}
2017-01-28 13:41:01 +00:00
}
}
2017-11-03 17:07:25 +00:00
2020-01-02 20:38:18 +00:00
# ifdef USE_DEEPSLEEP
void BMP_EnterSleep ( void )
{
2020-09-14 11:26:32 +01:00
if ( DeepSleepEnabled ( ) ) {
for ( uint32_t bmp_idx = 0 ; bmp_idx < bmp_count ; bmp_idx + + ) {
switch ( bmp_sensors [ bmp_idx ] . bmp_type ) {
case BMP180_CHIPID :
case BMP280_CHIPID :
case BME280_CHIPID :
I2cWrite8 ( bmp_sensors [ bmp_idx ] . bmp_address , BMP_REGISTER_RESET , BMP_CMND_RESET ) ;
break ;
default :
break ;
}
2020-01-02 20:38:18 +00:00
}
}
}
# endif // USE_DEEPSLEEP
2017-11-03 17:07:25 +00:00
/*********************************************************************************************\
* Interface
\ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2022-11-11 09:44:56 +00:00
bool Xsns09 ( uint32_t function )
2017-11-03 17:07:25 +00:00
{
2019-11-04 09:38:05 +00:00
if ( ! I2cEnabled ( XI2C_10 ) ) { return false ; }
2019-11-03 16:54:39 +00:00
2019-01-28 13:08:33 +00:00
bool result = false ;
2017-11-03 17:07:25 +00:00
2019-11-11 16:32:44 +00:00
if ( FUNC_INIT = = function ) {
BmpDetect ( ) ;
}
else if ( bmp_count ) {
switch ( function ) {
case FUNC_EVERY_SECOND :
BmpRead ( ) ;
break ;
case FUNC_JSON_APPEND :
BmpShow ( 1 ) ;
break ;
2017-11-03 17:07:25 +00:00
# ifdef USE_WEBSERVER
2019-11-11 16:32:44 +00:00
case FUNC_WEB_SENSOR :
BmpShow ( 0 ) ;
break ;
2018-10-30 14:20:19 +00:00
# endif // USE_WEBSERVER
2020-01-02 20:38:18 +00:00
# ifdef USE_DEEPSLEEP
case FUNC_SAVE_BEFORE_RESTART :
BMP_EnterSleep ( ) ;
break ;
2020-01-02 20:51:15 +00:00
# endif // USE_DEEPSLEEP
2019-11-11 16:32:44 +00:00
}
2017-11-03 17:07:25 +00:00
}
return result ;
}
2018-10-30 14:20:19 +00:00
# endif // USE_BMP
# endif // USE_I2C