8 static const char *
const TAG =
"sps30";
10 static const uint16_t SPS30_CMD_GET_ARTICLE_CODE = 0xD025;
11 static const uint16_t SPS30_CMD_GET_SERIAL_NUMBER = 0xD033;
12 static const uint16_t SPS30_CMD_GET_FIRMWARE_VERSION = 0xD100;
13 static const uint16_t SPS30_CMD_START_CONTINUOUS_MEASUREMENTS = 0x0010;
14 static const uint16_t SPS30_CMD_START_CONTINUOUS_MEASUREMENTS_ARG = 0x0300;
15 static const uint16_t SPS30_CMD_GET_DATA_READY_STATUS = 0x0202;
16 static const uint16_t SPS30_CMD_READ_MEASUREMENT = 0x0300;
17 static const uint16_t SPS30_CMD_STOP_MEASUREMENTS = 0x0104;
18 static const uint16_t SPS30_CMD_SET_AUTOMATIC_CLEANING_INTERVAL_SECONDS = 0x8004;
19 static const uint16_t SPS30_CMD_START_FAN_CLEANING = 0x5607;
20 static const uint16_t SPS30_CMD_SOFT_RESET = 0xD304;
21 static const size_t SERIAL_NUMBER_LENGTH = 8;
22 static const uint8_t MAX_SKIPPED_DATA_CYCLES_BEFORE_ERROR = 5;
25 ESP_LOGCONFIG(TAG,
"Setting up sps30...");
36 uint16_t raw_serial_number[8];
37 if (!this->
get_register(SPS30_CMD_GET_SERIAL_NUMBER, raw_serial_number, 8, 1)) {
43 for (
size_t i = 0; i < 8; ++i) {
44 this->
serial_number_[i * 2] =
static_cast<char>(raw_serial_number[i] >> 8);
45 this->
serial_number_[i * 2 + 1] = uint16_t(uint16_t(raw_serial_number[i] & 0xFF));
54 result =
write_command(SPS30_CMD_SET_AUTOMATIC_CLEANING_INTERVAL_SECONDS);
71 ESP_LOGCONFIG(TAG,
"sps30:");
74 switch (this->error_code_) {
76 ESP_LOGW(TAG,
"Communication failed! Is the sensor connected?");
79 ESP_LOGW(TAG,
"Measurement Initialization failed!");
82 ESP_LOGW(TAG,
"Unable to request sensor serial number");
85 ESP_LOGW(TAG,
"Unable to read sensor serial number");
88 ESP_LOGW(TAG,
"Unable to request sensor firmware version");
91 ESP_LOGW(TAG,
"Unable to read sensor firmware version");
94 ESP_LOGW(TAG,
"Unknown setup error!");
98 LOG_UPDATE_INTERVAL(
this);
102 LOG_SENSOR(
" ",
"PM1.0 Weight Concentration", this->
pm_1_0_sensor_);
103 LOG_SENSOR(
" ",
"PM2.5 Weight Concentration", this->
pm_2_5_sensor_);
104 LOG_SENSOR(
" ",
"PM4 Weight Concentration", this->
pm_4_0_sensor_);
116 ESP_LOGD(TAG,
"Trying to reconnect the sensor...");
118 ESP_LOGD(TAG,
"Sensor has soft-reset successfully. Waiting for reconnection in 500ms...");
124 ESP_LOGD(TAG,
"Sensor reconnected successfully. Resuming continuous measurement!");
127 ESP_LOGD(TAG,
"Sensor soft-reset failed. Is the sensor offline?");
137 uint16_t raw_read_status;
138 if (!this->
read_data(&raw_read_status, 1) || raw_read_status == 0x00) {
139 ESP_LOGD(TAG,
"Sensor measurement not ready yet.");
144 ESP_LOGD(TAG,
"Sensor exceeded max allowed attempts. Sensor communication will be reinitialized.");
151 ESP_LOGW(TAG,
"Error reading measurement status!");
157 uint16_t raw_data[20];
159 ESP_LOGW(TAG,
"Error reading measurement data!");
164 union uint32_float_t {
170 uint32_float_t pm_1_0{.uint32 = (((uint32_t(raw_data[0])) << 16) | (uint32_t(raw_data[1])))};
171 uint32_float_t pm_2_5{.uint32 = (((uint32_t(raw_data[2])) << 16) | (uint32_t(raw_data[3])))};
172 uint32_float_t pm_4_0{.uint32 = (((uint32_t(raw_data[4])) << 16) | (uint32_t(raw_data[5])))};
173 uint32_float_t pm_10_0{.uint32 = (((uint32_t(raw_data[6])) << 16) | (uint32_t(raw_data[7])))};
176 uint32_float_t pmc_0_5{.uint32 = (((uint32_t(raw_data[8])) << 16) | (uint32_t(raw_data[9])))};
177 uint32_float_t pmc_1_0{.uint32 = (((uint32_t(raw_data[10])) << 16) | (uint32_t(raw_data[11])))};
178 uint32_float_t pmc_2_5{.uint32 = (((uint32_t(raw_data[12])) << 16) | (uint32_t(raw_data[13])))};
179 uint32_float_t pmc_4_0{.uint32 = (((uint32_t(raw_data[14])) << 16) | (uint32_t(raw_data[15])))};
180 uint32_float_t pmc_10_0{.uint32 = (((uint32_t(raw_data[16])) << 16) | (uint32_t(raw_data[17])))};
183 uint32_float_t pm_size{.uint32 = (((uint32_t(raw_data[18])) << 16) | (uint32_t(raw_data[19])))};
215 data[0] = SPS30_CMD_START_CONTINUOUS_MEASUREMENTS & 0xFF;
219 if (!this->
write_command(SPS30_CMD_START_CONTINUOUS_MEASUREMENTS, SPS30_CMD_START_CONTINUOUS_MEASUREMENTS_ARG)) {
220 ESP_LOGE(TAG,
"Error initiating measurements");
229 ESP_LOGE(TAG,
"write error start fan (%d)", this->
last_error_);
232 ESP_LOGD(TAG,
"Fan auto clean started");
sensor::Sensor * pm_2_5_sensor_
value_type const & value() const
void status_set_warning(const char *message="unspecified")
bool start_continuous_measurement_()
bool status_has_warning() const
void dump_config() override
sensor::Sensor * pm_size_sensor_
bool write_command(T i2c_register)
Write a command to the i2c device.
sensor::Sensor * pmc_10_0_sensor_
sensor::Sensor * pm_4_0_sensor_
void set_timeout(const std::string &name, uint32_t timeout, std::function< void()> &&f)
Set a timeout function with a unique name.
optional< uint32_t > fan_interval_
bool read_data(uint16_t *data, uint8_t len)
Read data words from i2c device.
uint8_t sht_crc_(uint16_t data)
8-bit CRC checksum that is transmitted after each data word for read and write operation ...
bool start_fan_cleaning()
sensor::Sensor * pmc_0_5_sensor_
uint16_t raw_firmware_version_
Terminating NULL character.
void status_clear_warning()
void publish_state(float state)
Publish a new state to the front-end.
uint8_t skipped_data_read_cycles_
bool get_register(uint16_t command, uint16_t *data, uint8_t len, uint8_t delay=0)
get data words from i2c register.
virtual void mark_failed()
Mark this component as failed.
i2c::ErrorCode last_error_
last error code from i2c operation
sensor::Sensor * pmc_2_5_sensor_
Implementation of SPI Controller mode.
sensor::Sensor * pmc_1_0_sensor_
sensor::Sensor * pmc_4_0_sensor_
sensor::Sensor * pm_10_0_sensor_
sensor::Sensor * pm_1_0_sensor_
void IRAM_ATTR HOT delay(uint32_t ms)