Executando verificação de segurança...
3

Problema com o botão de reset no ESP32-CAM - não reinicia como esperado

Olá, estou usando um ESP32-CAM e configurei um botão de reset no pino GPIO 0.

Quando pressiono o botão, espero que o ESP32 reinicie, mas isso não está acontecendo. O LED no ESP32 acende corretamente, mas o reset não é acionado.

#include <Arduino.h>
#include <ArduinoJson.h>
#include <WebSocketsClient.h>
#include <WiFiManager.h>

#include <WiFi.h>
#include <HTTPClient.h>

String cod_esp = "id";

#define MACHINE_ID "id"
const char *websocket_server = "ws://ip";
const int websocket_port = 8080;
const char *websocket_path = "/api/websocket";

WebSocketsClient webSocket;
WiFiManager wm;

// Pinagem do pulso
#define PULSE_PIN 4
#define LED_OK 3
#define LED_FAIL 1

// Pinagem para envio de pulso via HTTP
#define PULSE_IN_P01 12
#define PULSE_IN_P02 13
#define PULSE_IN_P03 15

String URL_base = "http://ip/web/P017S-WEB/P017S-WEB-V30.0/";

int counter = 0;
bool connection = false;
const int buttonPin = 0;
enum ButtonState { RELEASED, 
                   PRESSED, 
                   LONG_PRESS };
ButtonState buttonState = RELEASED;
unsigned long buttonPressStartTime;

const unsigned long LED_BLINK_INTERVAL = 500;
unsigned long lastLEDChangeTime = 0;

float n = 0.00;
int x = 0;
int verificador = 1;

//Variáveis para contagem de pulso
volatile bool interruptFlagP01 = false;
volatile bool interruptFlagP02 = false;
volatile bool interruptFlagP03 = false;

unsigned long lastInterruptTimeP01 = 0;
unsigned long lastInterruptTimeP02 = 0;
unsigned long lastInterruptTimeP03 = 0;

//const unsigned long PassaBaixo = 2;

int cont_P01 = 0;
int cont_P02 = 0;
int cont_P03 = 0;

//Funções da configuração de pulsos
int opcao = 1024;
int num_pulso = 0;
int duracao_on = 0;
int duracao_off = 0;

int tempo_restart = 30000;
int tempo_inicial = 0;
int ver_setup = 0;

//Funções que contam o número de pulsos
void handleInterrupt01() {
  unsigned long interruptFlagP01 = millis();
  lastInterruptTimeP01 = interruptFlagP01;
  cont_P01++;
  Serial.println("SINAL");
}

void handleInterrupt02() {
  unsigned long interruptFlagP02 = millis();
  lastInterruptTimeP02 = interruptFlagP02;
  cont_P02++;
  Serial.println("SINAL");
}

void handleInterrupt03() {
  unsigned long interruptFlagP03 = millis();
  lastInterruptTimeP03 = interruptFlagP03;
  cont_P03++;
  Serial.println("SINAL");
}

String appendString(String original, String toAdd) { 
  return original + toAdd; 
}

int transf(int valor_aux) {
  switch (opcao) {
  case 0:
    return valor_aux;
    break;
  case 1:
    switch (valor_aux) {
    case 1:
      return 1;
      break;
    case 2:
      return 2;
      break;
    case 5:
      return 3;
      break;
    case 10:
      return 4;
      break;
    case 20:
      return 5;
      break;
    case 50:
      return 6;
      break;
    case 100:
      return 7;
      break;
    default:
      return 0;
      break;
    }
    break;
  case 2:
    return valor_aux;
    break;
  case 3:
    return num_pulso;
    break;
  case 4:
    return num_pulso * valor_aux;
    break;
  default:
    return 0;
    break;
  }
}

bool isConnectedToInternet() {
  return WiFi.status() == WL_CONNECTED;
}

void webSocketEvent(WStype_t type, uint8_t *payload, size_t length) {
  StaticJsonDocument<1024> doc;

  switch (type) {
		case WStype_DISCONNECTED: {
			Serial.println("WebSocket Disconnected");
			digitalWrite(LED_FAIL, HIGH);
			digitalWrite(LED_OK, LOW);
			break;
		}
		case WStype_CONNECTED: {
			Serial.println("WebSocket Connected");
			digitalWrite(LED_OK, HIGH);
			digitalWrite(LED_FAIL, LOW);
			webSocket.sendTXT("CONNECT\naccept-version:1.1,1.0\n\n\x00");
			webSocket.sendTXT("SUBSCRIBE\ndestination:/topics/machine/" MACHINE_ID
							  "\nid:sub-" MACHINE_ID "\nack:auto\n\n\x00");
			break;
		}
		case WStype_TEXT: {
			Serial.printf("WebSocket Message: %s\n", payload);
			deserializeJson(doc, payload);

			float credits = doc["credits"];
			const char *message = doc["message"];

			Serial.printf("Message: %s, Credits: %.2f\n", message, credits);
			if (credits >= 1.0) {
				int numeroDePulsos = transf(static_cast<int>(credits));
				while (numeroDePulsos > 0) {
					digitalWrite(PULSE_PIN, HIGH);
					delay(duracao_on);
					digitalWrite(PULSE_PIN, LOW);
					delay(duracao_off);
					numeroDePulsos--;
				}
			}
			break;
		}

		case WStype_ERROR: {
			Serial.printf("WebSocket Error: %s\n", payload); // Adiciona o payload do erro
			break;
		}
	}
}

int UpPulseValuer(int P01, int P02, int P03) {
    String url = "";
    url = appendString(url, URL_base);
    url = appendString(url, "?");
    url = appendString(url, "code_esp=");
    url = appendString(url, cod_esp);
    url = appendString(url, "&P01=");
    url = appendString(url , String(P01));
    url = appendString(url, "&P02=");
    url = appendString(url, String(P02));
    url = appendString(url, "&P03=");
    url = appendString(url, String(P03));

  HTTPClient http;
  WiFiClient wifiClient;
  http.begin(url);

  Serial.println(String(P01));
  Serial.println(String(P02));
  Serial.println(String(P03));

  int httpResponseCode = http.GET();

  if (httpResponseCode > 0) {
    String response = http.getString();
    Serial.println("Resposta HTTP:");
    Serial.println(response);
    http.end();
    cont_P01 = 0;
    cont_P02 = 0;
    cont_P03 = 0;
    return 0;
  } else {
    Serial.print("Erro ao enviar a requisição: ");
    Serial.println(httpResponseCode);
    http.end();
    return -1;
  }
}

void setup() {
  Serial.begin(115200);

  pinMode(buttonPin, INPUT_PULLUP);
  pinMode(LED_OK, OUTPUT);
  pinMode(LED_FAIL, OUTPUT);
  pinMode(PULSE_PIN, OUTPUT);
  pinMode(PULSE_IN_P01, INPUT_PULLUP);
  pinMode(PULSE_IN_P02, INPUT_PULLUP);
  pinMode(PULSE_IN_P03, INPUT_PULLUP);
  
  attachInterrupt(digitalPinToInterrupt(PULSE_IN_P01), handleInterrupt01, RISING);
  attachInterrupt(digitalPinToInterrupt(PULSE_IN_P02), handleInterrupt02, RISING);
  attachInterrupt(digitalPinToInterrupt(PULSE_IN_P03), handleInterrupt03, RISING);

  WiFiManagerParameter custon_duracao_on_aux ("num_pulso_aux", "<br> <br> duração do pulso (Disponível anenas para opção especial)", "0", 10);
  WiFiManagerParameter custon_duracao_off_aux("duracao_on_aux", "duração do intervalo entre pulsos (Disponível anenas para opção especial)", "0", 10);
  WiFiManagerParameter custon_num_pulso_aux("duracao_off_aux", "numero de pulsos (Disponível anenas para opção especial)", "0", 10);
  WiFiManagerParameter custom_param("opcao", "0 para 50x100 Hall <br> 1 para 30x30 Show <br> 2 para 100x100 Hall <br> 3 para Especial fixo <br> 4 para Especial Aberto", "0", 10);

  wm.addParameter(&custom_param);
  wm.addParameter(&custon_num_pulso_aux);
  wm.addParameter(&custon_duracao_on_aux);
  wm.addParameter(&custon_duracao_off_aux);

  opcao = atoi(custom_param.getValue());

  /////Configuração wifi manager////////////
  wm.setConfigPortalTimeout(60);
  if (!wm.autoConnect("PixPi_001", "pix99177")) {
    wm.startConfigPortal("PixPi_001", "pix99177");
    delay(10000);
    ESP.restart();
  } else {
    digitalWrite(LED_OK, HIGH);
    digitalWrite(LED_FAIL, LOW);
    delay(1000);
    digitalWrite(LED_OK, LOW);
  }

  webSocket.begin(websocket_server, websocket_port, websocket_path);
  webSocket.onEvent(webSocketEvent);
  webSocket.setReconnectInterval(5000);
}

void loop() {
  webSocket.loop();

  if ((cont_P01 + cont_P02 + cont_P03) > 0) {
    UpPulseValuer(cont_P01, cont_P02, cont_P03);
  }

  Serial.println("LOOP OK");
  Serial.println(num_pulso);
  Serial.println(duracao_on);
  Serial.println(duracao_off);

  unsigned long currentMillis = millis();
  if (currentMillis - lastLEDChangeTime >= LED_BLINK_INTERVAL) {
    lastLEDChangeTime = currentMillis;

    if (!webSocket.isConnected() || !isConnectedToInternet()) 
    {
      counter++;
      digitalWrite(LED_FAIL, !digitalRead(LED_FAIL));
      digitalWrite(LED_OK, LOW); 

      if (counter >= 5) {
        Serial.println("Conexão falhou por muito tempo, reiniciando o ESP...");
        ESP.restart();  // Reinicia se falha persistir
      }     
    } else {
      counter = 0;
      // Piscar LED verde se tudo estiver ok
      digitalWrite(LED_OK, !digitalRead(LED_OK));
      digitalWrite(LED_FAIL, LOW);  // Garante que o LED vermelho esteja desligado
    }
  }

  if (isConnectedToInternet()) {
    Serial.println(
        "Conectado à Internet. Agora você pode realizar operações online.");
  } else {
    Serial.println(
        "Não foi possível conectar à Internet. Verifique a conexão WiFi.");
  }

  int buttonRead = digitalRead(buttonPin);
  switch (buttonState) {
  case RELEASED:
    if (buttonRead == LOW) {
      buttonPressStartTime = millis();
      buttonState = PRESSED;
    }
    break;
  case PRESSED:
    if (buttonRead == HIGH) {
      buttonState = RELEASED;
      ESP.restart();
    } else if (millis() - buttonPressStartTime >= 2000) {
      digitalWrite(LED_OK, LOW);
      digitalWrite(LED_FAIL, HIGH);
      WiFiManager wm;
      wm.resetSettings();
      ESP.restart();
      buttonState = LONG_PRESS;
    }
    break;
  case LONG_PRESS:
      if (buttonRead == HIGH) {
        buttonState = RELEASED;
        ESP.restart();
      }
    break;
  }
}

Aqui está um vídeo que mostra o problema ao testar o botão de reset: video testando

Alguém já teve esse problema ou tem sugestões do que posso tentar?

Obrigado!

Carregando publicação patrocinada...
1

Eu recomendaria usar outro GPIO, já que o GPIO0 é usado para o sinal de boot do esp32. Existe o GPIO 'EN' para o propósito de reset do microcontrolador. Não cheguei a ler o código de fato, mas só de dar uma passada de olho e vendo o teu propósito, eu recomendaria fortemente usar ESP-IDF ao invés do framework Arduino, já que conta com freertos e você vai ter um controle/workflow bem melhor do seu projeto que lida com máquina de estados, tratamento de interrupções, a parte do websocket e organização em árvore de arquivos.