ESPHome  2024.3.1
pm1006.cpp
Go to the documentation of this file.
1 #include "pm1006.h"
2 #include "esphome/core/log.h"
3 
4 namespace esphome {
5 namespace pm1006 {
6 
7 static const char *const TAG = "pm1006";
8 
9 static const uint8_t PM1006_RESPONSE_HEADER[] = {0x16, 0x11, 0x0B};
10 static const uint8_t PM1006_REQUEST[] = {0x11, 0x02, 0x0B, 0x01, 0xE1};
11 
13  // because this implementation is currently rx-only, there is nothing to setup
14 }
15 
17  ESP_LOGCONFIG(TAG, "PM1006:");
18  LOG_SENSOR(" ", "PM2.5", this->pm_2_5_sensor_);
19  LOG_UPDATE_INTERVAL(this);
20  this->check_uart_settings(9600);
21 }
22 
24  ESP_LOGV(TAG, "sending measurement request");
25  this->write_array(PM1006_REQUEST, sizeof(PM1006_REQUEST));
26 }
27 
29  while (this->available() != 0) {
30  this->read_byte(&this->data_[this->data_index_]);
31  auto check = this->check_byte_();
32  if (!check.has_value()) {
33  // finished
34  this->parse_data_();
35  this->data_index_ = 0;
36  } else if (!*check) {
37  // wrong data
38  ESP_LOGV(TAG, "Byte %i of received data frame is invalid.", this->data_index_);
39  this->data_index_ = 0;
40  } else {
41  // next byte
42  this->data_index_++;
43  }
44  }
45 }
46 
48 
49 uint8_t PM1006Component::pm1006_checksum_(const uint8_t *command_data, uint8_t length) const {
50  uint8_t sum = 0;
51  for (uint8_t i = 0; i < length; i++) {
52  sum += command_data[i];
53  }
54  return sum;
55 }
56 
58  uint8_t index = this->data_index_;
59  uint8_t byte = this->data_[index];
60 
61  // index 0..2 are the fixed header
62  if (index < sizeof(PM1006_RESPONSE_HEADER)) {
63  return byte == PM1006_RESPONSE_HEADER[index];
64  }
65 
66  // just some additional notes here:
67  // index 3..4 is unused
68  // index 5..6 is our PM2.5 reading (3..6 is called DF1-DF4 in the datasheet at
69  // http://www.jdscompany.co.kr/download.asp?gubun=07&filename=PM1006_LED_PARTICLE_SENSOR_MODULE_SPECIFICATIONS.pdf
70  // that datasheet goes on up to DF16, which is unused for PM1006 but used in PM1006K
71  // so this code should be trivially extensible to support that one later
72  if (index < (sizeof(PM1006_RESPONSE_HEADER) + 16))
73  return true;
74 
75  // checksum
76  if (index == (sizeof(PM1006_RESPONSE_HEADER) + 16)) {
77  uint8_t checksum = pm1006_checksum_(this->data_, sizeof(PM1006_RESPONSE_HEADER) + 17);
78  if (checksum != 0) {
79  ESP_LOGW(TAG, "PM1006 checksum is wrong: %02x, expected zero", checksum);
80  return false;
81  }
82  return {};
83  }
84 
85  return false;
86 }
87 
89  const int pm_2_5_concentration = this->get_16_bit_uint_(5);
90 
91  ESP_LOGD(TAG, "Got PM2.5 Concentration: %d µg/m³", pm_2_5_concentration);
92 
93  if (this->pm_2_5_sensor_ != nullptr) {
94  this->pm_2_5_sensor_->publish_state(pm_2_5_concentration);
95  }
96 }
97 
98 uint16_t PM1006Component::get_16_bit_uint_(uint8_t start_index) const {
99  return encode_uint16(this->data_[start_index], this->data_[start_index + 1]);
100 }
101 
102 } // namespace pm1006
103 } // namespace esphome
const float DATA
For components that import data from directly connected sensors like DHT.
Definition: component.cpp:19
void write_array(const uint8_t *data, size_t len)
Definition: uart.h:21
sensor::Sensor * pm_2_5_sensor_
Definition: pm1006.h:28
void dump_config() override
Definition: pm1006.cpp:16
uint16_t get_16_bit_uint_(uint8_t start_index) const
Definition: pm1006.cpp:98
float get_setup_priority() const override
Definition: pm1006.cpp:47
void check_uart_settings(uint32_t baud_rate, uint8_t stop_bits=1, UARTParityOptions parity=UART_CONFIG_PARITY_NONE, uint8_t data_bits=8)
Check that the configuration of the UART bus matches the provided values and otherwise print a warnin...
Definition: uart.cpp:13
bool read_byte(uint8_t *data)
Definition: uart.h:29
void publish_state(float state)
Publish a new state to the front-end.
Definition: sensor.cpp:39
constexpr uint16_t encode_uint16(uint8_t msb, uint8_t lsb)
Encode a 16-bit value given the most and least significant byte.
Definition: helpers.h:182
uint8_t checksum
Definition: bl0939.h:35
uint8_t pm1006_checksum_(const uint8_t *command_data, uint8_t length) const
Definition: pm1006.cpp:49
optional< bool > check_byte_() const
Definition: pm1006.cpp:57
uint16_t length
Definition: tt21100.cpp:12
This is a workaround until we can figure out a way to get the tflite-micro idf component code availab...
Definition: a01nyub.cpp:7