ESPHome  2024.5.0
qwiic_pir.cpp
Go to the documentation of this file.
1 #include "qwiic_pir.h"
2 #include "esphome/core/log.h"
3 
4 namespace esphome {
5 namespace qwiic_pir {
6 
7 static const char *const TAG = "qwiic_pir";
8 
10  ESP_LOGCONFIG(TAG, "Setting up Qwiic PIR...");
11 
12  // Verify I2C communcation by reading and verifying the chip ID
13  uint8_t chip_id;
14 
15  if (!this->read_byte(QWIIC_PIR_CHIP_ID, &chip_id)) {
16  ESP_LOGE(TAG, "Failed to read the chip's ID");
17 
18  this->error_code_ = ERROR_COMMUNICATION_FAILED;
19  this->mark_failed();
20 
21  return;
22  }
23 
24  if (chip_id != QWIIC_PIR_DEVICE_ID) {
25  ESP_LOGE(TAG, "Unknown chip ID, is this a Qwiic PIR?");
26 
27  this->error_code_ = ERROR_WRONG_CHIP_ID;
28  this->mark_failed();
29 
30  return;
31  }
32 
34  ESP_LOGE(TAG, "Failed to configure debounce time.");
35 
36  this->error_code_ = ERROR_COMMUNICATION_FAILED;
37  this->mark_failed();
38 
39  return;
40  }
41 
42  if (this->debounce_mode_ == NATIVE_DEBOUNCE_MODE) {
43  // Publish the starting raw state of the PIR sensor
44  // If NATIVE mode, the binary_sensor state would be unknown until a motion event
45  if (!this->read_byte(QWIIC_PIR_EVENT_STATUS, &this->event_register_.reg)) {
46  ESP_LOGE(TAG, "Failed to read initial sensor state.");
47 
48  this->error_code_ = ERROR_COMMUNICATION_FAILED;
49  this->mark_failed();
50 
51  return;
52  }
53 
54  this->publish_state(this->event_register_.raw_reading);
55  }
56 }
57 
59  // Read Event Register
60  if (!this->read_byte(QWIIC_PIR_EVENT_STATUS, &this->event_register_.reg)) {
61  ESP_LOGW(TAG, "Failed to communicate with sensor");
62 
63  return;
64  }
65 
66  if (this->debounce_mode_ == HYBRID_DEBOUNCE_MODE) {
67  // Use a combination of the raw sensor reading and the device's event detection to determine state
68  // - The device is hardcoded to use a debounce time of 1 ms in this mode
69  // - Any event, even if it is object_removed, implies motion was active since the last loop, so publish true
70  // - Use ESPHome's built-in filters for debouncing
71  this->publish_state(this->event_register_.raw_reading || this->event_register_.event_available);
72 
73  if (this->event_register_.event_available) {
74  this->clear_events_();
75  }
76  } else if (this->debounce_mode_ == NATIVE_DEBOUNCE_MODE) {
77  // Uses the device's firmware to debounce the signal
78  // - Follows the logic of SparkFun's example implementation:
79  // https://github.com/sparkfun/SparkFun_Qwiic_PIR_Arduino_Library/blob/master/examples/Example2_PrintPIRStatus/Example2_PrintPIRStatus.ino
80  // (accessed July 2023)
81  // - Is unreliable at detecting an object being removed, especially at debounce rates even slightly large
82  if (this->event_register_.event_available) {
83  // If an object is detected, publish true
84  if (this->event_register_.object_detected)
85  this->publish_state(true);
86 
87  // If an object has been removed, publish false
88  if (this->event_register_.object_removed)
89  this->publish_state(false);
90 
91  this->clear_events_();
92  }
93  } else if (this->debounce_mode_ == RAW_DEBOUNCE_MODE) {
94  // Publishes the raw PIR sensor reading with no further logic
95  // - May miss a very short motion detection if the ESP's loop time is slow
96  this->publish_state(this->event_register_.raw_reading);
97  }
98 }
99 
101  ESP_LOGCONFIG(TAG, "Qwiic PIR:");
102 
103  if (this->debounce_mode_ == RAW_DEBOUNCE_MODE) {
104  ESP_LOGCONFIG(TAG, " Debounce Mode: RAW");
105  } else if (this->debounce_mode_ == NATIVE_DEBOUNCE_MODE) {
106  ESP_LOGCONFIG(TAG, " Debounce Mode: NATIVE");
107  ESP_LOGCONFIG(TAG, " Debounce Time: %ums", this->debounce_time_);
108  } else if (this->debounce_mode_ == HYBRID_DEBOUNCE_MODE) {
109  ESP_LOGCONFIG(TAG, " Debounce Mode: HYBRID");
110  }
111 
112  switch (this->error_code_) {
113  case NONE:
114  break;
116  ESP_LOGE(TAG, " Communication with Qwiic PIR failed!");
117  break;
118  case ERROR_WRONG_CHIP_ID:
119  ESP_LOGE(TAG, " Qwiic PIR has wrong chip ID - please verify you are using a Qwiic PIR");
120  break;
121  default:
122  ESP_LOGE(TAG, " Qwiic PIR error code %d", (int) this->error_code_);
123  break;
124  }
125 
126  LOG_I2C_DEVICE(this);
127  LOG_BINARY_SENSOR(" ", "Qwiic PIR Binary Sensor", this);
128 }
129 
131  // Clear event status register
132  if (!this->write_byte(QWIIC_PIR_EVENT_STATUS, 0x00))
133  ESP_LOGW(TAG, "Failed to clear events on sensor");
134 }
135 
136 } // namespace qwiic_pir
137 } // namespace esphome
bool read_byte(uint8_t a_register, uint8_t *data, bool stop=true)
Definition: i2c.h:235
enum esphome::qwiic_pir::QwiicPIRComponent::ErrorCode NONE
union esphome::qwiic_pir::QwiicPIRComponent::@102 event_register_
void publish_state(bool state)
Publish a new state to the front-end.
bool write_byte(uint8_t a_register, uint8_t data, bool stop=true)
Definition: i2c.h:262
virtual void mark_failed()
Mark this component as failed.
Definition: component.cpp:118
This is a workaround until we can figure out a way to get the tflite-micro idf component code availab...
Definition: a01nyub.cpp:7
bool write_byte_16(uint8_t a_register, uint16_t data)
Definition: i2c.h:266