ESPHome  2024.4.1
dps310.cpp
Go to the documentation of this file.
1 #include "dps310.h"
2 #include "esphome/core/log.h"
3 #include "esphome/core/hal.h"
4 
5 namespace esphome {
6 namespace dps310 {
7 
8 static const char *const TAG = "dps310";
9 
11  uint8_t coef_data_raw[DPS310_NUM_COEF_REGS];
12  auto timer = DPS310_INIT_TIMEOUT;
13  uint8_t reg = 0;
14 
15  ESP_LOGCONFIG(TAG, "Setting up DPS310...");
16  // first, reset the sensor
17  if (!this->write_byte(DPS310_REG_RESET, DPS310_CMD_RESET)) {
18  this->mark_failed();
19  return;
20  }
21  delay(10);
22  // wait for the sensor and its coefficients to be ready
23  while (timer-- && (!(reg & DPS310_BIT_SENSOR_RDY) || !(reg & DPS310_BIT_COEF_RDY))) {
24  reg = this->read_byte(DPS310_REG_MEAS_CFG).value_or(0);
25  delay(5);
26  }
27 
28  if (!(reg & DPS310_BIT_SENSOR_RDY) || !(reg & DPS310_BIT_COEF_RDY)) { // the flags were not set in time
29  this->mark_failed();
30  return;
31  }
32  // read device ID
33  if (!this->read_byte(DPS310_REG_PROD_REV_ID, &this->prod_rev_id_)) {
34  this->mark_failed();
35  return;
36  }
37  // read in coefficients used to calculate the compensated pressure and temperature values
38  if (!this->read_bytes(DPS310_REG_COEF, coef_data_raw, DPS310_NUM_COEF_REGS)) {
39  this->mark_failed();
40  return;
41  }
42  // read in coefficients source register, too -- we need this a few lines down
43  if (!this->read_byte(DPS310_REG_TMP_COEF_SRC, &reg)) {
44  this->mark_failed();
45  return;
46  }
47  // set up operational stuff
48  if (!this->write_byte(DPS310_REG_PRS_CFG, DPS310_VAL_PRS_CFG)) {
49  this->mark_failed();
50  return;
51  }
52  if (!this->write_byte(DPS310_REG_TMP_CFG, DPS310_VAL_TMP_CFG | (reg & DPS310_BIT_TMP_COEF_SRC))) {
53  this->mark_failed();
54  return;
55  }
56  if (!this->write_byte(DPS310_REG_CFG, DPS310_VAL_REG_CFG)) {
57  this->mark_failed();
58  return;
59  }
60  if (!this->write_byte(DPS310_REG_MEAS_CFG, 0x07)) { // enable background mode
61  this->mark_failed();
62  return;
63  }
64 
65  this->c0_ = // we only ever use c0/2, so just divide by 2 here to save time later
67  int16_t(((uint16_t) coef_data_raw[0] << 4) | (((uint16_t) coef_data_raw[1] >> 4) & 0x0F)), 12) /
68  2;
69 
70  this->c1_ =
71  DPS310Component::twos_complement(int16_t((((uint16_t) coef_data_raw[1] & 0x0F) << 8) | coef_data_raw[2]), 12);
72 
73  this->c00_ = ((uint32_t) coef_data_raw[3] << 12) | ((uint32_t) coef_data_raw[4] << 4) |
74  (((uint32_t) coef_data_raw[5] >> 4) & 0x0F);
76 
77  this->c10_ =
78  (((uint32_t) coef_data_raw[5] & 0x0F) << 16) | ((uint32_t) coef_data_raw[6] << 8) | (uint32_t) coef_data_raw[7];
80 
81  this->c01_ = int16_t(((uint16_t) coef_data_raw[8] << 8) | (uint16_t) coef_data_raw[9]);
82  this->c11_ = int16_t(((uint16_t) coef_data_raw[10] << 8) | (uint16_t) coef_data_raw[11]);
83  this->c20_ = int16_t(((uint16_t) coef_data_raw[12] << 8) | (uint16_t) coef_data_raw[13]);
84  this->c21_ = int16_t(((uint16_t) coef_data_raw[14] << 8) | (uint16_t) coef_data_raw[15]);
85  this->c30_ = int16_t(((uint16_t) coef_data_raw[16] << 8) | (uint16_t) coef_data_raw[17]);
86 }
87 
89  ESP_LOGCONFIG(TAG, "DPS310:");
90  ESP_LOGCONFIG(TAG, " Product ID: %u", this->prod_rev_id_ & 0x0F);
91  ESP_LOGCONFIG(TAG, " Revision ID: %u", (this->prod_rev_id_ >> 4) & 0x0F);
92  LOG_I2C_DEVICE(this);
93  if (this->is_failed()) {
94  ESP_LOGE(TAG, "Communication with DPS310 failed!");
95  }
96  LOG_UPDATE_INTERVAL(this);
97  LOG_SENSOR(" ", "Temperature", this->temperature_sensor_);
98  LOG_SENSOR(" ", "Pressure", this->pressure_sensor_);
99 }
100 
102 
104  if (!this->update_in_progress_) {
105  this->update_in_progress_ = true;
106  this->read_();
107  }
108 }
109 
111  uint8_t reg = 0;
112  if (!this->read_byte(DPS310_REG_MEAS_CFG, &reg)) {
113  this->status_set_warning();
114  return;
115  }
116 
117  if ((!this->got_pres_) && (reg & DPS310_BIT_PRS_RDY)) {
118  this->read_pressure_();
119  }
120 
121  if ((!this->got_temp_) && (reg & DPS310_BIT_TMP_RDY)) {
122  this->read_temperature_();
123  }
124 
125  if (this->got_pres_ && this->got_temp_) {
127  this->got_pres_ = false;
128  this->got_temp_ = false;
129  this->update_in_progress_ = false;
130  this->status_clear_warning();
131  } else {
132  auto f = std::bind(&DPS310Component::read_, this);
133  this->set_timeout("dps310", 10, f);
134  }
135 }
136 
138  uint8_t bytes[3];
139  if (!this->read_bytes(DPS310_REG_PRS_B2, bytes, 3)) {
140  this->status_set_warning();
141  return;
142  }
143  this->got_pres_ = true;
145  int32_t((uint32_t(bytes[0]) << 16) | (uint32_t(bytes[1]) << 8) | (uint32_t(bytes[2]))), 24);
146 }
147 
149  uint8_t bytes[3];
150  if (!this->read_bytes(DPS310_REG_TMP_B2, bytes, 3)) {
151  this->status_set_warning();
152  return;
153  }
154  this->got_temp_ = true;
156  int32_t((uint32_t(bytes[0]) << 16) | (uint32_t(bytes[1]) << 8) | (uint32_t(bytes[2]))), 24);
157 }
158 
159 // Calculations are taken from the datasheet which can be found here:
160 // https://www.infineon.com/dgdl/Infineon-DPS310-DataSheet-v01_02-EN.pdf?fileId=5546d462576f34750157750826c42242
161 // Sections "How to Calculate Compensated Pressure Values" and "How to Calculate Compensated Temperature Values"
162 // Variable names below match variable names from the datasheet but lowercased
163 void DPS310Component::calculate_values_(int32_t raw_temperature, int32_t raw_pressure) {
164  const float t_raw_sc = (float) raw_temperature / DPS310_SCALE_FACTOR;
165  const float p_raw_sc = (float) raw_pressure / DPS310_SCALE_FACTOR;
166 
167  const float temperature = t_raw_sc * this->c1_ + this->c0_; // c0/2 done earlier!
168 
169  const float pressure = (this->c00_ + p_raw_sc * (this->c10_ + p_raw_sc * (this->c20_ + p_raw_sc * this->c30_)) +
170  t_raw_sc * this->c01_ + t_raw_sc * p_raw_sc * (this->c11_ + p_raw_sc * this->c21_)) /
171  100; // divide by 100 for hPa
172 
173  if (this->temperature_sensor_ != nullptr) {
174  this->temperature_sensor_->publish_state(temperature);
175  }
176  if (this->pressure_sensor_ != nullptr) {
177  this->pressure_sensor_->publish_state(pressure);
178  }
179 }
180 
181 int32_t DPS310Component::twos_complement(int32_t val, uint8_t bits) {
182  if (val & ((uint32_t) 1 << (bits - 1))) {
183  val -= (uint32_t) 1 << bits;
184  }
185  return val;
186 }
187 
188 } // namespace dps310
189 } // namespace esphome
bool read_byte(uint8_t a_register, uint8_t *data, bool stop=true)
Definition: i2c.h:235
const float DATA
For components that import data from directly connected sensors like DHT.
Definition: component.cpp:19
void dump_config() override
Definition: dps310.cpp:88
void status_set_warning(const char *message="unspecified")
Definition: component.cpp:151
uint8_t pressure
Definition: tt21100.cpp:19
I2CRegister reg(uint8_t a_register)
calls the I2CRegister constructor
Definition: i2c.h:149
void set_timeout(const std::string &name, uint32_t timeout, std::function< void()> &&f)
Set a timeout function with a unique name.
Definition: component.cpp:69
bool read_bytes(uint8_t a_register, uint8_t *data, uint8_t len)
Compat APIs All methods below have been added for compatibility reasons.
Definition: i2c.h:212
sensor::Sensor * temperature_sensor_
Definition: dps310.h:56
mopeka_std_values val[4]
void calculate_values_(int32_t raw_temperature, int32_t raw_pressure)
Definition: dps310.cpp:163
void status_clear_warning()
Definition: component.cpp:166
void publish_state(float state)
Publish a new state to the front-end.
Definition: sensor.cpp:39
uint16_t temperature
Definition: sun_gtil2.cpp:26
sensor::Sensor * pressure_sensor_
Definition: dps310.h:57
bool write_byte(uint8_t a_register, uint8_t data, bool stop=true)
Definition: i2c.h:262
virtual void mark_failed()
Mark this component as failed.
Definition: component.cpp:118
float get_setup_priority() const override
Definition: dps310.cpp:101
This is a workaround until we can figure out a way to get the tflite-micro idf component code availab...
Definition: a01nyub.cpp:7
std::vector< uint8_t > bytes
Definition: sml_parser.h:12
static int32_t twos_complement(int32_t val, uint8_t bits)
Definition: dps310.cpp:181
void IRAM_ATTR HOT delay(uint32_t ms)
Definition: core.cpp:26