From c1cedcf333b41ea8a97edf77824a9efdddb500cf Mon Sep 17 00:00:00 2001 From: Florian Date: Tue, 10 Jan 2023 11:32:56 -0600 Subject: [PATCH] Add ESP32 internal temperature measurement and automatic Actuator switch Off (#1384) * Add automatic stop of relay following ESP32 temperature To avoid overheating when too much current goes through the device. Add internal temperature reporting to SYStoMQTT This function is not available with ESP32 S3 and C3 * Temp update and error log Update of the temperature to get closer to the datasheet of the ESP32 -40 +85C and add the module name to the error log --- main/ZactuatorONOFF.ino | 20 ++++++++++++++++++++ main/ZmqttDiscovery.ino | 9 +++++++++ main/config_ONOFF.h | 7 ++++++- main/main.ino | 35 ++++++++++++++++++++++++++++++++++- platformio.ini | 5 ++++- 5 files changed, 73 insertions(+), 3 deletions(-) diff --git a/main/ZactuatorONOFF.ino b/main/ZactuatorONOFF.ino index 841c70ec..786501d3 100644 --- a/main/ZactuatorONOFF.ino +++ b/main/ZactuatorONOFF.ino @@ -29,6 +29,7 @@ #include "User_config.h" #ifdef ZactuatorONOFF +unsigned long timeinttemp = 0; void setupONOFF() { pinMode(ACTUATOR_ONOFF_GPIO, OUTPUT); @@ -103,6 +104,25 @@ void MQTTtoONOFF(char* topicOri, char* datacallback) { } # endif +//Check regularly temperature of the ESP32 board and switch OFF the relay if temperature is more than MAX_TEMP_ACTUATOR +# ifdef MAX_TEMP_ACTUATOR +void OverHeatingRelayOFF() { +# if defined(ESP32) && defined(SENS_SAR_MEAS_WAIT2_REG) // This macro is necessary to retrieve temperature and not present with S3 and C3 environment + if (millis() > (timeinttemp + TimeBetweenReadingIntTemp)) { + float internalTempc = intTemperatureRead(); + Log.trace(F("Internal temperature of the ESP32 %F" CR), internalTempc); + if (internalTempc > MAX_TEMP_ACTUATOR && digitalRead(ACTUATOR_ONOFF_GPIO) == ACTUATOR_ON) { + Log.error(F("[ActuatorONOFF] OverTemperature detected ( %F > %F ) switching OFF Actuator" CR), internalTempc, MAX_TEMP_ACTUATOR); + ActuatorManualTrigger(!ACTUATOR_ON); + } + timeinttemp = millis(); + } +# endif +} +# else +void OverHeatingRelayOFF() {} +# endif + void ActuatorManualTrigger(uint8_t level) { # ifdef ACTUATOR_BUTTON_TRIGGER_LEVEL if (level == ACTUATOR_BUTTON_TRIGGER_LEVEL) { diff --git a/main/ZmqttDiscovery.ino b/main/ZmqttDiscovery.ino index 2a766c3d..ef79be70 100644 --- a/main/ZmqttDiscovery.ino +++ b/main/ZmqttDiscovery.ino @@ -421,6 +421,15 @@ void pubMqttDiscovery() { # endif # endif # ifdef ESP32 + createDiscovery("sensor", //set Type + subjectSYStoMQTT, "SYS: Internal temperature", (char*)getUniqueId("tempc", "").c_str(), //set state_topic,name,uniqueId + "", "temperature", "{{ value_json.tempc }}", //set availability_topic,device_class,value_template, + "", "", "°C", //set,payload_on,payload_off,unit_of_meas, + 0, //set off_delay + "", "", true, "", //set,payload_avalaible,payload_not avalaible ,is a gateway entity, command topic + "", "", "", "", false, // device name, device manufacturer, device model, device MAC + stateClassMeasurement //State Class + ); # ifdef ZgatewayBT createDiscovery("sensor", //set Type subjectSYStoMQTT, "SYS: Low Power Mode", (char*)getUniqueId("lowpowermode", "").c_str(), //set state_topic,name,uniqueId diff --git a/main/config_ONOFF.h b/main/config_ONOFF.h index 4641d0fc..11e8bb88 100644 --- a/main/config_ONOFF.h +++ b/main/config_ONOFF.h @@ -46,7 +46,12 @@ extern void MQTTtoONOFF(char* topicOri, JsonObject& RFdata); #ifndef ACTUATOR_TRIGGER # define ACTUATOR_TRIGGER false // false or true, enable to control an actuator directly from the board switch (default behavior if true), or by button if ACTUATOR_BUTTON_TRIGGER_LEVEL is defined #endif - +#ifndef MAX_TEMP_ACTUATOR +//# define MAX_TEMP_ACTUATOR 70 // Temperature that will trigger the relay to go OFF +#endif +#ifndef TimeBetweenReadingIntTemp +# define TimeBetweenReadingIntTemp 5000 // Time interval between internal temp measurement to switch off the relay if MAX_TEMP_ACTUATOR is reached +#endif /*-------------------PIN DEFINITIONS----------------------*/ // default pin, if not set into the MQTT json #ifndef ACTUATOR_ONOFF_GPIO diff --git a/main/main.ino b/main/main.ino index 72ed0acc..996d48dd 100644 --- a/main/main.ino +++ b/main/main.ino @@ -227,6 +227,14 @@ static String ota_server_cert = ""; bool ProcessLock = false; // Process lock when we want to use a critical function like OTA for example +# if defined(SENS_SAR_MEAS_WAIT2_REG) +// ESP32 internal temperature reading +# include + +# include "rom/ets_sys.h" +# include "soc/rtc_cntl_reg.h" +# include "soc/sens_reg.h" +# endif # ifdef ESP32_ETHERNET # include void WiFiEvent(WiFiEvent_t event); @@ -1576,6 +1584,9 @@ void loop() { #ifdef ZactuatorFASTLED FASTLEDLoop(); #endif +#ifdef ZactuatorONOFF + OverHeatingRelayOFF(); +#endif #ifdef ZactuatorPWM PWMLoop(); #endif @@ -1631,13 +1642,32 @@ unsigned long uptime() { return uptime; } +/** + * Calculate internal ESP32 temperature + */ +#if defined(ESP32) && defined(SENS_SAR_MEAS_WAIT2_REG) +float intTemperatureRead() { + SET_PERI_REG_BITS(SENS_SAR_MEAS_WAIT2_REG, SENS_FORCE_XPD_SAR, 3, SENS_FORCE_XPD_SAR_S); + SET_PERI_REG_BITS(SENS_SAR_TSENS_CTRL_REG, SENS_TSENS_CLK_DIV, 10, SENS_TSENS_CLK_DIV_S); + CLEAR_PERI_REG_MASK(SENS_SAR_TSENS_CTRL_REG, SENS_TSENS_POWER_UP); + CLEAR_PERI_REG_MASK(SENS_SAR_TSENS_CTRL_REG, SENS_TSENS_DUMP_OUT); + SET_PERI_REG_MASK(SENS_SAR_TSENS_CTRL_REG, SENS_TSENS_POWER_UP_FORCE); + SET_PERI_REG_MASK(SENS_SAR_TSENS_CTRL_REG, SENS_TSENS_POWER_UP); + ets_delay_us(100); + SET_PERI_REG_MASK(SENS_SAR_TSENS_CTRL_REG, SENS_TSENS_DUMP_OUT); + ets_delay_us(5); + float temp_f = (float)GET_PERI_REG_BITS2(SENS_SAR_SLAVE_ADDR3_REG, SENS_TSENS_OUT, SENS_TSENS_OUT_S); + float temp_c = (temp_f - 32) / 1.8; + return temp_c; +} +#endif + #if defined(ESP8266) || defined(ESP32) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega1280__) void stateMeasures() { StaticJsonDocument jsonBuffer; JsonObject SYSdata = jsonBuffer.to(); SYSdata["uptime"] = uptime(); SYSdata["version"] = OMG_VERSION; - Log.trace(F("retrieving value of system characteristics Uptime (s):%u" CR), uptime()); # if defined(ESP8266) || defined(ESP32) uint32_t freeMem; freeMem = ESP.getFreeHeap(); @@ -1645,6 +1675,9 @@ void stateMeasures() { SYSdata["mqttport"] = mqtt_port; SYSdata["mqttsecure"] = mqtt_secure; # ifdef ESP32 +# ifdef SENS_SAR_MEAS_WAIT2_REG // This macro is necessary to retrieve temperature and not present with S3 and C3 environment + SYSdata["tempc"] = intTemperatureRead(); +# endif SYSdata["freestack"] = uxTaskGetStackHighWaterMark(NULL); # endif # ifdef ESP32_ETHERNET diff --git a/platformio.ini b/platformio.ini index 90e5ebbe..60573786 100644 --- a/platformio.ini +++ b/platformio.ini @@ -66,6 +66,8 @@ extra_configs = ;default_envs = heltec-wifi-lora-32-868 ;default_envs = heltec-wifi-lora-32-915 ;default_envs = heltec-rtl_433 +;default_envs = esp32c3-dev-m1-ble +;default_envs = esp32s3-dev-c1-ble ;default_envs = nodemcuv2-rf ;default_envs = nodemcuv2-rf-cc1101 ;default_envs = nodemcuv2-somfy-cc1101 @@ -1041,13 +1043,14 @@ build_flags = '-DZactuatorONOFF="ONOFF"' '-DACTUATOR_ON=1' '-DACTUATOR_OFF=0' - '-ACTUATOR_TRIGGER=true' + '-DACTUATOR_TRIGGER=true' '-DZsensorGPIOInput="GPIOInput"' '-DINPUT_GPIO=4' '-DGPIO_INPUT_TYPE=INPUT' '-DACTUATOR_ONOFF_GPIO=26' '-DZsensorADC="ADC"' '-DADC_GPIO=32' + '-DMAX_TEMP_ACTUATOR=70' '-DUSE_MAC_AS_GATEWAY_NAME' '-DFRAMEWORK_ARDUINO_SOLO1' '-DGATEWAY_MANUFACTURER="Shelly"'