mirror of
https://github.com/esphome/esphome.git
synced 2024-11-10 01:07:45 +01:00
Add support for QMP6988 Pressure sensor (#3192)
This commit is contained in:
parent
59f67796dc
commit
99f5ed1461
6 changed files with 627 additions and 0 deletions
|
@ -151,6 +151,7 @@ esphome/components/preferences/* @esphome/core
|
||||||
esphome/components/psram/* @esphome/core
|
esphome/components/psram/* @esphome/core
|
||||||
esphome/components/pulse_meter/* @cstaahl @stevebaxter
|
esphome/components/pulse_meter/* @cstaahl @stevebaxter
|
||||||
esphome/components/pvvx_mithermometer/* @pasiz
|
esphome/components/pvvx_mithermometer/* @pasiz
|
||||||
|
esphome/components/qmp6988/* @andrewpc
|
||||||
esphome/components/qr_code/* @wjtje
|
esphome/components/qr_code/* @wjtje
|
||||||
esphome/components/radon_eye_ble/* @jeffeb3
|
esphome/components/radon_eye_ble/* @jeffeb3
|
||||||
esphome/components/radon_eye_rd200/* @jeffeb3
|
esphome/components/radon_eye_rd200/* @jeffeb3
|
||||||
|
|
1
esphome/components/qmp6988/__init__.py
Normal file
1
esphome/components/qmp6988/__init__.py
Normal file
|
@ -0,0 +1 @@
|
||||||
|
CODEOWNERS = ["@andrewpc"]
|
397
esphome/components/qmp6988/qmp6988.cpp
Normal file
397
esphome/components/qmp6988/qmp6988.cpp
Normal file
|
@ -0,0 +1,397 @@
|
||||||
|
#include "qmp6988.h"
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace qmp6988 {
|
||||||
|
|
||||||
|
static const uint8_t QMP6988_CHIP_ID = 0x5C;
|
||||||
|
|
||||||
|
static const uint8_t QMP6988_CHIP_ID_REG = 0xD1; /* Chip ID confirmation Register */
|
||||||
|
static const uint8_t QMP6988_RESET_REG = 0xE0; /* Device reset register */
|
||||||
|
static const uint8_t QMP6988_DEVICE_STAT_REG = 0xF3; /* Device state register */
|
||||||
|
static const uint8_t QMP6988_CTRLMEAS_REG = 0xF4; /* Measurement Condition Control Register */
|
||||||
|
/* data */
|
||||||
|
static const uint8_t QMP6988_PRESSURE_MSB_REG = 0xF7; /* Pressure MSB Register */
|
||||||
|
static const uint8_t QMP6988_TEMPERATURE_MSB_REG = 0xFA; /* Temperature MSB Reg */
|
||||||
|
|
||||||
|
/* compensation calculation */
|
||||||
|
static const uint8_t QMP6988_CALIBRATION_DATA_START = 0xA0; /* QMP6988 compensation coefficients */
|
||||||
|
static const uint8_t QMP6988_CALIBRATION_DATA_LENGTH = 25;
|
||||||
|
|
||||||
|
static const uint8_t SHIFT_RIGHT_4_POSITION = 4;
|
||||||
|
static const uint8_t SHIFT_LEFT_2_POSITION = 2;
|
||||||
|
static const uint8_t SHIFT_LEFT_4_POSITION = 4;
|
||||||
|
static const uint8_t SHIFT_LEFT_5_POSITION = 5;
|
||||||
|
static const uint8_t SHIFT_LEFT_8_POSITION = 8;
|
||||||
|
static const uint8_t SHIFT_LEFT_12_POSITION = 12;
|
||||||
|
static const uint8_t SHIFT_LEFT_16_POSITION = 16;
|
||||||
|
|
||||||
|
/* power mode */
|
||||||
|
static const uint8_t QMP6988_SLEEP_MODE = 0x00;
|
||||||
|
static const uint8_t QMP6988_FORCED_MODE = 0x01;
|
||||||
|
static const uint8_t QMP6988_NORMAL_MODE = 0x03;
|
||||||
|
|
||||||
|
static const uint8_t QMP6988_CTRLMEAS_REG_MODE_POS = 0;
|
||||||
|
static const uint8_t QMP6988_CTRLMEAS_REG_MODE_MSK = 0x03;
|
||||||
|
static const uint8_t QMP6988_CTRLMEAS_REG_MODE_LEN = 2;
|
||||||
|
|
||||||
|
static const uint8_t QMP6988_CTRLMEAS_REG_OSRST_POS = 5;
|
||||||
|
static const uint8_t QMP6988_CTRLMEAS_REG_OSRST_MSK = 0xE0;
|
||||||
|
static const uint8_t QMP6988_CTRLMEAS_REG_OSRST_LEN = 3;
|
||||||
|
|
||||||
|
static const uint8_t QMP6988_CTRLMEAS_REG_OSRSP_POS = 2;
|
||||||
|
static const uint8_t QMP6988_CTRLMEAS_REG_OSRSP_MSK = 0x1C;
|
||||||
|
static const uint8_t QMP6988_CTRLMEAS_REG_OSRSP_LEN = 3;
|
||||||
|
|
||||||
|
static const uint8_t QMP6988_CONFIG_REG = 0xF1; /*IIR filter co-efficient setting Register*/
|
||||||
|
static const uint8_t QMP6988_CONFIG_REG_FILTER_POS = 0;
|
||||||
|
static const uint8_t QMP6988_CONFIG_REG_FILTER_MSK = 0x07;
|
||||||
|
static const uint8_t QMP6988_CONFIG_REG_FILTER_LEN = 3;
|
||||||
|
|
||||||
|
static const uint32_t SUBTRACTOR = 8388608;
|
||||||
|
|
||||||
|
static const char *const TAG = "qmp6988";
|
||||||
|
|
||||||
|
static const char *oversampling_to_str(QMP6988Oversampling oversampling) {
|
||||||
|
switch (oversampling) {
|
||||||
|
case QMP6988_OVERSAMPLING_SKIPPED:
|
||||||
|
return "None";
|
||||||
|
case QMP6988_OVERSAMPLING_1X:
|
||||||
|
return "1x";
|
||||||
|
case QMP6988_OVERSAMPLING_2X:
|
||||||
|
return "2x";
|
||||||
|
case QMP6988_OVERSAMPLING_4X:
|
||||||
|
return "4x";
|
||||||
|
case QMP6988_OVERSAMPLING_8X:
|
||||||
|
return "8x";
|
||||||
|
case QMP6988_OVERSAMPLING_16X:
|
||||||
|
return "16x";
|
||||||
|
case QMP6988_OVERSAMPLING_32X:
|
||||||
|
return "32x";
|
||||||
|
case QMP6988_OVERSAMPLING_64X:
|
||||||
|
return "64x";
|
||||||
|
default:
|
||||||
|
return "UNKNOWN";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *iir_filter_to_str(QMP6988IIRFilter filter) {
|
||||||
|
switch (filter) {
|
||||||
|
case QMP6988_IIR_FILTER_OFF:
|
||||||
|
return "OFF";
|
||||||
|
case QMP6988_IIR_FILTER_2X:
|
||||||
|
return "2x";
|
||||||
|
case QMP6988_IIR_FILTER_4X:
|
||||||
|
return "4x";
|
||||||
|
case QMP6988_IIR_FILTER_8X:
|
||||||
|
return "8x";
|
||||||
|
case QMP6988_IIR_FILTER_16X:
|
||||||
|
return "16x";
|
||||||
|
case QMP6988_IIR_FILTER_32X:
|
||||||
|
return "32x";
|
||||||
|
default:
|
||||||
|
return "UNKNOWN";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QMP6988Component::device_check_() {
|
||||||
|
uint8_t ret = 0;
|
||||||
|
|
||||||
|
ret = this->read_register(QMP6988_CHIP_ID_REG, &(qmp6988_data_.chip_id), 1);
|
||||||
|
if (ret != i2c::ERROR_OK) {
|
||||||
|
ESP_LOGE(TAG, "%s: read chip ID (0xD1) failed", __func__);
|
||||||
|
}
|
||||||
|
ESP_LOGD(TAG, "qmp6988 read chip id = 0x%x", qmp6988_data_.chip_id);
|
||||||
|
|
||||||
|
return qmp6988_data_.chip_id == QMP6988_CHIP_ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QMP6988Component::get_calibration_data_() {
|
||||||
|
uint8_t status = 0;
|
||||||
|
// BITFIELDS temp_COE;
|
||||||
|
uint8_t a_data_uint8_tr[QMP6988_CALIBRATION_DATA_LENGTH] = {0};
|
||||||
|
int len;
|
||||||
|
|
||||||
|
for (len = 0; len < QMP6988_CALIBRATION_DATA_LENGTH; len += 1) {
|
||||||
|
status = this->read_register(QMP6988_CALIBRATION_DATA_START + len, &a_data_uint8_tr[len], 1);
|
||||||
|
if (status != i2c::ERROR_OK) {
|
||||||
|
ESP_LOGE(TAG, "qmp6988 read calibration data (0xA0) error!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
qmp6988_data_.qmp6988_cali.COE_a0 =
|
||||||
|
(QMP6988_S32_t)(((a_data_uint8_tr[18] << SHIFT_LEFT_12_POSITION) |
|
||||||
|
(a_data_uint8_tr[19] << SHIFT_LEFT_4_POSITION) | (a_data_uint8_tr[24] & 0x0f))
|
||||||
|
<< 12);
|
||||||
|
qmp6988_data_.qmp6988_cali.COE_a0 = qmp6988_data_.qmp6988_cali.COE_a0 >> 12;
|
||||||
|
|
||||||
|
qmp6988_data_.qmp6988_cali.COE_a1 =
|
||||||
|
(QMP6988_S16_t)(((a_data_uint8_tr[20]) << SHIFT_LEFT_8_POSITION) | a_data_uint8_tr[21]);
|
||||||
|
qmp6988_data_.qmp6988_cali.COE_a2 =
|
||||||
|
(QMP6988_S16_t)(((a_data_uint8_tr[22]) << SHIFT_LEFT_8_POSITION) | a_data_uint8_tr[23]);
|
||||||
|
|
||||||
|
qmp6988_data_.qmp6988_cali.COE_b00 =
|
||||||
|
(QMP6988_S32_t)(((a_data_uint8_tr[0] << SHIFT_LEFT_12_POSITION) | (a_data_uint8_tr[1] << SHIFT_LEFT_4_POSITION) |
|
||||||
|
((a_data_uint8_tr[24] & 0xf0) >> SHIFT_RIGHT_4_POSITION))
|
||||||
|
<< 12);
|
||||||
|
qmp6988_data_.qmp6988_cali.COE_b00 = qmp6988_data_.qmp6988_cali.COE_b00 >> 12;
|
||||||
|
|
||||||
|
qmp6988_data_.qmp6988_cali.COE_bt1 =
|
||||||
|
(QMP6988_S16_t)(((a_data_uint8_tr[2]) << SHIFT_LEFT_8_POSITION) | a_data_uint8_tr[3]);
|
||||||
|
qmp6988_data_.qmp6988_cali.COE_bt2 =
|
||||||
|
(QMP6988_S16_t)(((a_data_uint8_tr[4]) << SHIFT_LEFT_8_POSITION) | a_data_uint8_tr[5]);
|
||||||
|
qmp6988_data_.qmp6988_cali.COE_bp1 =
|
||||||
|
(QMP6988_S16_t)(((a_data_uint8_tr[6]) << SHIFT_LEFT_8_POSITION) | a_data_uint8_tr[7]);
|
||||||
|
qmp6988_data_.qmp6988_cali.COE_b11 =
|
||||||
|
(QMP6988_S16_t)(((a_data_uint8_tr[8]) << SHIFT_LEFT_8_POSITION) | a_data_uint8_tr[9]);
|
||||||
|
qmp6988_data_.qmp6988_cali.COE_bp2 =
|
||||||
|
(QMP6988_S16_t)(((a_data_uint8_tr[10]) << SHIFT_LEFT_8_POSITION) | a_data_uint8_tr[11]);
|
||||||
|
qmp6988_data_.qmp6988_cali.COE_b12 =
|
||||||
|
(QMP6988_S16_t)(((a_data_uint8_tr[12]) << SHIFT_LEFT_8_POSITION) | a_data_uint8_tr[13]);
|
||||||
|
qmp6988_data_.qmp6988_cali.COE_b21 =
|
||||||
|
(QMP6988_S16_t)(((a_data_uint8_tr[14]) << SHIFT_LEFT_8_POSITION) | a_data_uint8_tr[15]);
|
||||||
|
qmp6988_data_.qmp6988_cali.COE_bp3 =
|
||||||
|
(QMP6988_S16_t)(((a_data_uint8_tr[16]) << SHIFT_LEFT_8_POSITION) | a_data_uint8_tr[17]);
|
||||||
|
|
||||||
|
ESP_LOGV(TAG, "<-----------calibration data-------------->\r\n");
|
||||||
|
ESP_LOGV(TAG, "COE_a0[%d] COE_a1[%d] COE_a2[%d] COE_b00[%d]\r\n", qmp6988_data_.qmp6988_cali.COE_a0,
|
||||||
|
qmp6988_data_.qmp6988_cali.COE_a1, qmp6988_data_.qmp6988_cali.COE_a2, qmp6988_data_.qmp6988_cali.COE_b00);
|
||||||
|
ESP_LOGV(TAG, "COE_bt1[%d] COE_bt2[%d] COE_bp1[%d] COE_b11[%d]\r\n", qmp6988_data_.qmp6988_cali.COE_bt1,
|
||||||
|
qmp6988_data_.qmp6988_cali.COE_bt2, qmp6988_data_.qmp6988_cali.COE_bp1, qmp6988_data_.qmp6988_cali.COE_b11);
|
||||||
|
ESP_LOGV(TAG, "COE_bp2[%d] COE_b12[%d] COE_b21[%d] COE_bp3[%d]\r\n", qmp6988_data_.qmp6988_cali.COE_bp2,
|
||||||
|
qmp6988_data_.qmp6988_cali.COE_b12, qmp6988_data_.qmp6988_cali.COE_b21, qmp6988_data_.qmp6988_cali.COE_bp3);
|
||||||
|
ESP_LOGV(TAG, "<-----------calibration data-------------->\r\n");
|
||||||
|
|
||||||
|
qmp6988_data_.ik.a0 = qmp6988_data_.qmp6988_cali.COE_a0; // 20Q4
|
||||||
|
qmp6988_data_.ik.b00 = qmp6988_data_.qmp6988_cali.COE_b00; // 20Q4
|
||||||
|
|
||||||
|
qmp6988_data_.ik.a1 = 3608L * (QMP6988_S32_t) qmp6988_data_.qmp6988_cali.COE_a1 - 1731677965L; // 31Q23
|
||||||
|
qmp6988_data_.ik.a2 = 16889L * (QMP6988_S32_t) qmp6988_data_.qmp6988_cali.COE_a2 - 87619360L; // 30Q47
|
||||||
|
|
||||||
|
qmp6988_data_.ik.bt1 = 2982L * (QMP6988_S64_t) qmp6988_data_.qmp6988_cali.COE_bt1 + 107370906L; // 28Q15
|
||||||
|
qmp6988_data_.ik.bt2 = 329854L * (QMP6988_S64_t) qmp6988_data_.qmp6988_cali.COE_bt2 + 108083093L; // 34Q38
|
||||||
|
qmp6988_data_.ik.bp1 = 19923L * (QMP6988_S64_t) qmp6988_data_.qmp6988_cali.COE_bp1 + 1133836764L; // 31Q20
|
||||||
|
qmp6988_data_.ik.b11 = 2406L * (QMP6988_S64_t) qmp6988_data_.qmp6988_cali.COE_b11 + 118215883L; // 28Q34
|
||||||
|
qmp6988_data_.ik.bp2 = 3079L * (QMP6988_S64_t) qmp6988_data_.qmp6988_cali.COE_bp2 - 181579595L; // 29Q43
|
||||||
|
qmp6988_data_.ik.b12 = 6846L * (QMP6988_S64_t) qmp6988_data_.qmp6988_cali.COE_b12 + 85590281L; // 29Q53
|
||||||
|
qmp6988_data_.ik.b21 = 13836L * (QMP6988_S64_t) qmp6988_data_.qmp6988_cali.COE_b21 + 79333336L; // 29Q60
|
||||||
|
qmp6988_data_.ik.bp3 = 2915L * (QMP6988_S64_t) qmp6988_data_.qmp6988_cali.COE_bp3 + 157155561L; // 28Q65
|
||||||
|
ESP_LOGV(TAG, "<----------- int calibration data -------------->\r\n");
|
||||||
|
ESP_LOGV(TAG, "a0[%d] a1[%d] a2[%d] b00[%d]\r\n", qmp6988_data_.ik.a0, qmp6988_data_.ik.a1, qmp6988_data_.ik.a2,
|
||||||
|
qmp6988_data_.ik.b00);
|
||||||
|
ESP_LOGV(TAG, "bt1[%lld] bt2[%lld] bp1[%lld] b11[%lld]\r\n", qmp6988_data_.ik.bt1, qmp6988_data_.ik.bt2,
|
||||||
|
qmp6988_data_.ik.bp1, qmp6988_data_.ik.b11);
|
||||||
|
ESP_LOGV(TAG, "bp2[%lld] b12[%lld] b21[%lld] bp3[%lld]\r\n", qmp6988_data_.ik.bp2, qmp6988_data_.ik.b12,
|
||||||
|
qmp6988_data_.ik.b21, qmp6988_data_.ik.bp3);
|
||||||
|
ESP_LOGV(TAG, "<----------- int calibration data -------------->\r\n");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
QMP6988_S16_t QMP6988Component::get_compensated_temperature_(qmp6988_ik_data_t *ik, QMP6988_S32_t dt) {
|
||||||
|
QMP6988_S16_t ret;
|
||||||
|
QMP6988_S64_t wk1, wk2;
|
||||||
|
|
||||||
|
// wk1: 60Q4 // bit size
|
||||||
|
wk1 = ((QMP6988_S64_t) ik->a1 * (QMP6988_S64_t) dt); // 31Q23+24-1=54 (54Q23)
|
||||||
|
wk2 = ((QMP6988_S64_t) ik->a2 * (QMP6988_S64_t) dt) >> 14; // 30Q47+24-1=53 (39Q33)
|
||||||
|
wk2 = (wk2 * (QMP6988_S64_t) dt) >> 10; // 39Q33+24-1=62 (52Q23)
|
||||||
|
wk2 = ((wk1 + wk2) / 32767) >> 19; // 54,52->55Q23 (20Q04)
|
||||||
|
ret = (QMP6988_S16_t)((ik->a0 + wk2) >> 4); // 21Q4 -> 17Q0
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
QMP6988_S32_t QMP6988Component::get_compensated_pressure_(qmp6988_ik_data_t *ik, QMP6988_S32_t dp, QMP6988_S16_t tx) {
|
||||||
|
QMP6988_S32_t ret;
|
||||||
|
QMP6988_S64_t wk1, wk2, wk3;
|
||||||
|
|
||||||
|
// wk1 = 48Q16 // bit size
|
||||||
|
wk1 = ((QMP6988_S64_t) ik->bt1 * (QMP6988_S64_t) tx); // 28Q15+16-1=43 (43Q15)
|
||||||
|
wk2 = ((QMP6988_S64_t) ik->bp1 * (QMP6988_S64_t) dp) >> 5; // 31Q20+24-1=54 (49Q15)
|
||||||
|
wk1 += wk2; // 43,49->50Q15
|
||||||
|
wk2 = ((QMP6988_S64_t) ik->bt2 * (QMP6988_S64_t) tx) >> 1; // 34Q38+16-1=49 (48Q37)
|
||||||
|
wk2 = (wk2 * (QMP6988_S64_t) tx) >> 8; // 48Q37+16-1=63 (55Q29)
|
||||||
|
wk3 = wk2; // 55Q29
|
||||||
|
wk2 = ((QMP6988_S64_t) ik->b11 * (QMP6988_S64_t) tx) >> 4; // 28Q34+16-1=43 (39Q30)
|
||||||
|
wk2 = (wk2 * (QMP6988_S64_t) dp) >> 1; // 39Q30+24-1=62 (61Q29)
|
||||||
|
wk3 += wk2; // 55,61->62Q29
|
||||||
|
wk2 = ((QMP6988_S64_t) ik->bp2 * (QMP6988_S64_t) dp) >> 13; // 29Q43+24-1=52 (39Q30)
|
||||||
|
wk2 = (wk2 * (QMP6988_S64_t) dp) >> 1; // 39Q30+24-1=62 (61Q29)
|
||||||
|
wk3 += wk2; // 62,61->63Q29
|
||||||
|
wk1 += wk3 >> 14; // Q29 >> 14 -> Q15
|
||||||
|
wk2 = ((QMP6988_S64_t) ik->b12 * (QMP6988_S64_t) tx); // 29Q53+16-1=45 (45Q53)
|
||||||
|
wk2 = (wk2 * (QMP6988_S64_t) tx) >> 22; // 45Q53+16-1=61 (39Q31)
|
||||||
|
wk2 = (wk2 * (QMP6988_S64_t) dp) >> 1; // 39Q31+24-1=62 (61Q30)
|
||||||
|
wk3 = wk2; // 61Q30
|
||||||
|
wk2 = ((QMP6988_S64_t) ik->b21 * (QMP6988_S64_t) tx) >> 6; // 29Q60+16-1=45 (39Q54)
|
||||||
|
wk2 = (wk2 * (QMP6988_S64_t) dp) >> 23; // 39Q54+24-1=62 (39Q31)
|
||||||
|
wk2 = (wk2 * (QMP6988_S64_t) dp) >> 1; // 39Q31+24-1=62 (61Q20)
|
||||||
|
wk3 += wk2; // 61,61->62Q30
|
||||||
|
wk2 = ((QMP6988_S64_t) ik->bp3 * (QMP6988_S64_t) dp) >> 12; // 28Q65+24-1=51 (39Q53)
|
||||||
|
wk2 = (wk2 * (QMP6988_S64_t) dp) >> 23; // 39Q53+24-1=62 (39Q30)
|
||||||
|
wk2 = (wk2 * (QMP6988_S64_t) dp); // 39Q30+24-1=62 (62Q30)
|
||||||
|
wk3 += wk2; // 62,62->63Q30
|
||||||
|
wk1 += wk3 >> 15; // Q30 >> 15 = Q15
|
||||||
|
wk1 /= 32767L;
|
||||||
|
wk1 >>= 11; // Q15 >> 7 = Q4
|
||||||
|
wk1 += ik->b00; // Q4 + 20Q4
|
||||||
|
// wk1 >>= 4; // 28Q4 -> 24Q0
|
||||||
|
ret = (QMP6988_S32_t) wk1;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QMP6988Component::software_reset_() {
|
||||||
|
uint8_t ret = 0;
|
||||||
|
|
||||||
|
ret = this->write_byte(QMP6988_RESET_REG, 0xe6);
|
||||||
|
if (ret != i2c::ERROR_OK) {
|
||||||
|
ESP_LOGE(TAG, "Software Reset (0xe6) failed");
|
||||||
|
}
|
||||||
|
delay(10);
|
||||||
|
|
||||||
|
this->write_byte(QMP6988_RESET_REG, 0x00);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QMP6988Component::set_power_mode_(uint8_t power_mode) {
|
||||||
|
uint8_t data;
|
||||||
|
|
||||||
|
ESP_LOGD(TAG, "Setting Power mode to: %d", power_mode);
|
||||||
|
|
||||||
|
qmp6988_data_.power_mode = power_mode;
|
||||||
|
this->read_register(QMP6988_CTRLMEAS_REG, &data, 1);
|
||||||
|
data = data & 0xfc;
|
||||||
|
if (power_mode == QMP6988_SLEEP_MODE) {
|
||||||
|
data |= 0x00;
|
||||||
|
} else if (power_mode == QMP6988_FORCED_MODE) {
|
||||||
|
data |= 0x01;
|
||||||
|
} else if (power_mode == QMP6988_NORMAL_MODE) {
|
||||||
|
data |= 0x03;
|
||||||
|
}
|
||||||
|
this->write_byte(QMP6988_CTRLMEAS_REG, data);
|
||||||
|
|
||||||
|
ESP_LOGD(TAG, "Set Power mode 0xf4=0x%x \r\n", data);
|
||||||
|
|
||||||
|
delay(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QMP6988Component::write_filter_(unsigned char filter) {
|
||||||
|
uint8_t data;
|
||||||
|
|
||||||
|
data = (filter & 0x03);
|
||||||
|
this->write_byte(QMP6988_CONFIG_REG, data);
|
||||||
|
delay(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QMP6988Component::write_oversampling_pressure_(unsigned char oversampling_p) {
|
||||||
|
uint8_t data;
|
||||||
|
|
||||||
|
this->read_register(QMP6988_CTRLMEAS_REG, &data, 1);
|
||||||
|
data &= 0xe3;
|
||||||
|
data |= (oversampling_p << 2);
|
||||||
|
this->write_byte(QMP6988_CTRLMEAS_REG, data);
|
||||||
|
delay(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QMP6988Component::write_oversampling_temperature_(unsigned char oversampling_t) {
|
||||||
|
uint8_t data;
|
||||||
|
|
||||||
|
this->read_register(QMP6988_CTRLMEAS_REG, &data, 1);
|
||||||
|
data &= 0x1f;
|
||||||
|
data |= (oversampling_t << 5);
|
||||||
|
this->write_byte(QMP6988_CTRLMEAS_REG, data);
|
||||||
|
delay(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QMP6988Component::set_temperature_oversampling(QMP6988Oversampling oversampling_t) {
|
||||||
|
this->temperature_oversampling_ = oversampling_t;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QMP6988Component::set_pressure_oversampling(QMP6988Oversampling oversampling_p) {
|
||||||
|
this->pressure_oversampling_ = oversampling_p;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QMP6988Component::set_iir_filter(QMP6988IIRFilter iirfilter) { this->iir_filter_ = iirfilter; }
|
||||||
|
|
||||||
|
void QMP6988Component::calculate_altitude_(float pressure, float temp) {
|
||||||
|
float altitude;
|
||||||
|
altitude = (pow((101325 / pressure), 1 / 5.257) - 1) * (temp + 273.15) / 0.0065;
|
||||||
|
this->qmp6988_data_.altitude = altitude;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QMP6988Component::calculate_pressure_() {
|
||||||
|
uint8_t err = 0;
|
||||||
|
QMP6988_U32_t p_read, t_read;
|
||||||
|
QMP6988_S32_t p_raw, t_raw;
|
||||||
|
uint8_t a_data_uint8_tr[6] = {0};
|
||||||
|
QMP6988_S32_t t_int, p_int;
|
||||||
|
this->qmp6988_data_.temperature = 0;
|
||||||
|
this->qmp6988_data_.pressure = 0;
|
||||||
|
|
||||||
|
err = this->read_register(QMP6988_PRESSURE_MSB_REG, a_data_uint8_tr, 6);
|
||||||
|
if (err != i2c::ERROR_OK) {
|
||||||
|
ESP_LOGE(TAG, "Error reading raw pressure/temp values");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
p_read = (QMP6988_U32_t)((((QMP6988_U32_t)(a_data_uint8_tr[0])) << SHIFT_LEFT_16_POSITION) |
|
||||||
|
(((QMP6988_U16_t)(a_data_uint8_tr[1])) << SHIFT_LEFT_8_POSITION) | (a_data_uint8_tr[2]));
|
||||||
|
p_raw = (QMP6988_S32_t)(p_read - SUBTRACTOR);
|
||||||
|
|
||||||
|
t_read = (QMP6988_U32_t)((((QMP6988_U32_t)(a_data_uint8_tr[3])) << SHIFT_LEFT_16_POSITION) |
|
||||||
|
(((QMP6988_U16_t)(a_data_uint8_tr[4])) << SHIFT_LEFT_8_POSITION) | (a_data_uint8_tr[5]));
|
||||||
|
t_raw = (QMP6988_S32_t)(t_read - SUBTRACTOR);
|
||||||
|
|
||||||
|
t_int = this->get_compensated_temperature_(&(qmp6988_data_.ik), t_raw);
|
||||||
|
p_int = this->get_compensated_pressure_(&(qmp6988_data_.ik), p_raw, t_int);
|
||||||
|
|
||||||
|
this->qmp6988_data_.temperature = (float) t_int / 256.0f;
|
||||||
|
this->qmp6988_data_.pressure = (float) p_int / 16.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QMP6988Component::setup() {
|
||||||
|
ESP_LOGCONFIG(TAG, "Setting up QMP6988");
|
||||||
|
|
||||||
|
bool ret;
|
||||||
|
ret = this->device_check_();
|
||||||
|
if (!ret) {
|
||||||
|
ESP_LOGCONFIG(TAG, "Setup failed - device not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
this->software_reset_();
|
||||||
|
this->get_calibration_data_();
|
||||||
|
this->set_power_mode_(QMP6988_NORMAL_MODE);
|
||||||
|
this->write_filter_(iir_filter_);
|
||||||
|
this->write_oversampling_pressure_(this->pressure_oversampling_);
|
||||||
|
this->write_oversampling_temperature_(this->temperature_oversampling_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QMP6988Component::dump_config() {
|
||||||
|
ESP_LOGCONFIG(TAG, "QMP6988:");
|
||||||
|
LOG_I2C_DEVICE(this);
|
||||||
|
if (this->is_failed()) {
|
||||||
|
ESP_LOGE(TAG, "Communication with QMP6988 failed!");
|
||||||
|
}
|
||||||
|
LOG_UPDATE_INTERVAL(this);
|
||||||
|
|
||||||
|
LOG_SENSOR(" ", "Temperature", this->temperature_sensor_);
|
||||||
|
ESP_LOGCONFIG(TAG, " Temperature Oversampling: %s", oversampling_to_str(this->temperature_oversampling_));
|
||||||
|
LOG_SENSOR(" ", "Pressure", this->pressure_sensor_);
|
||||||
|
ESP_LOGCONFIG(TAG, " Pressure Oversampling: %s", oversampling_to_str(this->pressure_oversampling_));
|
||||||
|
ESP_LOGCONFIG(TAG, " IIR Filter: %s", iir_filter_to_str(this->iir_filter_));
|
||||||
|
}
|
||||||
|
|
||||||
|
float QMP6988Component::get_setup_priority() const { return setup_priority::DATA; }
|
||||||
|
|
||||||
|
void QMP6988Component::update() {
|
||||||
|
this->calculate_pressure_();
|
||||||
|
float pressurehectopascals = this->qmp6988_data_.pressure / 100;
|
||||||
|
float temperature = this->qmp6988_data_.temperature;
|
||||||
|
|
||||||
|
ESP_LOGD(TAG, "Temperature=%.2f°C, Pressure=%.2fhPa", temperature, pressurehectopascals);
|
||||||
|
if (this->temperature_sensor_ != nullptr)
|
||||||
|
this->temperature_sensor_->publish_state(temperature);
|
||||||
|
if (this->pressure_sensor_ != nullptr)
|
||||||
|
this->pressure_sensor_->publish_state(pressurehectopascals);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace qmp6988
|
||||||
|
} // namespace esphome
|
116
esphome/components/qmp6988/qmp6988.h
Normal file
116
esphome/components/qmp6988/qmp6988.h
Normal file
|
@ -0,0 +1,116 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "esphome/core/log.h"
|
||||||
|
#include "esphome/core/component.h"
|
||||||
|
#include "esphome/core/hal.h"
|
||||||
|
#include "esphome/core/helpers.h"
|
||||||
|
#include "esphome/components/sensor/sensor.h"
|
||||||
|
#include "esphome/components/i2c/i2c.h"
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace qmp6988 {
|
||||||
|
|
||||||
|
#define QMP6988_U16_t unsigned short
|
||||||
|
#define QMP6988_S16_t short
|
||||||
|
#define QMP6988_U32_t unsigned int
|
||||||
|
#define QMP6988_S32_t int
|
||||||
|
#define QMP6988_U64_t unsigned long long
|
||||||
|
#define QMP6988_S64_t long long
|
||||||
|
|
||||||
|
/* oversampling */
|
||||||
|
enum QMP6988Oversampling {
|
||||||
|
QMP6988_OVERSAMPLING_SKIPPED = 0x00,
|
||||||
|
QMP6988_OVERSAMPLING_1X = 0x01,
|
||||||
|
QMP6988_OVERSAMPLING_2X = 0x02,
|
||||||
|
QMP6988_OVERSAMPLING_4X = 0x03,
|
||||||
|
QMP6988_OVERSAMPLING_8X = 0x04,
|
||||||
|
QMP6988_OVERSAMPLING_16X = 0x05,
|
||||||
|
QMP6988_OVERSAMPLING_32X = 0x06,
|
||||||
|
QMP6988_OVERSAMPLING_64X = 0x07,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* filter */
|
||||||
|
enum QMP6988IIRFilter {
|
||||||
|
QMP6988_IIR_FILTER_OFF = 0x00,
|
||||||
|
QMP6988_IIR_FILTER_2X = 0x01,
|
||||||
|
QMP6988_IIR_FILTER_4X = 0x02,
|
||||||
|
QMP6988_IIR_FILTER_8X = 0x03,
|
||||||
|
QMP6988_IIR_FILTER_16X = 0x04,
|
||||||
|
QMP6988_IIR_FILTER_32X = 0x05,
|
||||||
|
};
|
||||||
|
|
||||||
|
using qmp6988_cali_data_t = struct Qmp6988CaliData {
|
||||||
|
QMP6988_S32_t COE_a0;
|
||||||
|
QMP6988_S16_t COE_a1;
|
||||||
|
QMP6988_S16_t COE_a2;
|
||||||
|
QMP6988_S32_t COE_b00;
|
||||||
|
QMP6988_S16_t COE_bt1;
|
||||||
|
QMP6988_S16_t COE_bt2;
|
||||||
|
QMP6988_S16_t COE_bp1;
|
||||||
|
QMP6988_S16_t COE_b11;
|
||||||
|
QMP6988_S16_t COE_bp2;
|
||||||
|
QMP6988_S16_t COE_b12;
|
||||||
|
QMP6988_S16_t COE_b21;
|
||||||
|
QMP6988_S16_t COE_bp3;
|
||||||
|
};
|
||||||
|
|
||||||
|
using qmp6988_fk_data_t = struct Qmp6988FkData {
|
||||||
|
float a0, b00;
|
||||||
|
float a1, a2, bt1, bt2, bp1, b11, bp2, b12, b21, bp3;
|
||||||
|
};
|
||||||
|
|
||||||
|
using qmp6988_ik_data_t = struct Qmp6988IkData {
|
||||||
|
QMP6988_S32_t a0, b00;
|
||||||
|
QMP6988_S32_t a1, a2;
|
||||||
|
QMP6988_S64_t bt1, bt2, bp1, b11, bp2, b12, b21, bp3;
|
||||||
|
};
|
||||||
|
|
||||||
|
using qmp6988_data_t = struct Qmp6988Data {
|
||||||
|
uint8_t chip_id;
|
||||||
|
uint8_t power_mode;
|
||||||
|
float temperature;
|
||||||
|
float pressure;
|
||||||
|
float altitude;
|
||||||
|
qmp6988_cali_data_t qmp6988_cali;
|
||||||
|
qmp6988_ik_data_t ik;
|
||||||
|
};
|
||||||
|
|
||||||
|
class QMP6988Component : public PollingComponent, public i2c::I2CDevice {
|
||||||
|
public:
|
||||||
|
void set_temperature_sensor(sensor::Sensor *temperature_sensor) { temperature_sensor_ = temperature_sensor; }
|
||||||
|
void set_pressure_sensor(sensor::Sensor *pressure_sensor) { pressure_sensor_ = pressure_sensor; }
|
||||||
|
|
||||||
|
void setup() override;
|
||||||
|
void dump_config() override;
|
||||||
|
float get_setup_priority() const override;
|
||||||
|
void update() override;
|
||||||
|
|
||||||
|
void set_iir_filter(QMP6988IIRFilter iirfilter);
|
||||||
|
void set_temperature_oversampling(QMP6988Oversampling oversampling_t);
|
||||||
|
void set_pressure_oversampling(QMP6988Oversampling oversampling_p);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
qmp6988_data_t qmp6988_data_;
|
||||||
|
sensor::Sensor *temperature_sensor_;
|
||||||
|
sensor::Sensor *pressure_sensor_;
|
||||||
|
|
||||||
|
QMP6988Oversampling temperature_oversampling_{QMP6988_OVERSAMPLING_16X};
|
||||||
|
QMP6988Oversampling pressure_oversampling_{QMP6988_OVERSAMPLING_16X};
|
||||||
|
QMP6988IIRFilter iir_filter_{QMP6988_IIR_FILTER_OFF};
|
||||||
|
|
||||||
|
void software_reset_();
|
||||||
|
bool get_calibration_data_();
|
||||||
|
bool device_check_();
|
||||||
|
void set_power_mode_(uint8_t power_mode);
|
||||||
|
void write_oversampling_temperature_(unsigned char oversampling_t);
|
||||||
|
void write_oversampling_pressure_(unsigned char oversampling_p);
|
||||||
|
void write_filter_(unsigned char filter);
|
||||||
|
void calculate_pressure_();
|
||||||
|
void calculate_altitude_(float pressure, float temp);
|
||||||
|
|
||||||
|
QMP6988_S32_t get_compensated_pressure_(qmp6988_ik_data_t *ik, QMP6988_S32_t dp, QMP6988_S16_t tx);
|
||||||
|
QMP6988_S16_t get_compensated_temperature_(qmp6988_ik_data_t *ik, QMP6988_S32_t dt);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace qmp6988
|
||||||
|
} // namespace esphome
|
101
esphome/components/qmp6988/sensor.py
Normal file
101
esphome/components/qmp6988/sensor.py
Normal file
|
@ -0,0 +1,101 @@
|
||||||
|
import esphome.codegen as cg
|
||||||
|
import esphome.config_validation as cv
|
||||||
|
from esphome.components import i2c, sensor
|
||||||
|
from esphome.const import (
|
||||||
|
CONF_ID,
|
||||||
|
CONF_PRESSURE,
|
||||||
|
CONF_TEMPERATURE,
|
||||||
|
DEVICE_CLASS_PRESSURE,
|
||||||
|
DEVICE_CLASS_TEMPERATURE,
|
||||||
|
STATE_CLASS_MEASUREMENT,
|
||||||
|
UNIT_CELSIUS,
|
||||||
|
UNIT_HECTOPASCAL,
|
||||||
|
CONF_IIR_FILTER,
|
||||||
|
CONF_OVERSAMPLING,
|
||||||
|
)
|
||||||
|
|
||||||
|
DEPENDENCIES = ["i2c"]
|
||||||
|
|
||||||
|
qmp6988_ns = cg.esphome_ns.namespace("qmp6988")
|
||||||
|
QMP6988Component = qmp6988_ns.class_(
|
||||||
|
"QMP6988Component", cg.PollingComponent, i2c.I2CDevice
|
||||||
|
)
|
||||||
|
|
||||||
|
QMP6988Oversampling = qmp6988_ns.enum("QMP6988Oversampling")
|
||||||
|
OVERSAMPLING_OPTIONS = {
|
||||||
|
"NONE": QMP6988Oversampling.QMP6988_OVERSAMPLING_SKIPPED,
|
||||||
|
"1X": QMP6988Oversampling.QMP6988_OVERSAMPLING_1X,
|
||||||
|
"2X": QMP6988Oversampling.QMP6988_OVERSAMPLING_2X,
|
||||||
|
"4X": QMP6988Oversampling.QMP6988_OVERSAMPLING_4X,
|
||||||
|
"8X": QMP6988Oversampling.QMP6988_OVERSAMPLING_8X,
|
||||||
|
"16X": QMP6988Oversampling.QMP6988_OVERSAMPLING_16X,
|
||||||
|
"32X": QMP6988Oversampling.QMP6988_OVERSAMPLING_32X,
|
||||||
|
"64X": QMP6988Oversampling.QMP6988_OVERSAMPLING_64X,
|
||||||
|
}
|
||||||
|
|
||||||
|
QMP6988IIRFilter = qmp6988_ns.enum("QMP6988IIRFilter")
|
||||||
|
IIR_FILTER_OPTIONS = {
|
||||||
|
"OFF": QMP6988IIRFilter.QMP6988_IIR_FILTER_OFF,
|
||||||
|
"2X": QMP6988IIRFilter.QMP6988_IIR_FILTER_2X,
|
||||||
|
"4X": QMP6988IIRFilter.QMP6988_IIR_FILTER_4X,
|
||||||
|
"8X": QMP6988IIRFilter.QMP6988_IIR_FILTER_8X,
|
||||||
|
"16X": QMP6988IIRFilter.QMP6988_IIR_FILTER_16X,
|
||||||
|
"32X": QMP6988IIRFilter.QMP6988_IIR_FILTER_32X,
|
||||||
|
}
|
||||||
|
|
||||||
|
CONFIG_SCHEMA = (
|
||||||
|
cv.Schema(
|
||||||
|
{
|
||||||
|
cv.GenerateID(): cv.declare_id(QMP6988Component),
|
||||||
|
cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema(
|
||||||
|
unit_of_measurement=UNIT_CELSIUS,
|
||||||
|
accuracy_decimals=1,
|
||||||
|
device_class=DEVICE_CLASS_TEMPERATURE,
|
||||||
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
|
).extend(
|
||||||
|
{
|
||||||
|
cv.Optional(CONF_OVERSAMPLING, default="8X"): cv.enum(
|
||||||
|
OVERSAMPLING_OPTIONS, upper=True
|
||||||
|
),
|
||||||
|
}
|
||||||
|
),
|
||||||
|
cv.Optional(CONF_PRESSURE): sensor.sensor_schema(
|
||||||
|
unit_of_measurement=UNIT_HECTOPASCAL,
|
||||||
|
accuracy_decimals=1,
|
||||||
|
device_class=DEVICE_CLASS_PRESSURE,
|
||||||
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
|
).extend(
|
||||||
|
{
|
||||||
|
cv.Optional(CONF_OVERSAMPLING, default="8X"): cv.enum(
|
||||||
|
OVERSAMPLING_OPTIONS, upper=True
|
||||||
|
),
|
||||||
|
}
|
||||||
|
),
|
||||||
|
cv.Optional(CONF_IIR_FILTER, default="OFF"): cv.enum(
|
||||||
|
IIR_FILTER_OPTIONS, upper=True
|
||||||
|
),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.extend(cv.polling_component_schema("60s"))
|
||||||
|
.extend(i2c.i2c_device_schema(0x70))
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def to_code(config):
|
||||||
|
var = cg.new_Pvariable(config[CONF_ID])
|
||||||
|
await cg.register_component(var, config)
|
||||||
|
await i2c.register_i2c_device(var, config)
|
||||||
|
|
||||||
|
if CONF_TEMPERATURE in config:
|
||||||
|
conf = config[CONF_TEMPERATURE]
|
||||||
|
sens = await sensor.new_sensor(conf)
|
||||||
|
cg.add(var.set_temperature_sensor(sens))
|
||||||
|
cg.add(var.set_temperature_oversampling(conf[CONF_OVERSAMPLING]))
|
||||||
|
|
||||||
|
if CONF_PRESSURE in config:
|
||||||
|
conf = config[CONF_PRESSURE]
|
||||||
|
sens = await sensor.new_sensor(conf)
|
||||||
|
cg.add(var.set_pressure_sensor(sens))
|
||||||
|
cg.add(var.set_pressure_oversampling(conf[CONF_OVERSAMPLING]))
|
||||||
|
|
||||||
|
cg.add(var.set_iir_filter(config[CONF_IIR_FILTER]))
|
|
@ -798,6 +798,17 @@ sensor:
|
||||||
value: 12345
|
value: 12345
|
||||||
total:
|
total:
|
||||||
name: "Pulse Meter Total"
|
name: "Pulse Meter Total"
|
||||||
|
- platform: qmp6988
|
||||||
|
temperature:
|
||||||
|
name: "Living Temperature QMP"
|
||||||
|
oversampling: 32x
|
||||||
|
pressure:
|
||||||
|
name: "Living Pressure QMP"
|
||||||
|
oversampling: 2x
|
||||||
|
address: 0x70
|
||||||
|
update_interval: 30s
|
||||||
|
iir_filter: 16x
|
||||||
|
i2c_id: i2c_bus
|
||||||
- platform: rotary_encoder
|
- platform: rotary_encoder
|
||||||
name: "Rotary Encoder"
|
name: "Rotary Encoder"
|
||||||
id: rotary_encoder1
|
id: rotary_encoder1
|
||||||
|
|
Loading…
Reference in a new issue