// 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 // #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 // 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 #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); }