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:
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:
- ESP32_DevKitC_V4 with the ESP32-WROVER-E Chip with an bouild in WIFI Antenna
- 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);
}
}