10 static const char *
const TAG =
"sen5x";
12 static const uint16_t SEN5X_CMD_AUTO_CLEANING_INTERVAL = 0x8004;
13 static const uint16_t SEN5X_CMD_GET_DATA_READY_STATUS = 0x0202;
14 static const uint16_t SEN5X_CMD_GET_FIRMWARE_VERSION = 0xD100;
15 static const uint16_t SEN5X_CMD_GET_PRODUCT_NAME = 0xD014;
16 static const uint16_t SEN5X_CMD_GET_SERIAL_NUMBER = 0xD033;
17 static const uint16_t SEN5X_CMD_NOX_ALGORITHM_TUNING = 0x60E1;
18 static const uint16_t SEN5X_CMD_READ_MEASUREMENT = 0x03C4;
19 static const uint16_t SEN5X_CMD_RHT_ACCELERATION_MODE = 0x60F7;
20 static const uint16_t SEN5X_CMD_START_CLEANING_FAN = 0x5607;
21 static const uint16_t SEN5X_CMD_START_MEASUREMENTS = 0x0021;
22 static const uint16_t SEN5X_CMD_START_MEASUREMENTS_RHT_ONLY = 0x0037;
23 static const uint16_t SEN5X_CMD_STOP_MEASUREMENTS = 0x3f86;
24 static const uint16_t SEN5X_CMD_TEMPERATURE_COMPENSATION = 0x60B2;
25 static const uint16_t SEN5X_CMD_VOC_ALGORITHM_STATE = 0x6181;
26 static const uint16_t SEN5X_CMD_VOC_ALGORITHM_TUNING = 0x60D0;
29 ESP_LOGCONFIG(TAG,
"Setting up sen5x...");
35 ESP_LOGE(TAG,
"Failed to write data ready status command");
40 uint16_t raw_read_status;
42 ESP_LOGE(TAG,
"Failed to read data ready status");
47 uint32_t stop_measurement_delay = 0;
49 if (raw_read_status) {
50 ESP_LOGD(TAG,
"Sensor has data available, stopping periodic measurement");
52 ESP_LOGE(TAG,
"Failed to stop measurements");
58 stop_measurement_delay = 200;
60 this->
set_timeout(stop_measurement_delay, [
this]() {
61 uint16_t raw_serial_number[3];
62 if (!this->
get_register(SEN5X_CMD_GET_SERIAL_NUMBER, raw_serial_number, 3, 20)) {
63 ESP_LOGE(TAG,
"Failed to read serial number");
68 this->
serial_number_[0] =
static_cast<bool>(uint16_t(raw_serial_number[0]) & 0xFF);
69 this->
serial_number_[1] =
static_cast<uint16_t
>(raw_serial_number[0] & 0xFF);
70 this->
serial_number_[2] =
static_cast<uint16_t
>(raw_serial_number[1] >> 8);
73 uint16_t raw_product_name[16];
74 if (!this->
get_register(SEN5X_CMD_GET_PRODUCT_NAME, raw_product_name, 16, 20)) {
75 ESP_LOGE(TAG,
"Failed to read product name");
81 const uint16_t *current_int = raw_product_name;
86 current_char = *current_int >> 8;
90 current_char = *current_int & 0xFF;
95 }
while (current_char && --max);
111 ESP_LOGE(TAG,
"For Relative humidity a SEN54 OR SEN55 is required. You are using a <%s> sensor",
116 ESP_LOGE(TAG,
"For Temperature a SEN54 OR SEN55 is required. You are using a <%s> sensor",
121 ESP_LOGE(TAG,
"For VOC a SEN54 OR SEN55 is required. You are using a <%s> sensor", this->
product_name_.c_str());
125 ESP_LOGE(TAG,
"For NOx a SEN55 is required. You are using a <%s> sensor", this->
product_name_.c_str());
130 ESP_LOGE(TAG,
"Failed to read firmware version");
139 uint32_t combined_serial =
147 if (this->pref_.load(&this->voc_baselines_storage_)) {
148 ESP_LOGI(TAG,
"Loaded VOC baseline state0: 0x%04" PRIX32
", state1: 0x%04" PRIX32,
156 ESP_LOGI(TAG,
"Setting VOC baseline from save state0: 0x%04" PRIX32
", state1: 0x%04" PRIX32,
165 if (!this->
write_command(SEN5X_CMD_VOC_ALGORITHM_STATE, states, 4)) {
166 ESP_LOGE(TAG,
"Failed to set VOC baseline from saved state");
187 result = this->
write_command(SEN5X_CMD_RHT_ACCELERATION_MODE);
190 ESP_LOGE(TAG,
"Failed to set rh/t acceleration mode");
201 ESP_LOGE(TAG,
"Failed to read RHT Acceleration mode");
219 auto cmd = SEN5X_CMD_START_MEASUREMENTS_RHT_ONLY;
222 cmd = SEN5X_CMD_START_MEASUREMENTS;
226 ESP_LOGE(TAG,
"Error starting continuous measurements.");
232 ESP_LOGD(TAG,
"Sensor initialized");
238 ESP_LOGCONFIG(TAG,
"sen5x:");
239 LOG_I2C_DEVICE(
this);
243 ESP_LOGW(TAG,
"Communication failed! Is the sensor connected?");
246 ESP_LOGW(TAG,
"Measurement Initialization failed!");
249 ESP_LOGW(TAG,
"Unable to read sensor serial id");
252 ESP_LOGW(TAG,
"Unable to read product name");
255 ESP_LOGW(TAG,
"Unable to read sensor firmware version");
258 ESP_LOGW(TAG,
"Unknown setup error!");
262 ESP_LOGCONFIG(TAG,
" Productname: %s", this->
product_name_.c_str());
271 ESP_LOGCONFIG(TAG,
" Low RH/T acceleration mode");
274 ESP_LOGCONFIG(TAG,
" Medium RH/T accelertion mode");
277 ESP_LOGCONFIG(TAG,
" High RH/T accelertion mode");
281 LOG_UPDATE_INTERVAL(
this);
305 uint32_t state0 = states[0] << 16 | states[1];
306 uint32_t state1 = states[2] << 16 | states[3];
309 (uint32_t) std::abs(static_cast<int32_t>(this->voc_baselines_storage_.state1 - state1)) >
311 this->seconds_since_last_store_ = 0;
312 this->voc_baselines_storage_.state0 = state0;
313 this->voc_baselines_storage_.state1 = state1;
315 if (this->pref_.save(&this->voc_baselines_storage_)) {
316 ESP_LOGI(TAG,
"Stored VOC baseline state0: 0x%04" PRIX32
" ,state1: 0x%04" PRIX32,
317 this->voc_baselines_storage_.state0, voc_baselines_storage_.state1);
319 ESP_LOGW(TAG,
"Could not store VOC baselines");
329 ESP_LOGD(TAG,
"write error read measurement (%d)", this->
last_error_);
333 uint16_t measurements[8];
337 ESP_LOGD(TAG,
"read data error (%d)", this->
last_error_);
340 float pm_1_0 = measurements[0] / 10.0;
341 if (measurements[0] == 0xFFFF)
343 float pm_2_5 = measurements[1] / 10.0;
344 if (measurements[1] == 0xFFFF)
346 float pm_4_0 = measurements[2] / 10.0;
347 if (measurements[2] == 0xFFFF)
349 float pm_10_0 = measurements[3] / 10.0;
350 if (measurements[3] == 0xFFFF)
352 float humidity = measurements[4] / 100.0;
353 if (measurements[4] == 0xFFFF)
355 float temperature = (int16_t) measurements[5] / 200.0;
356 if (measurements[5] == 0xFFFF)
358 float voc = measurements[6] / 10.0;
359 if (measurements[6] == 0xFFFF)
361 float nox = measurements[7] / 10.0;
362 if (measurements[7] == 0xFFFF)
395 ESP_LOGE(TAG,
"set tuning parameters failed. i2c command=%0xX, err=%d", i2c_command, this->
last_error_);
402 params[0] = compensation.
offset;
405 if (!
write_command(SEN5X_CMD_TEMPERATURE_COMPENSATION, params, 3)) {
406 ESP_LOGE(TAG,
"set temperature_compensation failed. Err=%d", this->
last_error_);
415 ESP_LOGE(TAG,
"write error start fan (%d)", this->
last_error_);
418 ESP_LOGD(TAG,
"Fan auto clean started");
Sen5xBaselines voc_baselines_storage_
value_type const & value() const
optional< RhtAccelerationMode > acceleration_mode_
const char * to_string(SHTCXType type)
void status_set_warning(const char *message="unspecified")
optional< GasTuning > nox_tuning_params_
bool write_command(T i2c_register)
Write a command to the i2c device.
uint16_t gating_max_duration_minutes
std::string product_name_
uint16_t learning_time_gain_hours
void set_timeout(const std::string &name, uint32_t timeout, std::function< void()> &&f)
Set a timeout function with a unique name.
uint16_t learning_time_offset_hours
bool write_temperature_compensation_(const TemperatureCompensation &compensation)
bool read_data(uint16_t *data, uint8_t len)
Read data words from i2c device.
optional< GasTuning > voc_tuning_params_
optional< uint32_t > auto_cleaning_interval_
sensor::Sensor * humidity_sensor_
ESPPreferenceObject pref_
ESPPreferences * global_preferences
void dump_config() override
void status_clear_warning()
sensor::Sensor * pm_2_5_sensor_
BedjetMode mode
BedJet operating mode.
uint32_t seconds_since_last_store_
sensor::Sensor * pm_1_0_sensor_
void publish_state(float state)
Publish a new state to the front-end.
uint8_t serial_number_[4]
constexpr uint32_t encode_uint24(uint8_t byte1, uint8_t byte2, uint8_t byte3)
Encode a 24-bit value given three bytes in most to least significant byte order.
sensor::Sensor * nox_sensor_
Application App
Global storage of Application pointer - only one Application can exist.
bool start_fan_cleaning()
int16_t normalized_offset_slope
bool get_register(uint16_t command, uint16_t *data, uint8_t len, uint8_t delay=0)
get data words from i2c register.
sensor::Sensor * pm_10_0_sensor_
virtual ESPPreferenceObject make_preference(size_t length, uint32_t type, bool in_flash)=0
uint32_t fnv1_hash(const std::string &str)
Calculate a FNV-1 hash of str.
sensor::Sensor * temperature_sensor_
virtual void mark_failed()
Mark this component as failed.
i2c::ErrorCode last_error_
last error code from i2c operation
sensor::Sensor * voc_sensor_
Implementation of SPI Controller mode.
uint16_t firmware_version_
optional< TemperatureCompensation > temperature_compensation_
std::string get_compilation_time() const
const uint32_t SHORTEST_BASELINE_STORE_INTERVAL
const uint32_t MAXIMUM_STORAGE_DIFF
sensor::Sensor * pm_4_0_sensor_
void IRAM_ATTR HOT delay(uint32_t ms)
bool write_tuning_parameters_(uint16_t i2c_command, const GasTuning &tuning)