ESP32 crashes inconsistently

Hello There,

I have a problem with a ESP32 Project. I installed a Espressif ESP32 who controlls a small Roller shutter. The commands for open door/close door come from a Webserver with connects via WLAN to the ESP. The ESP32 is running as an Accesspoint. An Linux Computer connects to this AP and sends the open/close commands. However during operation the ESP32 will eventually and inconsistently crash during a door open or close operation. I put some serial prints in the program to debug the problem. Still the ESP32 crashes randomly so I imagine its a hardware problem, however im not sure.

When the ESP32 crashes the Door will open or close completely (depends on current Action, open or close). The Indoorlights and the statuslight(warining light) activate.This is due to the hardware cabling, everything on the Relaymodule is connected as an NC Contact. Because the Relaymodule has an LLT the NC and LLT cancel each other out in the program through the not not logic.

All Voltages are meant to be DC, otherwise I will include an AC mark.

Hardware design:

The Roller shutter has two capacitive End Position Sensor(up Position and down Position)Model: Pepperl+Fuchs CBB4-12GH60-E2-V1The Sensor Signals gets converted from 24V to 3,3V by two Optocoupler relay, the 3,3V on this relay are supplied by the ESP32 3,3V Output.

Optocoupler Model: Phoenix Contact DEK-OE- 24DC/ 48DC/100

The door gets controller by the ESP over the following way: The 3,3V ESP Outputs go to a 8. Channel elegoo Relaymodule with switches 24V. This 24V go to another control cabinet and control another 24V Relais with finally switch the 230V to the shutter motor.

The elgoo Relaymodule is power by the 3,3V from the ESP. (Is this and the Optocoupler to much for the internal ESP32's 3,3V Power Supply?)

While the door is moving a warning light is active. This also goes over the Relaymodule and than to the second Relay to switch the Power.

Schutter-pipe-Motor: Somfy Oximo WT 5012622D

ESP Pinout:
Screenshot from 2024-01-10 13-20-22
S4 is currently disconnected! Its an unshielded 0,75mm² Signal wire. This caused the ESP to crash even more often.

All signal- and supplycables lie in the same Gauge tube. Max Voltage is 230V AC.

Pin 33,25,26,27= 8. Channel elgoo Relaymodul

Pin +5V /GND= Power Supply for the ESP=Mean Well HDR-15-5 DC 5V/2.4 A

GND is also used for the Optocouplers 3,3V side.

Pin 18= Optocoupler 3,3V Output, door closed

Pin 4= Optocoupler 3,3V Output, door open

I tryed two different ESP32 Dev Kits:

  1. ESP32_DevKitC_V4 with the ESP32-WROVER-E Chip with an bouild in WIFI Antenna
  2. ESP32_DevKitC_V4 with the ESP32-WROOM-32UE Chip with an external WIFI Antenna

Here are some excerpts from my cuircut diagramm for better understanding:


24V to 230V Relays, Roller shutter control unit K3 and K4 are mechanically interlocked against each other


Shutter Motor and Warning light. Motor is wired over a emergency stop NC Switch. There is also a manually overdrive for a key switch.

Do you have any idea why the ESP crashes, or what I can try to stop it doing this? If you maybe need some further info in order to help, pls ask.

My next step would be to oscillate each output/input of the ESP. Perhaps there is an unwanted voltage spike somewhere that is causing the ESP to crash.

The main.cpp from the ESP32:

#include <Arduino.h>
// #include <WiFi.h>
#include <Wire.h>
#include <SPI.h>
#include <ArduinoOTA.h>
#include "apconfig.h"
#include <WebServer.h>
#include <ArduinoJson.h>

#include <uptime.h>
int close_counter = 0;
int open_counter = 0;
////Variables
// Pin assignments on the ESP32 //PIN ASSIGNMENT WRONGE NEED CHANGE!
const unsigned int doorOpenAct = 25; //33 //NEW Pin assigment 25
const unsigned int doorCloseAct = 26; //27 //NEW Pin assigment 26
const unsigned int doorOpenedSense = 4; //4
const unsigned int doorClosedSense = 18; //18
const unsigned int indoorLights = 33; //26 //NEW Pin assigment 33
const unsigned int statusLight = 27; //25 //NEW Pin assigment 27
const unsigned int estop = 32; //32

// Door States, 0.0 closed, 0.5 undefined and 1.0 open
float doorSense =0.5;

//Status Light override
bool statusLightOverride = false;


//Internal Activity states
bool opening_active = false;
bool closing_active = false;
// bool tempsensorattached = false;

//SDH binary Status message
struct {
unsigned int doorOpenedEndstop : 1;
unsigned int doorClosedEndstop : 1;
unsigned int indoorLightsState : 1;
unsigned int statusLightState : 1;
unsigned int estopReleased : 1;
}status_static = {0,0,0,0,1};

////Objects
//Websever & JSON objects
WebServer server(80);
StaticJsonDocument<250> jsonDocument;
char buffer[250];

//Generic json creation
void create_json(char *tag1, char *data1, char *tag2, float data2) {
jsonDocument.clear();
jsonDocument[tag1] = data1;
jsonDocument[tag2] = data2;
serializeJson(jsonDocument, buffer);
}

//UpTime json creation
void create_uptime_json(){
jsonDocument.clear();
uptime::calculateUptime();
jsonDocument["uptime_d"] = uptime::getDays();
jsonDocument["uptime_h"] = uptime::getHours();
jsonDocument["uptime_m"] = uptime::getMinutes();
serializeJson(jsonDocument, buffer);
}

//SDH Status json creation
void create_status_json(){
jsonDocument.clear();
jsonDocument["door_opened"] = status_static.doorOpenedEndstop;
jsonDocument["door_closed"] = status_static.doorClosedEndstop;
jsonDocument["estop_released"] = status_static.estopReleased;
jsonDocument["indoorLightsState"] = status_static.indoorLightsState;
jsonDocument["statusLightState"] = status_static.statusLightState;
serializeJson(jsonDocument, buffer);
}

////Webserver callback functions
void sdh_open_doors(){
if(status_static.doorOpenedEndstop){
digitalWrite(doorOpenAct,HIGH);
digitalWrite(doorCloseAct,LOW);
digitalWrite(statusLight,HIGH);
opening_active = true;
closing_active = false;
create_json("device","doors","state",0.5);
}
else{
create_json("device","doors","state",1.0);

}
Serial.println("Opening Doors");
server.send(200, "application/json", buffer);
}

void sdh_close_doors(){
if(!status_static.doorClosedEndstop){
digitalWrite(doorCloseAct,HIGH);
digitalWrite(doorOpenAct,LOW);
digitalWrite(statusLight,HIGH);
closing_active = true;
opening_active = false;
create_json("device","doors","state",0.5);
}
else{
create_json("device","doors","state",0.0);
}
Serial.println("Closing Doors");
server.send(200, "application/json", buffer);
}

void sdhStopDoors(){
digitalWrite(doorOpenAct,LOW);
digitalWrite(doorCloseAct,LOW);
closing_active = false;
opening_active = false;
float response;
if(!status_static.doorOpenedEndstop && !status_static.doorClosedEndstop){
response = 1.0;
}
else if (status_static.doorOpenedEndstop && status_static.doorClosedEndstop)
{
response = 0.0;
}
else if(status_static.doorOpenedEndstop && !status_static.doorClosedEndstop)
{
response = 0.5;
}
else{
response = 0.5;
}
create_json("device","doors","state",response);
Serial.println("Stopping Doors");
server.send(200, "application/json", buffer);
}

void sdhIndoorLightsOn(){
if(digitalRead(indoorLights)){
digitalWrite(indoorLights,HIGH);
}
create_json("device","indoorlights","state",1.0);
Serial.println("Turn ON Indoors Lights");
server.send(200, "application/json", buffer);
}

void sdhIndoorLightsOff(){
if(!digitalRead(indoorLights)){
digitalWrite(indoorLights,LOW);
}
create_json("device","indoorlights","state",0.0);
Serial.println("Turn OFF Indoors Lights");
server.send(200, "application/json", buffer);
}

void sdhStatusLightOn(){
statusLightOverride = true;
if(digitalRead(statusLight)){
digitalWrite(statusLight,HIGH);
}
create_json("device","statusLight","state",1.0);
Serial.println("Turn ON Status Lights");
server.send(200, "application/json", buffer);
}

void sdhStatusLightOff(){
if(!digitalRead(statusLight)){
digitalWrite(statusLight,LOW);
}
statusLightOverride = false;
create_json("device","statusLight","state",0.0);
Serial.println("Turn OFF Status Lights");
server.send(200, "application/json", buffer);
}


void sdhStatus(){
status_static.indoorLightsState = !digitalRead(indoorLights);
status_static.statusLightState = !digitalRead(statusLight);
status_static.doorClosedEndstop = digitalRead(doorClosedSense);
status_static.doorOpenedEndstop = digitalRead(doorOpenedSense);
status_static.estopReleased = !digitalRead(estop);
create_status_json();
Serial.println("Status requested");
server.send(200, "application/json", buffer);
}

void sdhUptime(){
create_uptime_json();
Serial.println("Uptime requested");
server.send(200, "application/json", buffer);
}

// Setup Webserver api URLs
void setupWebServer(){

server.on("/doors/open",sdh_open_doors);
server.on("/doors/close",sdh_close_doors);
server.on("/doors/stop",sdhStopDoors);
server.on("/indoorlights/on", sdhIndoorLightsOn);
server.on("/indoorlights/off", sdhIndoorLightsOff);
server.on("/statuslight/on", sdhStatusLightOn);
server.on("/statuslight/off", sdhStatusLightOff);
server.on("/status",sdhStatus);
server.on("/uptime", sdhUptime);
server.begin();
}

//Configure ESP32 Pins for startup
void setupPins(){
pinMode(doorOpenAct,OUTPUT);
digitalWrite(doorOpenAct, LOW);
pinMode(doorCloseAct,OUTPUT);
digitalWrite(doorCloseAct, LOW);
pinMode(indoorLights, OUTPUT);
digitalWrite(indoorLights, LOW);
pinMode(statusLight, OUTPUT);
digitalWrite(statusLight, LOW);
pinMode(estop,INPUT_PULLUP);
pinMode(doorOpenedSense, INPUT_PULLDOWN);
pinMode(doorClosedSense, INPUT_PULLDOWN);
}


////------------------------------------------------------------------------------------------------
void setup() {
Serial.begin(115200);
setupPins();
Serial.println("Setup Complete1");
//Setup Wifi either as AP or client as defined in apconfig.h
WiFi.softAPConfig(local_ip, gateway_ip, subnet);
Serial.println("Setup Complete2");
WiFi.softAP(ssid, passwd);
Serial.println("Setup Complete3");

//Setup OTA flashing
ArduinoOTA.setPort(OTAport);
Serial.println("Setup Complete4");
ArduinoOTA.begin();
Serial.println("Setup Complete5");

Serial.println("Setup Complete");
//Satrt Webserver API
setupWebServer();
Serial.println("Setup Complete6");
}

void loop() {

//Handle OTA & Web API requests
ArduinoOTA.handle();
server.handleClient();

status_static.doorOpenedEndstop = digitalRead(doorOpenedSense);
status_static.doorClosedEndstop = digitalRead(doorClosedSense);
status_static.estopReleased = digitalRead(estop); //!digitalRead(estop); without ! because of error !!!! Wenn Not-Halt wieder hinzugefügt ! wieder ins programm implementieren

if(!status_static.doorOpenedEndstop){
// Serial.println("top sensor free");
}
if(status_static.doorClosedEndstop){
// Serial.println("bottom sensor triggered");
}

if(!status_static.estopReleased){
digitalWrite(doorOpenAct, LOW);
digitalWrite(doorCloseAct, LOW);
opening_active = false;
closing_active = false;
Serial.println("Estop pressed");
}
else if(!status_static.doorOpenedEndstop && opening_active){
// add +1 to the close_counter
open_counter = open_counter + 1;
// if close_counter is 300, then the door is opend
if (open_counter == 300) { //Counter helps to contain the bouncing of the sensors
delay(1000); // TEMP REMOVE
digitalWrite(doorOpenAct, LOW);
digitalWrite(doorCloseAct, LOW);
digitalWrite(statusLight,LOW);
opening_active = false;
Serial.println("Opened Door");
open_counter = 0;
}Serial.println(open_counter);}

/*else if( status_static.doorClosedEndstop && closing_active){
delay(5000);
digitalWrite(doorCloseAct, LOW);
digitalWrite(doorOpenAct, LOW);
digitalWrite(statusLight,LOW);
closing_active = false;
Serial.println("Closed door");
} */

else if (status_static.doorClosedEndstop && closing_active)
{
// add +1 to the close_counter
close_counter = close_counter + 1;
// if close_counter is 300, then the door is closed
if (close_counter == 300) { //Counter helps to contain the bouncing of the sensors
delay(7000);
digitalWrite(doorCloseAct, LOW);
digitalWrite(doorOpenAct, LOW);
digitalWrite(statusLight, LOW);
closing_active = false;
Serial.println("Closed door");
close_counter = 0; }
Serial.println(close_counter);}
else if (!opening_active && !closing_active && !statusLightOverride){
digitalWrite(statusLight,LOW);
}

}

Yes it most likely is. Relays tend to be require quite a bit of power and the 3.3v regulator on board the ESP32, although rated for 600mA depends on the heatsink.
I would power the relays in some other way, ideally separated as much from the ESP32 as possible, and even use opto-couplers to control the relays (that may already be on the relay board though)

If you have a stable 5V source you can just add a linear 3.3v regulator in a TO-220 package and a few capacitors and that should do the trick. Or you can probably power the relay module with 5v, i suspect it will take that as a power input (3.3v relays are so rare also because 5v relays work on 3.3v as well mostly)

This is a big No-No, EMI will cause all types of cross talk and as you indicate when the coils cycle you have problems, this is to be expected. You will need snubbers and zero cross if possible.

Totally agree with you on that as well. Signal wise only DALI is safe and able to share with AC mains, and LOW voltage and HIGH voltage power should stay separated.
It does depend a bit on the distance, but why

But Why ? The supply cables don't have to be. You need 230V only up to the relay board. Beyond that, all can be LOW voltage.

1 Like

Fristly, thank you for your answeres.

@Deva_Rishi
I made a mistake, the Relaymodule is already connected to 5V from the ESP.
However, I found this passage in the instructions for the module: "VCC and RY-VCC are also the power supply of the relay module. When you need to drive a large power load, you can take the jumper cap off and connect an extra power to RY-VCC to supply the relay; connect VCC to 5V of the MCU board to supply input signals.
NOTES: If you want complete optical isolation, connect "Vcc" to Arduino +5 volts but do NOT connect Arduino Ground. Remove the Vcc to JD-Vcc jumper. Connect a separate +5 supply to "JD-Vcc" and board Gnd. This will supply power to the transistor drivers and relay coils.
If relay isolation is enough for your application, connect Arduino +5 and Gnd, and leave Vcc to JD-Vcc jumper in place."

I will supply the jumper pins of the Relaymodule separately with 5V.

@gilshultz @Deva_Rishi
Let me explain in more detail: The 230V for the Motor/lights etc. is provided in a NYM cable. The signal cable with 24V is in a shielded cable in the same ductwork. The shield of this cable is connected to PE. I am attaching pictures for a better understanding. Only the currently unused emergency off signal line is unfortunately an unshielded cable. Is this still a big EMC problem?


ESP32 cabinet

ductwork marked in red

That is a good idea.

That does look like a fairly hostile environment for the ESP, but when the cables are only short, it should be within tolerance. Also the Adapter board / PCB has a shield usually incorporated in it.
To be clear, what i see in the first picture, makes me think it should be ok, but i can't tell where the cables are going and to what they are attached.

The relays draw significant power when switched and can cause voltage spikes and reverse voltages, but the board has components on there to deal with that, but the whole thing does have to be adequately powered.

I am still not quite clear on how you have connected everything to the ESP. Did you mention sensors ?
Best is if you draw a simple schematic, where all is in one picture. It doesn't need to be super detailed.

Anything that is directly connected to the ESP32 can cause issues, still usually just wrong readings and not random resets.

I looked at your code again and there is nothing that jumped out at me as wrong.

Still there must be some cause, let's hope it's the shared ground between the ESP and the relay board. ESP32's can be tricky, more people have reported strange resets, and i have some working that i have to give a power cycle at times because they stop doing what they are supposed to, but they are not that fragile.

Well that is already better than using the 3.3v !

That is what you want, you can use just a small 5v or 3.3v PSU for the ESP 500mA will do just fine.

What goes through the coil of wire (antenna) on the bottom.

Hello guys, so since I have connected the jumper Pins from the Relaymodule to 5V seperatly everything is working like it should. The shutter door works fine.

I would like to thank you for your help and input :slight_smile:

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.