1
0
mirror of https://github.com/esphome/esphome.git synced 2025-04-16 15:50:28 +01:00

138 lines
4.5 KiB
C++

#include "qwiic_pir.h"
#include "esphome/core/log.h"
namespace esphome {
namespace qwiic_pir {
static const char *const TAG = "qwiic_pir";
void QwiicPIRComponent::setup() {
ESP_LOGCONFIG(TAG, "Setting up Qwiic PIR...");
// Verify I2C communcation by reading and verifying the chip ID
uint8_t chip_id;
if (!this->read_byte(QWIIC_PIR_CHIP_ID, &chip_id)) {
ESP_LOGE(TAG, "Failed to read the chip's ID");
this->error_code_ = ERROR_COMMUNICATION_FAILED;
this->mark_failed();
return;
}
if (chip_id != QWIIC_PIR_DEVICE_ID) {
ESP_LOGE(TAG, "Unknown chip ID, is this a Qwiic PIR?");
this->error_code_ = ERROR_WRONG_CHIP_ID;
this->mark_failed();
return;
}
if (!this->write_byte_16(QWIIC_PIR_DEBOUNCE_TIME, this->debounce_time_)) {
ESP_LOGE(TAG, "Failed to configure debounce time.");
this->error_code_ = ERROR_COMMUNICATION_FAILED;
this->mark_failed();
return;
}
if (this->debounce_mode_ == NATIVE_DEBOUNCE_MODE) {
// Publish the starting raw state of the PIR sensor
// If NATIVE mode, the binary_sensor state would be unknown until a motion event
if (!this->read_byte(QWIIC_PIR_EVENT_STATUS, &this->event_register_.reg)) {
ESP_LOGE(TAG, "Failed to read initial sensor state.");
this->error_code_ = ERROR_COMMUNICATION_FAILED;
this->mark_failed();
return;
}
this->publish_state(this->event_register_.raw_reading);
}
}
void QwiicPIRComponent::loop() {
// Read Event Register
if (!this->read_byte(QWIIC_PIR_EVENT_STATUS, &this->event_register_.reg)) {
ESP_LOGW(TAG, "Failed to communicate with sensor");
return;
}
if (this->debounce_mode_ == HYBRID_DEBOUNCE_MODE) {
// Use a combination of the raw sensor reading and the device's event detection to determine state
// - The device is hardcoded to use a debounce time of 1 ms in this mode
// - Any event, even if it is object_removed, implies motion was active since the last loop, so publish true
// - Use ESPHome's built-in filters for debouncing
this->publish_state(this->event_register_.raw_reading || this->event_register_.event_available);
if (this->event_register_.event_available) {
this->clear_events_();
}
} else if (this->debounce_mode_ == NATIVE_DEBOUNCE_MODE) {
// Uses the device's firmware to debounce the signal
// - Follows the logic of SparkFun's example implementation:
// https://github.com/sparkfun/SparkFun_Qwiic_PIR_Arduino_Library/blob/master/examples/Example2_PrintPIRStatus/Example2_PrintPIRStatus.ino
// (accessed July 2023)
// - Is unreliable at detecting an object being removed, especially at debounce rates even slightly large
if (this->event_register_.event_available) {
// If an object is detected, publish true
if (this->event_register_.object_detected)
this->publish_state(true);
// If an object has been removed, publish false
if (this->event_register_.object_removed)
this->publish_state(false);
this->clear_events_();
}
} else if (this->debounce_mode_ == RAW_DEBOUNCE_MODE) {
// Publishes the raw PIR sensor reading with no further logic
// - May miss a very short motion detection if the ESP's loop time is slow
this->publish_state(this->event_register_.raw_reading);
}
}
void QwiicPIRComponent::dump_config() {
ESP_LOGCONFIG(TAG, "Qwiic PIR:");
if (this->debounce_mode_ == RAW_DEBOUNCE_MODE) {
ESP_LOGCONFIG(TAG, " Debounce Mode: RAW");
} else if (this->debounce_mode_ == NATIVE_DEBOUNCE_MODE) {
ESP_LOGCONFIG(TAG, " Debounce Mode: NATIVE");
ESP_LOGCONFIG(TAG, " Debounce Time: %ums", this->debounce_time_);
} else if (this->debounce_mode_ == HYBRID_DEBOUNCE_MODE) {
ESP_LOGCONFIG(TAG, " Debounce Mode: HYBRID");
}
switch (this->error_code_) {
case NONE:
break;
case ERROR_COMMUNICATION_FAILED:
ESP_LOGE(TAG, " Communication with Qwiic PIR failed!");
break;
case ERROR_WRONG_CHIP_ID:
ESP_LOGE(TAG, " Qwiic PIR has wrong chip ID - please verify you are using a Qwiic PIR");
break;
default:
ESP_LOGE(TAG, " Qwiic PIR error code %d", (int) this->error_code_);
break;
}
LOG_I2C_DEVICE(this);
LOG_BINARY_SENSOR(" ", "Qwiic PIR Binary Sensor", this);
}
void QwiicPIRComponent::clear_events_() {
// Clear event status register
if (!this->write_byte(QWIIC_PIR_EVENT_STATUS, 0x00))
ESP_LOGW(TAG, "Failed to clear events on sensor");
}
} // namespace qwiic_pir
} // namespace esphome