8static const char *
const TAG =
"sps30";
10static const uint16_t SPS30_CMD_GET_ARTICLE_CODE = 0xD025;
11static const uint16_t SPS30_CMD_GET_SERIAL_NUMBER = 0xD033;
12static const uint16_t SPS30_CMD_GET_FIRMWARE_VERSION = 0xD100;
13static const uint16_t SPS30_CMD_START_CONTINUOUS_MEASUREMENTS = 0x0010;
14static const uint16_t SPS30_CMD_START_CONTINUOUS_MEASUREMENTS_ARG = 0x0300;
15static const uint16_t SPS30_CMD_GET_DATA_READY_STATUS = 0x0202;
16static const uint16_t SPS30_CMD_READ_MEASUREMENT = 0x0300;
17static const uint16_t SPS30_CMD_STOP_MEASUREMENTS = 0x0104;
18static const uint16_t SPS30_CMD_SET_AUTOMATIC_CLEANING_INTERVAL_SECONDS = 0x8004;
19static const uint16_t SPS30_CMD_START_FAN_CLEANING = 0x5607;
20static const uint16_t SPS30_CMD_SOFT_RESET = 0xD304;
21static const size_t SERIAL_NUMBER_LENGTH = 8;
22static const uint8_t MAX_SKIPPED_DATA_CYCLES_BEFORE_ERROR = 5;
35 uint16_t raw_serial_number[8];
36 if (!this->
get_register(SPS30_CMD_GET_SERIAL_NUMBER, raw_serial_number, 8, 1)) {
42 for (
size_t i = 0; i < 8; ++i) {
43 this->
serial_number_[i * 2] =
static_cast<char>(raw_serial_number[i] >> 8);
44 this->
serial_number_[i * 2 + 1] = uint16_t(uint16_t(raw_serial_number[i] & 0xFF));
53 result = this->
write_command(SPS30_CMD_SET_AUTOMATIC_CLEANING_INTERVAL_SECONDS);
72 ESP_LOGCONFIG(TAG,
"SPS30:");
75 switch (this->error_code_) {
77 ESP_LOGW(TAG, ESP_LOG_MSG_COMM_FAIL);
80 ESP_LOGW(TAG,
"Measurement Initialization failed");
83 ESP_LOGW(TAG,
"Unable to request serial number");
86 ESP_LOGW(TAG,
"Unable to read serial number");
89 ESP_LOGW(TAG,
"Unable to request firmware version");
92 ESP_LOGW(TAG,
"Unable to read firmware version");
95 ESP_LOGW(TAG,
"Unknown setup error");
99 LOG_UPDATE_INTERVAL(
this);
101 " Serial number: %s\n"
102 " Firmware version v%0d.%0d",
104 LOG_SENSOR(
" ",
"PM1.0 Weight Concentration", this->
pm_1_0_sensor_);
105 LOG_SENSOR(
" ",
"PM2.5 Weight Concentration", this->
pm_2_5_sensor_);
106 LOG_SENSOR(
" ",
"PM4 Weight Concentration", this->
pm_4_0_sensor_);
120 ESP_LOGD(TAG,
"Reconnecting");
122 ESP_LOGD(TAG,
"Soft-reset successful; waiting 500 ms");
128 ESP_LOGD(TAG,
"Reconnected; resuming continuous measurement");
131 ESP_LOGD(TAG,
"Soft-reset failed");
141 uint16_t raw_read_status;
142 if (!this->
read_data(&raw_read_status, 1) || raw_read_status == 0x00) {
143 ESP_LOGD(TAG,
"Not ready");
148 ESP_LOGD(TAG,
"Exceeded max attempts; will reinitialize");
155 ESP_LOGW(TAG,
"Error reading status");
161 uint16_t raw_data[20];
163 ESP_LOGW(TAG,
"Error reading data");
168 union uint32_float_t {
174 uint32_float_t pm_1_0{.uint32 = (((uint32_t(raw_data[0])) << 16) | (uint32_t(raw_data[1])))};
175 uint32_float_t pm_2_5{.uint32 = (((uint32_t(raw_data[2])) << 16) | (uint32_t(raw_data[3])))};
176 uint32_float_t pm_4_0{.uint32 = (((uint32_t(raw_data[4])) << 16) | (uint32_t(raw_data[5])))};
177 uint32_float_t pm_10_0{.uint32 = (((uint32_t(raw_data[6])) << 16) | (uint32_t(raw_data[7])))};
180 uint32_float_t pmc_0_5{.uint32 = (((uint32_t(raw_data[8])) << 16) | (uint32_t(raw_data[9])))};
181 uint32_float_t pmc_1_0{.uint32 = (((uint32_t(raw_data[10])) << 16) | (uint32_t(raw_data[11])))};
182 uint32_float_t pmc_2_5{.uint32 = (((uint32_t(raw_data[12])) << 16) | (uint32_t(raw_data[13])))};
183 uint32_float_t pmc_4_0{.uint32 = (((uint32_t(raw_data[14])) << 16) | (uint32_t(raw_data[15])))};
184 uint32_float_t pmc_10_0{.uint32 = (((uint32_t(raw_data[16])) << 16) | (uint32_t(raw_data[17])))};
187 uint32_float_t pm_size{.uint32 = (((uint32_t(raw_data[18])) << 16) | (uint32_t(raw_data[19])))};
212 this->status_clear_warning();
213 this->skipped_data_read_cycles_ = 0;
218 if (!this->
write_command(SPS30_CMD_START_CONTINUOUS_MEASUREMENTS, SPS30_CMD_START_CONTINUOUS_MEASUREMENTS_ARG)) {
219 ESP_LOGE(TAG,
"Error initiating measurements");
228 ESP_LOGE(TAG,
"Start fan cleaning failed (%d)", this->
last_error_);
231 ESP_LOGD(TAG,
"Fan auto clean started");
virtual void mark_failed()
Mark this component as failed.
void status_set_warning(const char *message=nullptr)
bool status_has_warning() const
void status_clear_warning()
void set_timeout(const std::string &name, uint32_t timeout, std::function< void()> &&f)
Set a timeout function with a unique name.
value_type const & value() const
i2c::ErrorCode last_error_
last error code from I2C operation
bool get_register(uint16_t command, uint16_t *data, uint8_t len, uint8_t delay=0)
get data words from I2C register.
bool write_command(T i2c_register)
Write a command to the I2C device.
bool read_data(uint16_t *data, uint8_t len)
Read data words from I2C device.
void publish_state(float state)
Publish a new state to the front-end.
uint16_t raw_firmware_version_
sensor::Sensor * pm_2_5_sensor_
optional< uint32_t > fan_interval_
@ FIRMWARE_VERSION_REQUEST_FAILED
@ FIRMWARE_VERSION_READ_FAILED
@ SERIAL_NUMBER_READ_FAILED
@ SERIAL_NUMBER_REQUEST_FAILED
@ MEASUREMENT_INIT_FAILED
bool start_continuous_measurement_()
sensor::Sensor * pmc_4_0_sensor_
sensor::Sensor * pmc_2_5_sensor_
sensor::Sensor * pm_10_0_sensor_
uint8_t skipped_data_read_cycles_
Terminating NULL character.
bool start_fan_cleaning()
sensor::Sensor * pm_1_0_sensor_
sensor::Sensor * pm_size_sensor_
void dump_config() override
sensor::Sensor * pmc_0_5_sensor_
sensor::Sensor * pm_4_0_sensor_
sensor::Sensor * pmc_10_0_sensor_
sensor::Sensor * pmc_1_0_sensor_
Providing packet encoding functions for exchanging data with a remote host.