ESPHome 2026.2.1
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 {
5namespace pm1006 {
6
7static const char *const TAG = "pm1006";
8
9static const uint8_t PM1006_RESPONSE_HEADER[] = {0x16, 0x11, 0x0B};
10static 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
47uint8_t PM1006Component::pm1006_checksum_(const uint8_t *command_data, uint8_t length) const {
48 uint8_t sum = 0;
49 for (uint8_t i = 0; i < length; i++) {
50 sum += command_data[i];
51 }
52 return sum;
53}
54
56 const uint8_t index = this->data_index_;
57 const uint8_t byte = this->data_[index];
58
59 // index 0..2 are the fixed header
60 if (index < sizeof(PM1006_RESPONSE_HEADER)) {
61 return byte == PM1006_RESPONSE_HEADER[index];
62 }
63
64 // just some additional notes here:
65 // index 3..4 is unused
66 // index 5..6 is our PM2.5 reading (3..6 is called DF1-DF4 in the datasheet at
67 // http://www.jdscompany.co.kr/download.asp?gubun=07&filename=PM1006_LED_PARTICLE_SENSOR_MODULE_SPECIFICATIONS.pdf
68 // that datasheet goes on up to DF16, which is unused for PM1006 but used in PM1006K
69 // so this code should be trivially extensible to support that one later
70 if (index < (sizeof(PM1006_RESPONSE_HEADER) + 16))
71 return true;
72
73 // checksum
74 if (index == (sizeof(PM1006_RESPONSE_HEADER) + 16)) {
75 uint8_t checksum = pm1006_checksum_(this->data_, sizeof(PM1006_RESPONSE_HEADER) + 17);
76 if (checksum != 0) {
77 ESP_LOGW(TAG, "PM1006 checksum is wrong: %02x, expected zero", checksum);
78 return false;
79 }
80 return {};
81 }
82
83 return false;
84}
85
87 const uint16_t pm_2_5_concentration = this->get_16_bit_uint_(5);
88
89 ESP_LOGD(TAG, "Got PM2.5 Concentration: %d µg/m³", pm_2_5_concentration);
90
91 if (this->pm_2_5_sensor_ != nullptr) {
92 this->pm_2_5_sensor_->publish_state(pm_2_5_concentration);
93 }
94}
95
96} // namespace pm1006
97} // namespace esphome
uint8_t checksum
Definition bl0906.h:3
uint8_t pm1006_checksum_(const uint8_t *command_data, uint8_t length) const
Definition pm1006.cpp:47
uint16_t get_16_bit_uint_(uint8_t start_index) const
Definition pm1006.h:25
sensor::Sensor * pm_2_5_sensor_
Definition pm1006.h:29
optional< bool > check_byte_() const
Definition pm1006.cpp:55
void publish_state(float state)
Publish a new state to the front-end.
Definition sensor.cpp:65
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:16
bool read_byte(uint8_t *data)
Definition uart.h:34
void write_array(const uint8_t *data, size_t len)
Definition uart.h:26
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7
uint16_t length
Definition tt21100.cpp:0