ESPHome 2026.5.0b1
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 this->check_uart_settings(9600);
20}
21
23 ESP_LOGV(TAG, "sending measurement request");
24 this->write_array(PM1006_REQUEST, sizeof(PM1006_REQUEST));
25}
26
28 while (this->available() != 0) {
29 this->read_byte(&this->data_[this->data_index_]);
30 auto check = this->check_byte_();
31 if (!check.has_value()) {
32 // finished
33 this->parse_data_();
34 this->data_index_ = 0;
35 } else if (!*check) {
36 // wrong data
37 ESP_LOGV(TAG, "Byte %i of received data frame is invalid.", this->data_index_);
38 this->data_index_ = 0;
39 } else {
40 // next byte
41 this->data_index_++;
42 }
43 }
44}
45
46uint8_t PM1006Component::pm1006_checksum_(const uint8_t *command_data, uint8_t length) const {
47 uint8_t sum = 0;
48 for (uint8_t i = 0; i < length; i++) {
49 sum += command_data[i];
50 }
51 return sum;
52}
53
54optional<bool> PM1006Component::check_byte_() const {
55 const uint8_t index = this->data_index_;
56 const uint8_t byte = this->data_[index];
57
58 // index 0..2 are the fixed header
59 if (index < sizeof(PM1006_RESPONSE_HEADER)) {
60 return byte == PM1006_RESPONSE_HEADER[index];
61 }
62
63 // just some additional notes here:
64 // index 3..4 is unused
65 // index 5..6 is our PM2.5 reading (3..6 is called DF1-DF4 in the datasheet at
66 // http://www.jdscompany.co.kr/download.asp?gubun=07&filename=PM1006_LED_PARTICLE_SENSOR_MODULE_SPECIFICATIONS.pdf
67 // that datasheet goes on up to DF16, which is unused for PM1006 but used in PM1006K
68 // so this code should be trivially extensible to support that one later
69 if (index < (sizeof(PM1006_RESPONSE_HEADER) + 16))
70 return true;
71
72 // checksum
73 if (index == (sizeof(PM1006_RESPONSE_HEADER) + 16)) {
74 uint8_t checksum = pm1006_checksum_(this->data_, sizeof(PM1006_RESPONSE_HEADER) + 17);
75 if (checksum != 0) {
76 ESP_LOGW(TAG, "PM1006 checksum is wrong: %02x, expected zero", checksum);
77 return false;
78 }
79 return {};
80 }
81
82 return false;
83}
84
86 const uint16_t pm_2_5_concentration = this->get_16_bit_uint_(5);
87
88 ESP_LOGD(TAG, "Got PM2.5 Concentration: %d µg/m³", pm_2_5_concentration);
89
90 if (this->pm_2_5_sensor_ != nullptr) {
91 this->pm_2_5_sensor_->publish_state(pm_2_5_concentration);
92 }
93}
94
95} // 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:46
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:54
void publish_state(float state)
Publish a new state to the front-end.
Definition sensor.cpp:68
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
uint16_t length
Definition tt21100.cpp:0