ESPHome 2026.10.0-dev
Loading...
Searching...
No Matches
pm1006.cpp
Go to the documentation of this file.
1#include "pm1006.h"
2#include "esphome/core/log.h"
3
4namespace esphome::pm1006 {
5
6static const char *const TAG = "pm1006";
7
8static const uint8_t PM1006_RESPONSE_HEADER[] = {0x16, 0x11, 0x0B};
9static const uint8_t PM1006_REQUEST[] = {0x11, 0x02, 0x0B, 0x01, 0xE1};
10
12 // because this implementation is currently rx-only, there is nothing to setup
13}
14
16 ESP_LOGCONFIG(TAG, "PM1006:");
17 LOG_SENSOR(" ", "PM2.5", this->pm_2_5_sensor_);
18 LOG_UPDATE_INTERVAL(this);
19}
20
22 ESP_LOGV(TAG, "sending measurement request");
23 this->write_array(PM1006_REQUEST, sizeof(PM1006_REQUEST));
24}
25
27 while (this->available() != 0) {
28 this->read_byte(&this->data_[this->data_index_]);
29 auto check = this->check_byte_();
30 if (!check.has_value()) {
31 // finished
32 this->parse_data_();
33 this->data_index_ = 0;
34 } else if (!*check) {
35 // wrong data
36 ESP_LOGV(TAG, "Byte %i of received data frame is invalid.", this->data_index_);
37 this->data_index_ = 0;
38 } else {
39 // next byte
40 this->data_index_++;
41 }
42 }
43}
44
45uint8_t PM1006Component::pm1006_checksum_(const uint8_t *command_data, uint8_t length) const {
46 uint8_t sum = 0;
47 for (uint8_t i = 0; i < length; i++) {
48 sum += command_data[i];
49 }
50 return sum;
51}
52
53optional<bool> PM1006Component::check_byte_() const {
54 const uint8_t index = this->data_index_;
55 const uint8_t byte = this->data_[index];
56
57 // index 0..2 are the fixed header
58 if (index < sizeof(PM1006_RESPONSE_HEADER)) {
59 return byte == PM1006_RESPONSE_HEADER[index];
60 }
61
62 // just some additional notes here:
63 // index 3..4 is unused
64 // index 5..6 is our PM2.5 reading (3..6 is called DF1-DF4 in the datasheet at
65 // http://www.jdscompany.co.kr/download.asp?gubun=07&filename=PM1006_LED_PARTICLE_SENSOR_MODULE_SPECIFICATIONS.pdf
66 // that datasheet goes on up to DF16, which is unused for PM1006 but used in PM1006K
67 // so this code should be trivially extensible to support that one later
68 if (index < (sizeof(PM1006_RESPONSE_HEADER) + 16))
69 return true;
70
71 // checksum
72 if (index == (sizeof(PM1006_RESPONSE_HEADER) + 16)) {
73 uint8_t checksum = pm1006_checksum_(this->data_, sizeof(PM1006_RESPONSE_HEADER) + 17);
74 if (checksum != 0) {
75 ESP_LOGW(TAG, "PM1006 checksum is wrong: %02x, expected zero", checksum);
76 return false;
77 }
78 return {};
79 }
80
81 return false;
82}
83
85 const uint16_t pm_2_5_concentration = this->get_16_bit_uint_(5);
86
87 ESP_LOGD(TAG, "Got PM2.5 Concentration: %d µg/m³", pm_2_5_concentration);
88
89 if (this->pm_2_5_sensor_ != nullptr) {
90 this->pm_2_5_sensor_->publish_state(pm_2_5_concentration);
91 }
92}
93
94} // namespace esphome::pm1006
uint8_t checksum
Definition bl0906.h:3
uint8_t pm1006_checksum_(const uint8_t *command_data, uint8_t length) const
Definition pm1006.cpp:45
uint16_t get_16_bit_uint_(uint8_t start_index) const
Definition pm1006.h:24
sensor::Sensor * pm_2_5_sensor_
Definition pm1006.h:28
optional< bool > check_byte_() const
Definition pm1006.cpp:53
void publish_state(float state)
Publish a new state to the front-end.
Definition sensor.cpp:68
bool read_byte(uint8_t *data)
Definition uart.h:35
void write_array(const uint8_t *data, size_t len)
Definition uart.h:27
uint16_t length
Definition tt21100.cpp:0