Arduino_Sensor_Nodes/sketch_dec6b/sketch_dec6b.ino

865 lines
29 KiB
C++

// Xiao ESP32-C6
// uploading new script
// Zigbee connection establishment --> .......
// force remove deivce from Z2M with permit join OFF
// swich permit JOIN ON
// restart ESP32
// leave permit jion on until configuration finished
// Copyright 2024 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.
/**
* @brief This example demonstrates Zigbee occupancy sensor.
*
* The example demonstrates how to use Zigbee library to create a end device occupancy sensor.
* The occupancy sensor is a Zigbee end device, which is reporting data to the Zigbee network.
* Tested with PIR sensor HC-SR501 connected to GPIO4.
*
* Proper Zigbee mode must be selected in Tools->Zigbee mode
* and also the correct partition scheme must be selected in Tools->Partition Scheme.
*
* Please check the README.md for instructions and more detailed description.
*
* Created by Jan Procházka (https://github.com/P-R-O-C-H-Y/)
*/
// #ifndef ZIGBEE_MODE_ED
// #error "Zigbee end device mode is not selected in Tools->Zigbee mode"
// #endif
#define DEBUG_TRACE
#include "Zigbee.h"
// #include <HardwareSerial.h>
// #define SENSOR_RX 17 // ESP32 RX connected to sensor TX
// #define SENSOR_TX 16 // ESP32 TX connected to sensor RX
// HardwareSerial mmWaveSerial(1); // UART2
/* Zigbee occupancy sensor configuration */
// #define OCCUPANCY_SENSOR_ENDPOINT_NUMBER 1
uint8_t button = BOOT_PIN;
// uint8_t sensor_pin = 23; // connected to GPIO2 of the sensor; HIGH in case of presence detection
// Fade LED PIN (replace with LED_BUILTIN constant for the built-in LED)
// #define LED_PIN D5
const int ledPin = LED_BUILTIN;
// ZigbeeOccupancySensor zbOccupancySensor = ZigbeeOccupancySensor(OCCUPANCY_SENSOR_ENDPOINT_NUMBER);
#include "Arduino.h"
#include <bme68xLibrary.h>
// Define the I2C pins
#define SCL_PIN 18
#define SDA_PIN 20
#define TEMP_SENSOR_ENDPOINT_NUMBER 10
ZigbeeTempSensor zbTempSensor_BME68X = ZigbeeTempSensor(TEMP_SENSOR_ENDPOINT_NUMBER);
// #define TEMP_SENSOR_ENDPOINT_NUMBER_2 12
// ZigbeeTempSensor zbTempSensor2 = ZigbeeTempSensor(TEMP_SENSOR_ENDPOINT_NUMBER_2);
// #define CARBON_DIOXIDE_SENSOR_ENDPOINT_NUMBER 13
// ZigbeeCarbonDioxideSensor zbCarbonDioxideSensor = ZigbeeCarbonDioxideSensor(CARBON_DIOXIDE_SENSOR_ENDPOINT_NUMBER);
#define ANALOG_DEVICE_ENDPOINT_NUMBER 11
ZigbeeAnalog zbAnalogDevice_BME68X = ZigbeeAnalog(ANALOG_DEVICE_ENDPOINT_NUMBER);
/* BME280 sensor */
//BME280I2C sensor;
Bme68x bme;
int errorCount = 0; // Initialize an error counter
const int maxErrors = 5; // Maximum number of allowed errors before restart
/************************ Temp sensor *****************************/
static void bme680_sensor_value_update(void *arg) {
for (;;) {
float temperature(NAN), humidity(NAN), pressure(NAN), gasResistance(NAN);
uint8_t percentage;
// Prepare the BME680 for measurement
bme68xData data;
int8_t rslt;
bme.setOpMode(BME68X_FORCED_MODE);
delayMicroseconds(bme.getMeasDur());
if (bme.fetchData()) {
bme.getData(data);
temperature = data.temperature; // Temperature in °C
humidity = data.humidity; // Humidity in %
pressure = data.pressure; // Pressure in hPa
gasResistance = data.gas_resistance; // Gas resistance in ohms
errorCount = 0; // Reset error count on successful read
} else {
//Serial.println("Failed to read data from BME680!");
//return; // Exit if reading failed
errorCount++;
Serial.println("Failed to read data from BME680!");
if (errorCount >= maxErrors) {
Serial.println("Too many errors! Restarting...");
ESP.restart(); // Restart the ESP32 after too many errors
}
}
// Update temperature and humidity values in Temperature sensor EP
zbTempSensor_BME68X.setTemperature(temperature);
zbTempSensor_BME68X.setHumidity(humidity);
// zbCarbonDioxideSensor.setCarbonDioxide(gasResistance); // Assuming you have a method for gas resistance
zbAnalogDevice_BME68X.setAnalogInput(round(gasResistance / 1000.0));
// zbAnalogDevice_BME68X.reportAnalogInput();
// Report values
// zbTempSensor.report();
// zbTempSensor.reportBatteryPercentage();
// zbCarbonDioxideSensor.setCarbonDioxide(gasResistance);
// zbCarbonDioxideSensor.report();
#ifdef DEBUG_TRACE
//Serial.printf("Reported temperature: %.2f°C, Humidity: %.2f%%\r\n", temperature, humidity);
Serial.printf("BME680: Reported temperature: %.2f°C, Humidity: %.2f%%, Gas Resistance: %.2f ohms\r\n", temperature, humidity, gasResistance);
#endif
// // Read temperature sensor value
// // float tsens_value = temperatureRead();
// float tsens_value = random(180, 300) / 10.0;
// // Serial.printf("Updated temperature sensor value to %.2f°C\r\n", tsens_value);
// // Update temperature value in Temperature sensor EP
// zbTempSensor.setTemperature(tsens_value);
// zbTempSensor2.setTemperature(tsens_value);
// float humidity = random(300, 700) / 10.0;
// zbTempSensor.setHumidity(humidity);
// zbTempSensor2.setHumidity(humidity);
// Serial.printf("Reported temperature: %.2f°C, Humidity: %.2f%%\r\n", tsens_value, humidity);
delay(10000);
}
}
// #include <Wire.h>
#include "Adafruit_SHT4x.h"
#include "Adafruit_SGP40.h"
// --- Hardware Config ---
// #define I2C_SDA_PIN 6 // Default C6 SDA (Adjust if using a specific board like Seeed Xiao)
// #define I2C_SCL_PIN 7 // Default C6 SCL
// If using standard DevKit, you can often just use Wire.begin() without pins
// --- Objects ---
Adafruit_SHT4x sht4;
Adafruit_SGP40 sgp;
// Define a Zigbee Endpoint for Environmental Data
#define ENDPOINT_ENV 12
// ZigbeeTempSensor zbEnvSensor_sgp40_sht40(ENDPOINT_ENV);
ZigbeeTempSensor zbEnvSensor_sgp40_sht40 = ZigbeeTempSensor(ENDPOINT_ENV);
#define SGP_ANALOG_DEVICE_ENDPOINT_NUMBER 13
ZigbeeAnalog zbAnalogDevice_sgp40_sht40 = ZigbeeAnalog(SGP_ANALOG_DEVICE_ENDPOINT_NUMBER);
static void sgp40_sht40_sensor_value_update(void *arg) {
for (;;) {
float currentTemp(NAN), currentHum(NAN);
uint16_t currentRaw(NAN);
int32_t currentVOC(NAN);
// uint8_t percentage;
// Prepare the BME680 for measurement
// bme68xData data;
// int8_t rslt;
// bme.setOpMode(BME68X_FORCED_MODE);
// delayMicroseconds(bme.getMeasDur());
// if (bme.fetchData()) {
// bme.getData(data);
// temperature = data.temperature; // Temperature in °C
// humidity = data.humidity; // Humidity in %
// pressure = data.pressure; // Pressure in hPa
// gasResistance = data.gas_resistance; // Gas resistance in ohms
// errorCount = 0; // Reset error count on successful read
// } else {
// //Serial.println("Failed to read data from BME680!");
// //return; // Exit if reading failed
// errorCount++;
// Serial.println("Failed to read data from BME680!");
// if (errorCount >= maxErrors) {
// Serial.println("Too many errors! Restarting...");
// ESP.restart(); // Restart the ESP32 after too many errors
// }
// }
Serial.println("Starting readout of SHT40");
// --- 1. Read SHT40 (Temp/Hum) ---
sensors_event_t humidity, temp;
sht4.getEvent(&humidity, &temp); // Populate temp and humidity objects
currentTemp = temp.temperature;
currentHum = humidity.relative_humidity;
Serial.print("Temperature: "); Serial.print(currentTemp); Serial.println(" degrees C");
Serial.print("Humidity: "); Serial.print(currentHum); Serial.println("% rH");
Serial.println("Starting readout of SGP40");
// --- 2. Read SGP40 (VOC) ---
// SGP40 requires precise Temp/Hum for accurate compensation.
// We pass the raw SHT40 values directly to the SGP40 algorithm.
currentRaw = sgp.measureRaw(currentTemp, currentHum);
currentVOC = sgp.measureVocIndex(currentTemp, currentHum);
Serial.print("Raw measurement: ");
Serial.println(currentRaw);
Serial.print("Voc Index: ");
Serial.println(currentVOC);
// // Temp: Cluster 0x0402, Attribute 0x0000 (MeasuredValue), Type INT16, Value = Temp * 100
// int16_t zigbeeTemp = (int16_t)(currentTemp * 100);
// zbEnvSensor_sgp40_sht40.reportAttribute(ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT,
// ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID,
// ESP_ZB_ZCL_ATTR_TYPE_S16,
// &zigbeeTemp);
// // Humidity: Cluster 0x0405, Attribute 0x0000 (MeasuredValue), Type UINT16, Value = Hum * 100
// uint16_t zigbeeHum = (uint16_t)(currentHum * 100);
// zbEnvSensor_sgp40_sht40.reportAttribute(ESP_ZB_ZCL_CLUSTER_ID_REL_HUMIDITY,
// ESP_ZB_ZCL_ATTR_REL_HUMIDITY_MEASUREMENT_VALUE_ID,
// ESP_ZB_ZCL_ATTR_TYPE_U16,
// &zigbeeHum);
// // VOC (Analog Input): Cluster 0x000C, Attribute 0x0055 (PresentValue), Type SINGLE (Float)
// // Using Analog Input Present Value for VOC
// float zigbeeVOC = (float)currentVOC;
// zbEnvSensor_sgp40_sht40.reportAttribute(ESP_ZB_ZCL_CLUSTER_ID_ANALOG_INPUT,
// ESP_ZB_ZCL_ATTR_ANALOG_INPUT_PRESENT_VALUE_ID,
// ESP_ZB_ZCL_ATTR_TYPE_SINGLE,
// &zigbeeVOC);
// Serial.printf("T: %.2f C | H: %.2f %% | VOC Index: %d\n", zigbeeTemp, zigbeeHum, zigbeeVOC);
Serial.println("finished readout of SGP40");
// // Update temperature and humidity values in Temperature sensor EP
zbEnvSensor_sgp40_sht40.setTemperature(currentTemp);
zbEnvSensor_sgp40_sht40.setHumidity(currentHum);
// // zbCarbonDioxideSensor.setCarbonDioxide(gasResistance); // Assuming you have a method for gas resistance
zbAnalogDevice_sgp40_sht40.setAnalogInput(round(currentRaw / 1000.0));
// // zbAnalogDevice_BME68X.reportAnalogInput();
Serial.println("finished setting values");
// Report values
// zbTempSensor.report();
// zbTempSensor.reportBatteryPercentage();
// zbCarbonDioxideSensor.setCarbonDioxide(gasResistance);
// zbCarbonDioxideSensor.report();
#ifdef DEBUG_TRACE
//Serial.printf("Reported temperature: %.2f°C, Humidity: %.2f%%\r\n", temperature, humidity);
// Serial.printf("Reported temperature: %.2f°C, Humidity: %.2f%%, Gas Resistance: %.2f ohms\r\n", currentTemp, currentHum, currentVOC);
// Serial.printf("SGP/SHT: T: %.2f C | H: %.2f %% | Raw SGP: %d | VOC Index: %d\n", currentTemp, currentHum, currentRaw, currentVOC);
#endif
// // Read temperature sensor value
// // float tsens_value = temperatureRead();
// float tsens_value = random(180, 300) / 10.0;
// // Serial.printf("Updated temperature sensor value to %.2f°C\r\n", tsens_value);
// // Update temperature value in Temperature sensor EP
// zbTempSensor.setTemperature(tsens_value);
// zbTempSensor2.setTemperature(tsens_value);
// float humidity = random(300, 700) / 10.0;
// zbTempSensor.setHumidity(humidity);
// zbTempSensor2.setHumidity(humidity);
// Serial.printf("Reported temperature: %.2f°C, Humidity: %.2f%%\r\n", tsens_value, humidity);
delay(10000);
}
}
// Internal Led flash
void flashLED() {
// Turn on LED for 100ms
digitalWrite(LED_BUILTIN, HIGH);
delay(100);
digitalWrite(LED_BUILTIN, LOW);
}
// #define ZIGBEE_ILLUMINANCE_SENSOR_ENDPOINT 9
// uint8_t illuminance_sensor_pin = 1; // Insert the analog pin to which the sensor (e.g. photoresistor) is connected
// ZigbeeIlluminanceSensor zbIlluminanceSensor = ZigbeeIlluminanceSensor(ZIGBEE_ILLUMINANCE_SENSOR_ENDPOINT);
// /********************* Illuminance sensor **************************/
// static void illuminance_sensor_value_update(void *arg) {
// for (;;) {
// // read the raw analog value from the sensor
// int lsens_analog_raw = analogRead(illuminance_sensor_pin);
// Serial.printf("[Illuminance Sensor] raw analog value: %d\r\n", lsens_analog_raw);
// // conversion into zigbee raw illuminance value (typically between 0 in darkness and 50000 in direct sunlight)
// // depends on the value range of the raw analog sensor values and will need calibration for correct lux values
// // for demonstration purpose map the 12-bit ADC value (0-4095) to Zigbee illuminance range (0-50000)
// int lsens_illuminance_raw = map(lsens_analog_raw, 0, 4095, 0, 50000);
// Serial.printf("[Illuminance Sensor] raw illuminance value: %d\r\n", lsens_illuminance_raw);
// // according to zigbee documentation the formular 10^(lsens_illuminance_raw/10000)-1 can be used to calculate lux value from raw illuminance value
// // Note: Zigbee2MQTT seems to be using the formular 10^(lsens_illuminance_raw/10000) instead (without -1)
// int lsens_illuminance_lux = round(pow(10, (lsens_illuminance_raw / 10000.0)) - 1);
// Serial.printf("[Illuminance Sensor] lux value: %d lux\r\n", lsens_illuminance_lux);
// // Update illuminance in illuminance sensor EP
// zbIlluminanceSensor.setIlluminance(lsens_illuminance_raw); // use raw illuminance here!
// delay(10000); // reduce delay (in ms), if you want your device to react more quickly to changes in illuminance
// }
// }
// // 1. Define the task function (Global scope, outside setup/loop)
// void pirTask(void * parameter) {
// // Move the static variable here. It doesn't need to be 'static' anymore
// // because this function only runs once and stays in the loop below.
// bool occupancy = false;
// // 2. Infinite Loop: Tasks must never return!
// for(;;) {
// // --- Your Original Logic Start ---
// if (digitalRead(sensor_pin) == HIGH && !occupancy) {
// zbOccupancySensor.setOccupancy(true);
// zbOccupancySensor.report();
// occupancy = true;
// analogWrite(ledPin, 0);
// Serial.println("GPIO2 HIGH");
// } else if (digitalRead(sensor_pin) == LOW && occupancy) {
// zbOccupancySensor.setOccupancy(false);
// zbOccupancySensor.report();
// occupancy = false;
// analogWrite(ledPin, 255);
// Serial.println("GPIO2 LOW");
// }
// // --- Your Original Logic End ---
// // 3. CRITICAL: Delay to yield control
// // Polling a PIR every 50ms is plenty fast and saves CPU.
// vTaskDelay(50 / portTICK_PERIOD_MS);
// }
// }
// const char* commands[] = {
// "getRange",
// "getSensitivity",
// "getLatency",
// "getUart",
// "getGpioMode 2",
// "getLedMode 1",
// "getEcho",
// "getUartOutput 1",
// "getUartOutput 2",
// // "sensorStop",
// // "sensorStart",
// // "saveConfig",
// // "resetCfg",
// // "resetSystem",
// "getHWV",
// "getSWV",
// "getOutput"
// };
// const int numCommands = sizeof(commands) / sizeof(commands[0]);
// String line = "";
// bool sendCommandAndWaitForDone(String command, Stream &sensorSerial, unsigned long timeout = 1000) {
// // Send the command
// sensorSerial.println(command);
// Serial.print("Sending: ");
// Serial.println(command);
// // Wait for "Done" response
// unsigned long startTime = millis();
// String response;
// while (millis() - startTime < timeout) {
// while (sensorSerial.available()) {
// char c = sensorSerial.read();
// Serial.write(c); // Print response to Serial Monitor
// response += c;
// // If "Done" is found in the response, return success
// if (response.indexOf("Done") >= 0) {
// Serial.println("✓ Done received.");
// return true;
// }
// // Optional: detect "Error" for debugging
// if (response.indexOf("Error") >= 0) {
// Serial.println("✗ Error received.");
// return false;
// }
// }
// }
// Serial.println("✗ Timeout waiting for Done.");
// return false;
// }
// void turnOnSensor(int sensitivity) {
// Serial.println("=== Turning On Sensor ===");
// sendCommandAndWaitForDone("sensorStop", mmWaveSerial);
// sendCommandAndWaitForDone("resetCfg", mmWaveSerial); // Optional
// // sendCommandAndWaitForDone("setUartOutput 1 0", mmWaveSerial); // Disable $JYBSS
// // sendCommandAndWaitForDone("setUartOutput 2 1", mmWaveSerial); // Enable $JYRPO
// sendCommandAndWaitForDone("setUartOutput 1 1", mmWaveSerial); // Enable $JYBSS
// sendCommandAndWaitForDone("setUartOutput 2 0", mmWaveSerial); // Disable $JYRPO
// sendCommandAndWaitForDone("setSensitivity " + String(sensitivity), mmWaveSerial);
// sendCommandAndWaitForDone("setRange 0 3", mmWaveSerial);
// sendCommandAndWaitForDone("setLatency 0.025 0.5", mmWaveSerial);
// sendCommandAndWaitForDone("setEcho 1", mmWaveSerial); // Enable echo — sensor prints back commands and shows leapMMW:/> prompt (default).
// sendCommandAndWaitForDone("setLedMode 1 1", mmWaveSerial); // LED off
// sendCommandAndWaitForDone("setGpioMode 2 1", mmWaveSerial); // GPIO2 high when presence
// sendCommandAndWaitForDone("saveConfig", mmWaveSerial);
// sendCommandAndWaitForDone("sensorStart", mmWaveSerial);
// }
void setup() {
#ifdef DEBUG_TRACE
Serial.begin(115200);
// mmWaveSerial.begin(115200, SERIAL_8N1, SENSOR_RX, SENSOR_TX);
// delay(100); // Give sensor time to boot
Serial.println();
Serial.println("Tutoduino Zigbee temperature sensor start!");
#endif
// turnOnSensor(5); // initialization of mmwave sensor
// for (int i = 0; i < numCommands; i++) {
// const char* cmd = commands[i];
// sendCommandAndWaitForDone(cmd, mmWaveSerial);
// delay(10); // small delay before next command (optional)
// }
// Optional: configure analog input
analogSetAttenuation(ADC_11db); // set analog to digital converter (ADC) attenuation to 11 dB (up to ~3.3V input)
analogReadResolution(12); // set analog read resolution to 12 bits (value range from 0 to 4095), 12 is default
// // Init button + PIR sensor
// pinMode(button, INPUT_PULLUP);
// pinMode(sensor_pin, INPUT_PULLUP);
// pinMode(ledPin, OUTPUT);
// analogWrite(ledPin, 255); // pin, dutyCycle
// // Optional: set Zigbee device name and model
// zbOccupancySensor.setManufacturerAndModel("Espressif", "Node11_bme680_sht40_sgp40");
// // Optional: Set power source (choose between ZB_POWER_SOURCE_MAINS and ZB_POWER_SOURCE_BATTERY), defaults to unknown
// zbOccupancySensor.setPowerSource(ZB_POWER_SOURCE_MAINS);
// // Add endpoint to Zigbee Core
// Zigbee.addEndpoint(&zbOccupancySensor);
Wire.begin(SDA_PIN, SCL_PIN);
Wire.setClock(100000); // Set I2C clock speed to 100kHz
// Initialize the BME680
bme.begin(BME68X_I2C_ADDR_HIGH, Wire); // BME68X_I2C_ADDR_HIGH=0x76, BME68X_I2C_ADDR_LOW=0x77
// Set up the BME680
// bme.setGasStatus(BME680_ENABLE_GAS_MEAS);
// bme.setOversampling(T2, OS_2X);
// bme.setOversampling(T1, OS_16X);
// bme.setOversampling(H1, OS_2X);
// bme.setFilter(FILTER_SIZE_3);
// bme.setGasSettings(320, 25, 0x4, 130, 410, 4, 0x01, 0x10, 0);
if(bme.checkStatus())
{
if (bme.checkStatus() == BME68X_ERROR)
{
Serial.println("Sensor error:" + bme.statusString());
return;
}
else if (bme.checkStatus() == BME68X_WARNING)
{
Serial.println("Sensor Warning:" + bme.statusString());
}
}
/* Set the default configuration for temperature, pressure and humidity */
bme.setTPH();
/* Set the heater configuration to 300 deg C for 100ms for Forced mode */
bme.setHeaterProf(300, 100);
bme68xData data;
bme.setOpMode(BME68X_FORCED_MODE);
// Optional: set Zigbee device name and model
zbTempSensor_BME68X.setManufacturerAndModel("Espressif", "Node11_bme680_sht40_sgp40");
// Optional: Set power source (choose between ZB_POWER_SOURCE_MAINS and ZB_POWER_SOURCE_BATTERY), defaults to unknown
zbTempSensor_BME68X.setPowerSource(ZB_POWER_SOURCE_MAINS);
// Set minimum and maximum temperature measurement value (10-50°C is default range for chip temperature measurement)
zbTempSensor_BME68X.setMinMaxValue(0, 50);
// Set tolerance for temperature measurement in °C (lowest possible value is 0.01°C)
zbTempSensor_BME68X.setTolerance(1);
// Set power source to battery, battery percentage and battery voltage (now 100% and 3.5V for demonstration)
// The value can be also updated by calling zbTempSensor.setBatteryPercentage(percentage) or zbTempSensor.setBatteryVoltage(voltage) anytime after Zigbee.begin()
// zbTempSensor.setPowerSource(ZB_POWER_SOURCE_BATTERY, 100, 35);
// Add humidity cluster to the temperature sensor device with min, max and tolerance values
zbTempSensor_BME68X.addHumiditySensor(0, 100, 1);
// Add endpoint to Zigbee Core
Zigbee.addEndpoint(&zbTempSensor_BME68X);
// // Set minimum and maximum temperature measurement value (10-50°C is default range for chip temperature measurement)
// zbTempSensor2.setMinMaxValue(10, 50);
// // Set tolerance for temperature measurement in °C (lowest possible value is 0.01°C)
// zbTempSensor2.setTolerance(1);
// // Set power source to battery, battery percentage and battery voltage (now 100% and 3.5V for demonstration)
// // The value can be also updated by calling zbTempSensor.setBatteryPercentage(percentage) or zbTempSensor.setBatteryVoltage(voltage) anytime after Zigbee.begin()
// // zbTempSensor.setPowerSource(ZB_POWER_SOURCE_BATTERY, 100, 35);
// // Add humidity cluster to the temperature sensor device with min, max and tolerance values
// zbTempSensor2.addHumiditySensor(0, 100, 1);
// // Add endpoint to Zigbee Core
// Zigbee.addEndpoint(&zbTempSensor2);
// // Set minimum and maximum carbon dioxide measurement value in ppm
// zbCarbonDioxideSensor.setMinMaxValue(0, 150000000);
// // Add endpoints to Zigbee Core
// Zigbee.addEndpoint(&zbCarbonDioxideSensor);
// Add analog clusters to Zigbee Analog according your needs
zbAnalogDevice_BME68X.addAnalogInput();
// Add endpoints to Zigbee Core
Zigbee.addEndpoint(&zbAnalogDevice_BME68X);
// // Set minimum and maximum for raw illuminance value (0 min and 50000 max equals to 0 lux - 100,000 lux)
// zbIlluminanceSensor.setMinMaxValue(0, 50000);
// // Optional: Set tolerance for raw illuminance value
// zbIlluminanceSensor.setTolerance(1);
// // Add endpoint to Zigbee Core
// Serial.println("Adding Zigbee illuminance sensor endpoint to Zigbee Core");
// Zigbee.addEndpoint(&zbIlluminanceSensor);
Serial.println("Initializing SHT40...");
if (!sht4.begin(&Wire)) {
Serial.println("SHT40 not found! Check wiring.");
while (1) delay(10);
}
sht4.setPrecision(SHT4X_HIGH_PRECISION);
sht4.setHeater(SHT4X_NO_HEATER);
Serial.println("Initializing SGP40...");
if (!sgp.begin(&Wire)) {
Serial.println("SGP40 not found! Check wiring.");
while (1) delay(10);
}
// --- 2. Configure Zigbee Endpoint ---
// Set Manufacturer/Model
// zbEnvSensor.setManufacturerAndModel("Espressif", "ESP32C6-Env-Sensor");
// // A. Add Temperature Cluster (Standard)
// zbEnvSensor_sgp40_sht40.addCluster(ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT);
// // B. Add Humidity Cluster
// // We manually add this cluster to the endpoint
// zbEnvSensor_sgp40_sht40.addCluster(ESP_ZB_ZCL_CLUSTER_ID_REL_HUMIDITY);
// // C. Add Analog Input Cluster (for VOC Index)
// // We use Analog Input (0x000C) as a generic container for the VOC value (0-500)
// zbEnvSensor_sgp40_sht40.addCluster(ESP_ZB_ZCL_CLUSTER_ID_ANALOG_INPUT);
// Set minimum and maximum temperature measurement value (10-50°C is default range for chip temperature measurement)
zbEnvSensor_sgp40_sht40.setMinMaxValue(0, 50);
// Set tolerance for temperature measurement in °C (lowest possible value is 0.01°C)
zbEnvSensor_sgp40_sht40.setTolerance(1);
// Set power source to battery, battery percentage and battery voltage (now 100% and 3.5V for demonstration)
// The value can be also updated by calling zbTempSensor.setBatteryPercentage(percentage) or zbTempSensor.setBatteryVoltage(voltage) anytime after Zigbee.begin()
// zbTempSensor.setPowerSource(ZB_POWER_SOURCE_BATTERY, 100, 35);
// Add humidity cluster to the temperature sensor device with min, max and tolerance values
zbEnvSensor_sgp40_sht40.addHumiditySensor(0, 100, 1);
// Register the endpoint
Zigbee.addEndpoint(&zbEnvSensor_sgp40_sht40);
// Add analog clusters to Zigbee Analog according your needs
zbAnalogDevice_sgp40_sht40.addAnalogInput();
// Add endpoints to Zigbee Core
Zigbee.addEndpoint(&zbAnalogDevice_sgp40_sht40);
// Create a default Zigbee configuration for End Device
esp_zb_cfg_t zigbeeConfig = ZIGBEE_DEFAULT_ED_CONFIG();
#ifdef DEBUG_TRACE
Serial.println("Starting Zigbee");
#endif
// When all EPs are registered, start Zigbee in End Device mode
// if (!Zigbee.begin(&zigbeeConfig, false)) {
if (!Zigbee.begin(ZIGBEE_ROUTER)) {
#ifdef DEBUG_TRACE
Serial.println("Zigbee failed to start!");
Serial.println("Rebooting ESP32!");
#endif
ESP.restart();
} else {
Serial.println("Zigbee started successfully!");
}
#ifdef DEBUG_TRACE
Serial.println("Connecting to network");
#endif
while (!Zigbee.connected()) {
#ifdef DEBUG_TRACE
Serial.print(".");
#endif
delay(100);
}
#ifdef DEBUG_TRACE
Serial.println("Successfully connected to Zigbee network");
#endif
// // 4. Create the task
// xTaskCreate(
// pirTask, // Function to call
// "PIR_Check", // Name for debugging
// 4096, // Stack size (bytes) - Zigbee operations need space!
// NULL, // Parameter to pass
// 1, // Priority (1 is standard, higher numbers = higher priority)
// NULL // Task handle
// );
// Start Temperature sensor reading task
xTaskCreate(bme680_sensor_value_update, "temp_sensor_update", 2048, NULL, 10, NULL);
// Set reporting interval for temperature measurement in seconds, must be called after Zigbee.begin()
// min_interval and max_interval in seconds, delta (temp change in 0,1 °C)
// if min = 1 and max = 0, reporting is sent only when temperature changes by delta
// if min = 0 and max = 10, reporting is sent every 10 seconds or temperature changes by delta
// if min = 0, max = 10 and delta = 0, reporting is sent every 10 seconds regardless of temperature change
// zbTempSensor.setReporting(1, 0, 1);
zbTempSensor_BME68X.setReporting(0, 15, 1);
// zbTempSensor2.setReporting(0, 15, 0);
// zbCarbonDioxideSensor.setReporting(0, 30, 0);
zbAnalogDevice_BME68X.setAnalogInputReporting(0, 15, 10); // report every 30 seconds if value changes by 10
// Start illuminance sensor reading task
// xTaskCreate(illuminance_sensor_value_update, "illuminance_sensor_update", 2048, NULL, 10, NULL);
// Set reporting schedule for illuminance value measurement in seconds, must be called after Zigbee.begin()
// min_interval and max_interval in seconds, delta
// if min = 1 and max = 0, delta = 1000, reporting is sent when raw illuminance value changes by 1000, but at most once per second
// if min = 0 and max = 10, delta = 1000, reporting is sent every 10 seconds or if raw illuminance value changes by 1000
// if min = 0, max = 10 and delta = 0, reporting is sent every 10 seconds regardless of illuminance change
// Note: On pairing with Zigbee Home Automation or Zigbee2MQTT the reporting schedule will most likely be overwritten with their default settings
// zbIlluminanceSensor.setReporting(1, 0, 1);
xTaskCreate(sgp40_sht40_sensor_value_update, "sgp40_sht40_sensor_value_update", 2048, NULL, 10, NULL);
zbEnvSensor_sgp40_sht40.setReporting(0, 15, 1);
zbAnalogDevice_sgp40_sht40.setAnalogInputReporting(0, 15, 10); // report every 30 seconds if value changes by 10
}
void loop() {
// Checking PIR sensor for occupancy change
// static bool occupancy = false;
// if (digitalRead(sensor_pin) == HIGH && !occupancy) {
// // Update occupancy sensor value
// zbOccupancySensor.setOccupancy(true);
// zbOccupancySensor.report();
// occupancy = true;
// analogWrite(ledPin, 0);
// Serial.println("GPIO2 HIGH");
// } else if (digitalRead(sensor_pin) == LOW && occupancy) {
// zbOccupancySensor.setOccupancy(false);
// zbOccupancySensor.report();
// occupancy = false;
// analogWrite(ledPin, 255);
// Serial.println("GPIO2 LOW");
// }
// Checking button for factory reset
if (digitalRead(button) == LOW) { // Push button pressed
// Key debounce handling
delay(100);
int startTime = millis();
while (digitalRead(button) == LOW) {
delay(50);
if ((millis() - startTime) > 3000) {
// If key pressed for more than 3secs, factory reset Zigbee and reboot
Serial.println("Resetting Zigbee to factory and rebooting in 1s.");
delay(1000);
Zigbee.factoryReset();
}
}
// force report of illuminance when button is pressed
// zbIlluminanceSensor.report();
zbTempSensor_BME68X.report();
// zbCarbonDioxideSensor.report();
zbAnalogDevice_BME68X.reportAnalogInput();
// zbEnvSensor_sgp40_sht40.report();
}
delay(100);
}