3.3.7
This commit is contained in:
+230
@@ -0,0 +1,230 @@
|
||||
// Copyright 2025 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/*
|
||||
* This example is an example code that will create a Matter Device which can be
|
||||
* commissioned and controlled from a Matter Environment APP.
|
||||
* Additionally the ESP32 will send debug messages indicating the Matter activity.
|
||||
* Turning DEBUG Level ON may be useful to following Matter Accessory and Controller messages.
|
||||
*
|
||||
* The example will create a Matter Occupancy Sensor Device.
|
||||
* The Occupancy Sensor will be simulated to toggle occupancy every 2 minutes.
|
||||
* When occupancy is detected, the sensor holds the "occupied" state for the HoldTime duration
|
||||
* (default: 30 seconds, configurable via Matter Controller). After HoldTime expires,
|
||||
* the sensor automatically switches to "unoccupied" state.
|
||||
*
|
||||
* The HoldTime attribute allows you to adjust how long the active status is retained
|
||||
* after the person leaves. The HoldTime can be changed by a Matter Controller, and the
|
||||
* onHoldTimeChange() callback is used to update the simulated sensor functionality.
|
||||
*
|
||||
* The HoldTime value is persisted to Preferences (NVS) and restored on reboot, so the
|
||||
* last configured HoldTime value is maintained across device restarts.
|
||||
*
|
||||
* The onboard button can be kept pressed for 5 seconds to decommission the Matter Node.
|
||||
* The example will also show the manual commissioning code and QR code to be used in the Matter environment.
|
||||
*
|
||||
*/
|
||||
|
||||
// Matter Manager
|
||||
#include <Matter.h>
|
||||
// CONFIG_ENABLE_CHIPOBLE is enabled when BLE is used to commission the Matter Network
|
||||
#if !CONFIG_ENABLE_CHIPOBLE
|
||||
// if the device can be commissioned using BLE, WiFi is not used - save flash space
|
||||
#include <WiFi.h>
|
||||
// WiFi is manually set and started
|
||||
const char *ssid = "your-ssid"; // Change this to your WiFi SSID
|
||||
const char *password = "your-password"; // Change this to your WiFi password
|
||||
#endif
|
||||
#include <Preferences.h>
|
||||
|
||||
// HoldTime configuration constants
|
||||
const uint16_t HOLD_TIME_MIN = 0; // Minimum HoldTime in seconds
|
||||
const uint16_t HOLD_TIME_MAX = 3600; // Maximum HoldTime in seconds (1 hour)
|
||||
const uint16_t HOLD_TIME_DEFAULT = 30; // Default HoldTime in seconds
|
||||
|
||||
// List of Matter Endpoints for this Node
|
||||
// Matter Occupancy Sensor Endpoint
|
||||
MatterOccupancySensor OccupancySensor;
|
||||
|
||||
// Preferences to store HoldTime value across reboots
|
||||
Preferences matterPref;
|
||||
const char *holdTimePrefKey = "HoldTime";
|
||||
|
||||
// set your board USER BUTTON pin here - decommissioning only
|
||||
const uint8_t buttonPin = BOOT_PIN; // Set your pin here. Using BOOT Button.
|
||||
|
||||
// Button control
|
||||
uint32_t button_time_stamp = 0; // debouncing control
|
||||
bool button_state = false; // false = released | true = pressed
|
||||
const uint32_t decommissioningTimeout = 5000; // keep the button pressed for 5s, or longer, to decommission
|
||||
|
||||
// Simulated Occupancy Sensor with HoldTime support
|
||||
// When occupancy is detected, it holds the "occupied" state for HoldTime seconds
|
||||
// After HoldTime expires, it automatically switches to "unoccupied"
|
||||
//
|
||||
// Behavior for different HoldTime vs detectionInterval relationships:
|
||||
// - holdTime_ms < detectionInterval: State switches to unoccupied after HoldTime, then waits for next detection
|
||||
// - holdTime_ms == detectionInterval: If detections keep coming, timer resets (continuous occupancy)
|
||||
// - holdTime_ms > detectionInterval: If detections keep coming, timer resets (continuous occupancy)
|
||||
// If detections stop, HoldTime expires after the last detection
|
||||
bool simulatedHWOccupancySensor() {
|
||||
static bool occupancyState = false;
|
||||
static uint32_t lastDetectionTime = 0;
|
||||
static uint32_t lastDetectionEvent = millis();
|
||||
const uint32_t detectionInterval = 120000; // Simulate detection every 2 minutes
|
||||
|
||||
// Get current HoldTime from the sensor (can be changed by Matter Controller)
|
||||
uint32_t holdTime_ms = OccupancySensor.getHoldTime() * 1000; // Convert seconds to milliseconds
|
||||
|
||||
// Check HoldTime expiration FIRST (before processing new detections)
|
||||
// This ensures HoldTime can expire even if a detection occurs in the same iteration
|
||||
if (occupancyState && (millis() - lastDetectionTime > holdTime_ms)) {
|
||||
occupancyState = false;
|
||||
// Reset detection interval counter so next detection can happen immediately
|
||||
// This makes the simulation more responsive after the room becomes unoccupied
|
||||
lastDetectionEvent = millis();
|
||||
Serial.println("HoldTime expired. Switching to unoccupied state.");
|
||||
}
|
||||
|
||||
// Simulate periodic occupancy detection (e.g., motion detected)
|
||||
// Check this AFTER HoldTime expiration so new detections can immediately re-trigger occupancy
|
||||
if (millis() - lastDetectionEvent > detectionInterval) {
|
||||
// New detection event occurred
|
||||
lastDetectionEvent = millis();
|
||||
|
||||
if (!occupancyState) {
|
||||
// Transition from unoccupied to occupied - start hold timer
|
||||
occupancyState = true;
|
||||
lastDetectionTime = millis();
|
||||
Serial.printf("Occupancy detected! Holding state for %u seconds (HoldTime)\n", OccupancySensor.getHoldTime());
|
||||
} else {
|
||||
// Already occupied - new detection extends the hold period by resetting the timer
|
||||
// This simulates continuous occupancy (person still present)
|
||||
lastDetectionTime = millis();
|
||||
Serial.printf("Occupancy still detected. Resetting hold timer to %u seconds (HoldTime)\n", OccupancySensor.getHoldTime());
|
||||
}
|
||||
}
|
||||
|
||||
return occupancyState;
|
||||
}
|
||||
|
||||
void setup() {
|
||||
// Initialize the USER BUTTON (Boot button) that will be used to decommission the Matter Node
|
||||
pinMode(buttonPin, INPUT_PULLUP);
|
||||
|
||||
Serial.begin(115200);
|
||||
|
||||
// CONFIG_ENABLE_CHIPOBLE is enabled when BLE is used to commission the Matter Network
|
||||
#if !CONFIG_ENABLE_CHIPOBLE
|
||||
// Manually connect to WiFi
|
||||
WiFi.begin(ssid, password);
|
||||
// Wait for connection
|
||||
while (WiFi.status() != WL_CONNECTED) {
|
||||
delay(500);
|
||||
Serial.print(".");
|
||||
}
|
||||
Serial.println();
|
||||
#endif
|
||||
|
||||
// Initialize Preferences and read stored HoldTime value
|
||||
matterPref.begin("MatterPrefs", false);
|
||||
uint16_t storedHoldTime = matterPref.getUShort(holdTimePrefKey, HOLD_TIME_DEFAULT);
|
||||
|
||||
// Validate stored value is within limits
|
||||
if (storedHoldTime < HOLD_TIME_MIN || storedHoldTime > HOLD_TIME_MAX) {
|
||||
uint16_t invalidValue = storedHoldTime;
|
||||
storedHoldTime = HOLD_TIME_DEFAULT;
|
||||
Serial.printf("Invalid stored HoldTime (%u), using default: %u seconds\n", invalidValue, HOLD_TIME_DEFAULT);
|
||||
} else if (storedHoldTime != HOLD_TIME_DEFAULT) {
|
||||
Serial.printf("Restored HoldTime from Preferences: %u seconds\n", storedHoldTime);
|
||||
}
|
||||
|
||||
// Register callback for HoldTime changes from Matter Controller
|
||||
OccupancySensor.onHoldTimeChange([](uint16_t holdTime_seconds) -> bool {
|
||||
Serial.printf("HoldTime changed to %u seconds by Matter Controller\n", holdTime_seconds);
|
||||
// Store the new HoldTime value to Preferences for persistence across reboots
|
||||
matterPref.putUShort(holdTimePrefKey, holdTime_seconds);
|
||||
// The callback can return false to reject the change, or true to accept it
|
||||
// In this case, we always accept the change and update the simulator
|
||||
return true;
|
||||
});
|
||||
|
||||
// set initial occupancy sensor state as false and connected to a PIR sensor type (default)
|
||||
OccupancySensor.begin();
|
||||
|
||||
// Matter beginning - Last step, after all EndPoints are initialized
|
||||
Matter.begin();
|
||||
|
||||
// Set HoldTimeLimits after Matter.begin() (optional, but recommended for validation)
|
||||
if (!OccupancySensor.setHoldTimeLimits(HOLD_TIME_MIN, HOLD_TIME_MAX, HOLD_TIME_DEFAULT)) {
|
||||
Serial.println("Warning: Failed to set HoldTimeLimits");
|
||||
} else {
|
||||
Serial.printf("HoldTimeLimits set: Min=%u, Max=%u, Default=%u seconds\n", HOLD_TIME_MIN, HOLD_TIME_MAX, HOLD_TIME_DEFAULT);
|
||||
}
|
||||
|
||||
// Set initial HoldTime (use stored value if valid, otherwise use default)
|
||||
// This must be done after Matter.begin() because setHoldTime() requires the Matter event loop
|
||||
if (!OccupancySensor.setHoldTime(storedHoldTime)) {
|
||||
Serial.printf("Warning: Failed to set HoldTime to %u seconds\n", storedHoldTime);
|
||||
} else {
|
||||
Serial.printf("HoldTime set to: %u seconds\n", storedHoldTime);
|
||||
}
|
||||
|
||||
Serial.printf("Initial HoldTime: %u seconds\n", OccupancySensor.getHoldTime());
|
||||
|
||||
// Check Matter Accessory Commissioning state, which may change during execution of loop()
|
||||
if (!Matter.isDeviceCommissioned()) {
|
||||
Serial.println("");
|
||||
Serial.println("Matter Node is not commissioned yet.");
|
||||
Serial.println("Initiate the device discovery in your Matter environment.");
|
||||
Serial.println("Commission it to your Matter hub with the manual pairing code or QR code");
|
||||
Serial.printf("Manual pairing code: %s\r\n", Matter.getManualPairingCode().c_str());
|
||||
Serial.printf("QR code URL: %s\r\n", Matter.getOnboardingQRCodeUrl().c_str());
|
||||
// waits for Matter Occupancy Sensor Commissioning.
|
||||
uint32_t timeCount = 0;
|
||||
while (!Matter.isDeviceCommissioned()) {
|
||||
delay(100);
|
||||
if ((timeCount++ % 50) == 0) { // 50*100ms = 5 sec
|
||||
Serial.println("Matter Node not commissioned yet. Waiting for commissioning.");
|
||||
}
|
||||
}
|
||||
Serial.println("Matter Node is commissioned and connected to the network. Ready for use.");
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// Check if the button has been pressed
|
||||
if (digitalRead(buttonPin) == LOW && !button_state) {
|
||||
// deals with button debouncing
|
||||
button_time_stamp = millis(); // record the time while the button is pressed.
|
||||
button_state = true; // pressed.
|
||||
}
|
||||
|
||||
if (button_state && digitalRead(buttonPin) == HIGH) {
|
||||
button_state = false; // released
|
||||
}
|
||||
|
||||
// Onboard User Button is kept pressed for longer than 5 seconds in order to decommission matter node
|
||||
uint32_t time_diff = millis() - button_time_stamp;
|
||||
if (button_state && time_diff > decommissioningTimeout) {
|
||||
Serial.println("Decommissioning Occupancy Sensor Matter Accessory. It shall be commissioned again.");
|
||||
Matter.decommission();
|
||||
button_time_stamp = millis(); // avoid running decommissining again, reboot takes a second or so
|
||||
}
|
||||
|
||||
// Check Simulated Occupancy Sensor and set Matter Attribute
|
||||
OccupancySensor.setOccupancy(simulatedHWOccupancySensor());
|
||||
|
||||
delay(50);
|
||||
}
|
||||
@@ -0,0 +1,329 @@
|
||||
# Matter Occupancy Sensor with HoldTime Example
|
||||
|
||||
This example demonstrates how to create a Matter-compatible occupancy sensor device with HoldTime functionality using an ESP32 SoC microcontroller.\
|
||||
The application showcases Matter commissioning, sensor data reporting to smart home ecosystems, automatic simulation of occupancy state changes, and HoldTime configuration with persistence across reboots.
|
||||
|
||||
## Supported Targets
|
||||
|
||||
| SoC | Wi-Fi | Thread | BLE Commissioning | Status |
|
||||
| --- | ---- | ------ | ----------------- | ------ |
|
||||
| ESP32 | ✅ | ❌ | ❌ | Fully supported |
|
||||
| ESP32-S2 | ✅ | ❌ | ❌ | Fully supported |
|
||||
| ESP32-S3 | ✅ | ❌ | ✅ | Fully supported |
|
||||
| ESP32-C3 | ✅ | ❌ | ✅ | Fully supported |
|
||||
| ESP32-C5 | ❌ | ✅ | ✅ | Supported (Thread only) |
|
||||
| ESP32-C6 | ✅ | ❌ | ✅ | Fully supported |
|
||||
| ESP32-H2 | ❌ | ✅ | ✅ | Supported (Thread only) |
|
||||
|
||||
### Note on Commissioning:
|
||||
|
||||
- **ESP32 & ESP32-S2** do not support commissioning over Bluetooth LE. For these chips, you must provide Wi-Fi credentials directly in the sketch code so they can connect to your network manually.
|
||||
- **ESP32-C6** Although it has Thread support, the ESP32 Arduino Matter Library has been pre compiled using Wi-Fi only. In order to configure it for Thread-only operation it is necessary to build the project using Arduino as an IDF Component and to disable the Matter Wi-Fi station feature.
|
||||
- **ESP32-C5** Although it has Wi-Fi 2.4 GHz and 5 GHz support, the ESP32 Arduino Matter Library has been pre compiled using Thread only. In order to configure it for Wi-Fi operation it is necessary to build the project using Arduino as an ESP-IDF component and disable Thread network, keeping only Wi-Fi station.
|
||||
|
||||
## Features
|
||||
|
||||
- Matter protocol implementation for an occupancy sensor device with HoldTime support
|
||||
- Support for both Wi-Fi and Thread(*) connectivity
|
||||
- Occupancy state reporting (Occupied/Unoccupied)
|
||||
- HoldTime attribute for configuring how long the sensor holds the "occupied" state
|
||||
- HoldTimeLimits (min, max, default) for validation and controller guidance
|
||||
- HoldTime persistence across reboots using Preferences (NVS)
|
||||
- Automatic simulation of occupancy state changes every 2 minutes with HoldTime expiration
|
||||
- HoldTime change callback for real-time updates from Matter controllers
|
||||
- Button control for factory reset (decommission)
|
||||
- Matter commissioning via QR code or manual pairing code
|
||||
- Integration with Apple HomeKit, Amazon Alexa, and Google Home
|
||||
(*) It is necessary to compile the project using Arduino as IDF Component.
|
||||
|
||||
## Hardware Requirements
|
||||
|
||||
- ESP32 compatible development board (see supported targets table)
|
||||
- User button for factory reset (uses BOOT button by default)
|
||||
- Optional: PIR (Passive Infrared) motion sensor (e.g., HC-SR501, AM312) for real occupancy detection
|
||||
|
||||
## Pin Configuration
|
||||
|
||||
- **Button**: Uses `BOOT_PIN` by default
|
||||
- **PIR Sensor** (optional): Connect to any available GPIO pin (e.g., GPIO 4) when using a real sensor
|
||||
|
||||
## Software Setup
|
||||
|
||||
### Prerequisites
|
||||
|
||||
1. Install the Arduino IDE (2.0 or newer recommended)
|
||||
2. Install ESP32 Arduino Core with Matter support
|
||||
3. ESP32 Arduino libraries:
|
||||
- `Matter`
|
||||
- `Wi-Fi` (only for ESP32 and ESP32-S2)
|
||||
|
||||
### Configuration
|
||||
|
||||
Before uploading the sketch, configure the following:
|
||||
|
||||
1. **Wi-Fi credentials** (if not using BLE commissioning - mandatory for ESP32 | ESP32-S2):
|
||||
```cpp
|
||||
const char *ssid = "your-ssid"; // Change to your Wi-Fi SSID
|
||||
const char *password = "your-password"; // Change to your Wi-Fi password
|
||||
```
|
||||
|
||||
2. **HoldTime configuration** (optional):
|
||||
The example uses default HoldTime limits. You can customize them:
|
||||
```cpp
|
||||
const uint16_t HOLD_TIME_MIN = 0; // Minimum HoldTime in seconds
|
||||
const uint16_t HOLD_TIME_MAX = 3600; // Maximum HoldTime in seconds (1 hour)
|
||||
const uint16_t HOLD_TIME_DEFAULT = 30; // Default HoldTime in seconds
|
||||
```
|
||||
|
||||
3. **Button pin configuration** (optional):
|
||||
By default, the `BOOT` button (GPIO 0) is used for factory reset. You can change this to a different pin if needed.
|
||||
```cpp
|
||||
const uint8_t buttonPin = BOOT_PIN; // Set your button pin here
|
||||
```
|
||||
|
||||
4. **PIR sensor pin configuration** (optional, if using a real PIR sensor):
|
||||
```cpp
|
||||
const uint8_t pirPin = 4; // Set your PIR sensor pin here
|
||||
```
|
||||
See the "PIR Sensor Integration Example" section below for complete integration instructions.
|
||||
|
||||
## Building and Flashing
|
||||
|
||||
1. Open the `MatterOccupancyWithHoldTime.ino` sketch in the Arduino IDE.
|
||||
2. Select your ESP32 board from the **Tools > Board** menu.
|
||||
<!-- vale off -->
|
||||
3. Select **"Huge APP (3MB No OTA/1MB SPIFFS)"** from **Tools > Partition Scheme** menu.
|
||||
<!-- vale on -->
|
||||
4. Enable **"Erase All Flash Before Sketch Upload"** option from **Tools** menu.
|
||||
5. Connect your ESP32 board to your computer via USB.
|
||||
6. Click the **Upload** button to compile and flash the sketch.
|
||||
|
||||
## Expected Output
|
||||
|
||||
Once the sketch is running, open the Serial Monitor at a baud rate of **115200**. The Wi-Fi connection messages will be displayed only for ESP32 and ESP32-S2. Other targets will use Matter CHIPoBLE to automatically setup the IP Network. You should see output similar to the following, which provides the necessary information for commissioning:
|
||||
|
||||
```
|
||||
Connecting to your-wifi-ssid
|
||||
.......
|
||||
Wi-Fi connected
|
||||
IP address: 192.168.1.100
|
||||
|
||||
Restored HoldTime from Preferences: 30 seconds
|
||||
HoldTimeLimits set: Min=0, Max=3600, Default=30 seconds
|
||||
HoldTime set to: 30 seconds
|
||||
Initial HoldTime: 30 seconds
|
||||
|
||||
Matter Node is not commissioned yet.
|
||||
Initiate the device discovery in your Matter environment.
|
||||
Commission it to your Matter hub with the manual pairing code or QR code
|
||||
Manual pairing code: 34970112332
|
||||
QR code URL: https://project-chip.github.io/connectedhomeip/qrcode.html?data=MT%3A6FCJ142C00KA0648G00
|
||||
Matter Node not commissioned yet. Waiting for commissioning.
|
||||
Matter Node not commissioned yet. Waiting for commissioning.
|
||||
...
|
||||
Matter Node is commissioned and connected to the network. Ready for use.
|
||||
Occupancy detected! Holding state for 30 seconds (HoldTime)
|
||||
HoldTime expired. Switching to unoccupied state.
|
||||
```
|
||||
|
||||
After commissioning, the occupancy sensor will automatically simulate occupancy detections every 2 minutes. When occupancy is detected, the sensor holds the "occupied" state for the configured HoldTime duration (default: 30 seconds). After HoldTime expires, it automatically switches to "unoccupied" state. The Matter controller will receive these state updates and can also configure the HoldTime value.
|
||||
|
||||
## Using the Device
|
||||
|
||||
### Manual Control
|
||||
|
||||
The user button (BOOT button by default) provides factory reset functionality:
|
||||
|
||||
- **Long press (>5 seconds)**: Factory reset the device (decommission)
|
||||
|
||||
### Sensor Simulation
|
||||
|
||||
The example includes a simulated occupancy sensor with HoldTime support that:
|
||||
|
||||
- Starts in the unoccupied state (false)
|
||||
- Simulates occupancy detection every 2 minutes
|
||||
- When occupancy is detected, holds the "occupied" state for the HoldTime duration
|
||||
- After HoldTime expires, automatically switches to "unoccupied" state
|
||||
- If new detections occur while occupied, the HoldTime timer resets (continuous occupancy)
|
||||
- Updates the Matter attribute automatically
|
||||
|
||||
**HoldTime Behavior:**
|
||||
- The HoldTime value determines how long the sensor maintains the "occupied" state after the last detection
|
||||
- HoldTime can be configured via Matter Controller (within the min/max limits)
|
||||
- HoldTime value is persisted to Preferences and restored on reboot
|
||||
- When HoldTime expires, the sensor transitions to "unoccupied" even if no new detection occurs
|
||||
|
||||
To use a real occupancy sensor, replace the `simulatedHWOccupancySensor()` function with your sensor library code. The HoldTime functionality will work the same way - the sensor will hold the occupied state for the configured HoldTime duration after motion is no longer detected.
|
||||
|
||||
### PIR Sensor Integration Example
|
||||
|
||||
Here's a complete example for integrating a simple PIR (Passive Infrared) motion sensor:
|
||||
|
||||
#### Hardware Connections
|
||||
|
||||
Connect the PIR sensor to your ESP32:
|
||||
- **PIR VCC** → ESP32 3.3 V or 5 V (check your PIR sensor specifications)
|
||||
- **PIR GND** → ESP32 GND
|
||||
- **PIR OUT** → ESP32 GPIO pin (e.g., GPIO 4)
|
||||
|
||||
Common PIR sensors (HC-SR501, AM312, etc.) typically have three pins: VCC, GND, and OUT (digital output).
|
||||
|
||||
#### Code Modifications
|
||||
|
||||
1. **Add PIR pin definition** at the top of the sketch (after the button pin definition):
|
||||
|
||||
```cpp
|
||||
// PIR sensor pin
|
||||
const uint8_t pirPin = 4; // Change this to your PIR sensor pin
|
||||
```
|
||||
|
||||
2. **Initialize PIR pin in setup()** (after button initialization):
|
||||
|
||||
```cpp
|
||||
void setup() {
|
||||
// ... existing code ...
|
||||
pinMode(buttonPin, INPUT_PULLUP);
|
||||
|
||||
// Initialize PIR sensor pin
|
||||
pinMode(pirPin, INPUT);
|
||||
|
||||
// ... rest of setup code ...
|
||||
}
|
||||
```
|
||||
|
||||
3. **Replace the simulated function** with the real PIR reading function:
|
||||
|
||||
```cpp
|
||||
bool simulatedHWOccupancySensor() {
|
||||
// Read PIR sensor digital input
|
||||
// HIGH = motion detected (occupied), LOW = no motion (unoccupied)
|
||||
return digitalRead(pirPin) == HIGH;
|
||||
}
|
||||
```
|
||||
|
||||
#### Complete Modified Function Example
|
||||
|
||||
Here's the complete modified function with debouncing for more reliable readings:
|
||||
|
||||
```cpp
|
||||
bool simulatedHWOccupancySensor() {
|
||||
// Read PIR sensor with debouncing
|
||||
static bool lastState = false;
|
||||
static uint32_t lastChangeTime = 0;
|
||||
const uint32_t debounceTime = 100; // 100ms debounce
|
||||
|
||||
bool currentState = digitalRead(pirPin) == HIGH;
|
||||
|
||||
// Only update if state has changed and debounce time has passed
|
||||
if (currentState != lastState) {
|
||||
if (millis() - lastChangeTime > debounceTime) {
|
||||
lastState = currentState;
|
||||
lastChangeTime = millis();
|
||||
Serial.printf("Occupancy state changed: %s\r\n", currentState ? "OCCUPIED" : "UNOCCUPIED");
|
||||
}
|
||||
}
|
||||
|
||||
return lastState;
|
||||
}
|
||||
```
|
||||
|
||||
#### Testing the PIR Sensor
|
||||
|
||||
After making these changes:
|
||||
1. Upload the modified sketch to your ESP32
|
||||
2. Open the Serial Monitor at 115200 baud
|
||||
3. Move in front of the PIR sensor - you should see "OCCUPIED" messages
|
||||
4. Stay still for a few seconds - you should see "UNOCCUPIED" messages
|
||||
5. The Matter controller will automatically receive these occupancy state updates
|
||||
|
||||
### Smart Home Integration
|
||||
|
||||
Use a Matter-compatible hub (like an Apple HomePod, Google Nest Hub, or Amazon Echo) to commission the device.
|
||||
|
||||
#### Apple Home
|
||||
|
||||
1. Open the Home app on your iOS device
|
||||
2. Tap the "+" button > Add Accessory
|
||||
3. Scan the QR code displayed in the Serial Monitor, or
|
||||
4. Tap "I Don't Have a Code or Cannot Scan" and enter the manual pairing code
|
||||
5. Follow the prompts to complete setup
|
||||
6. The device will appear as an occupancy sensor in your Home app
|
||||
7. You can monitor the occupancy state and set up automations based on occupancy (e.g., turn on lights when occupied)
|
||||
8. You can configure the HoldTime value through the device settings (if supported by your Home app version)
|
||||
|
||||
#### Amazon Alexa
|
||||
|
||||
1. Open the Alexa app
|
||||
2. Tap More > Add Device > Matter
|
||||
3. Select "Scan QR code" or "Enter code manually"
|
||||
4. Complete the setup process
|
||||
5. The occupancy sensor will appear in your Alexa app
|
||||
6. You can monitor occupancy readings and create routines based on occupancy state changes
|
||||
|
||||
#### Google Home
|
||||
|
||||
1. Open the Google Home app
|
||||
2. Tap "+" > Set up device > New device
|
||||
3. Choose "Matter device"
|
||||
4. Scan the QR code or enter the manual pairing code
|
||||
5. Follow the prompts to complete setup
|
||||
6. You can monitor occupancy readings and create automations based on occupancy state changes
|
||||
|
||||
## Code Structure
|
||||
|
||||
The MatterOccupancyWithHoldTime example consists of the following main components:
|
||||
|
||||
1. **`setup()`**:
|
||||
- Initializes hardware (button), configures Wi-Fi (if needed)
|
||||
- Initializes Preferences and restores stored HoldTime value
|
||||
- Registers HoldTime change callback for persistence
|
||||
- Sets up the Matter Occupancy Sensor endpoint with initial state (unoccupied)
|
||||
- Calls `Matter.begin()` to start the Matter stack
|
||||
- Sets HoldTimeLimits (min, max, default) after Matter.begin()
|
||||
- Sets initial HoldTime value (from Preferences or default)
|
||||
- Waits for Matter commissioning
|
||||
|
||||
2. **`loop()`**:
|
||||
- Handles button input for factory reset
|
||||
- Continuously checks the simulated occupancy sensor and updates the Matter attribute
|
||||
- Allows the Matter stack to process events
|
||||
|
||||
3. **`simulatedHWOccupancySensor()`**:
|
||||
- Simulates a hardware occupancy sensor with HoldTime support
|
||||
- Detects occupancy every 2 minutes
|
||||
- Holds the "occupied" state for HoldTime seconds after detection
|
||||
- Automatically transitions to "unoccupied" when HoldTime expires
|
||||
- Resets HoldTime timer on new detections while occupied (continuous occupancy)
|
||||
- Replace this function with your actual sensor reading code
|
||||
|
||||
4. **HoldTime Callback**:
|
||||
- `onHoldTimeChange()` callback persists HoldTime changes to Preferences
|
||||
- Ensures HoldTime value is maintained across device reboots
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
- **Device not visible during commissioning**: Ensure Wi-Fi or Thread connectivity is properly configured
|
||||
- **Occupancy readings not updating**: Check that the sensor simulation function is being called correctly. For real sensors, verify sensor wiring and library initialization
|
||||
- **State not changing**: The simulated sensor detects occupancy every 2 minutes (120000 ms). The state will hold for HoldTime seconds after detection. If you're using a real sensor, ensure it's properly connected and reading correctly
|
||||
- **HoldTime not persisting**: Verify that Preferences is properly initialized and the callback is saving the value. Check Serial Monitor for "HoldTime changed" messages
|
||||
- **HoldTime not working**: Ensure `setHoldTimeLimits()` and `setHoldTime()` are called after `Matter.begin()`. Check Serial Monitor for error messages
|
||||
- **PIR sensor not detecting motion**:
|
||||
- Verify PIR sensor wiring (VCC, GND, OUT connections)
|
||||
- Check if PIR sensor requires 5 V or 3.3 V power (some PIR sensors need 5 V)
|
||||
- Allow 30-60 seconds for PIR sensor to stabilize after power-on
|
||||
- Adjust PIR sensor sensitivity and time delay potentiometers (if available on your sensor)
|
||||
- Ensure the PIR sensor has a clear view of the detection area
|
||||
- Test the PIR sensor directly by reading the GPIO pin value in Serial Monitor
|
||||
- **PIR sensor false triggers**: Add debouncing to the sensor reading function (see the "Complete Modified Function Example" above)
|
||||
- **Failed to commission**: Try factory resetting the device by long-pressing the button. Other option would be to erase the SoC Flash Memory by using `Arduino IDE Menu` -> `Tools` -> `Erase All Flash Before Sketch Upload: "Enabled"` or directly with `esptool.py --port <PORT> erase_flash`
|
||||
- **No serial output**: Check baudrate (115200) and USB connection
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- [Matter Overview](https://docs.espressif.com/projects/arduino-esp32/en/latest/matter/matter.html)
|
||||
- [Matter Endpoint Base Class](https://docs.espressif.com/projects/arduino-esp32/en/latest/matter/matter_ep.html)
|
||||
- [Matter Occupancy Sensor Endpoint](https://docs.espressif.com/projects/arduino-esp32/en/latest/matter/ep_occupancy_sensor.html)
|
||||
|
||||
## License
|
||||
|
||||
This example is licensed under the Apache License, Version 2.0.
|
||||
@@ -0,0 +1,4 @@
|
||||
fqbn_append: PartitionScheme=huge_app
|
||||
|
||||
requires:
|
||||
- CONFIG_ESP_MATTER_ENABLE_DATA_MODEL=y
|
||||
Reference in New Issue
Block a user