Alimentação de eletroímã e travamento do arduino

Estou enfrentando um problema na alimentação do meu Arduino. O sistema utiliza duas fontes distintas:

Uma fonte de 12V, responsável por alimentar o teclado NICE e também um eletroímã. O negativo dessa fonte está conectado diretamente a um dos terminais do eletroímã, enquanto o positivo vai para o terminal COMUM do módulo relé, que por sua vez controla a alimentação do outro terminal do eletroímã.
Uma segunda fonte de 9V está sendo usada para alimentar o Arduino e também o módulo relé.

Para que o teclado funcione corretamente, há um jumper ligando os aterramentos (GND) das duas fontes, garantindo um referencial comum.

O problema ocorre quando o relé é desligado (ou seja, corta a alimentação do eletroímã): nesse momento, o sistema trava e o eletroímã permanece sem energia. A única forma de restabelecer o funcionamento é pressionando o botão de reset do Arduino.

ARDUINO UNO
ETHERNET SHIELD W5100
MODULO RELE 8 CANAIS
FONTE 12V 2A
FONTE 9V 1A
TECLADO NICE LN001-A

Funcionamento adequado o usuário digita a senha, o arduino abre uma comunicação mqtt com servidor, verifica a senha e libera a porta, por vezes o funcionamento tem o travamento

Olá @weidson!

Ver Como obter o melhor deste fórum, no primeiro tópico fixado de qualquer thread, inclusive esta.
Inclua um esquema de como você ligou tudo, pode ser uma foto de um desenho feito à mão em papel.
Poste seu código. Use a auto formatação do Arduino para torná-lo mais legivel, e a chave <code> aqui do fórum para manter esta formatação no post e facilitar a cópia, caso alguém resolva testá-lo para ver se há algo errado.

O sintoma descrito me leva a crer que seu projeto com arduino está sofrendo da sindrome da falta de um snubber.
Mas somente poderei ter mais certeza disso se voce fizer o que recomendou @dilberto : Publicar um esquematico, (mesmo a mão livre), do seu projeto.

#include <SPI.h>
#include <Ethernet.h>
#include <PubSubClient.h>
#include <Wiegand.h>
#include <avr/wdt.h> // Watchdog para reiniciar

#define WIEGAND_D0 2
#define WIEGAND_D1 3
const byte relayPins[5] = {4, 5, 6, 7, 8};

// Configurações de rede
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };

// Cliente Ethernet e MQTT
EthernetClient ethClient;
PubSubClient client(ethClient);
WIEGAND wg;

// MQTT config
const char* mqtt_server = "dominio";
const int mqtt_port = 8000;
const char* mqtt_user = "usuario";
const char* mqtt_pass = "senha";

const int condominio_id = 4; //alterar o id do condominio

String senhaDigitada = "";

unsigned long relayTimer[5] = {0, 0, 0, 0, 0};
bool relayActive[5] = {false, false, false, false, false};

// Teste de conexão
IPAddress ipTeste(192, 168, 0, 1); // definir ip de teste sempre o gateway da rede
unsigned long ultimoTeste = 0;
const unsigned long intervaloTeste = 60000; // a cada 1 minutos
int falhasConsecutivas = 0;
const int limiteFalhas = 4;

void setup() {
  Serial.begin(9600);
  delay(2000);

  Ethernet.begin(mac);
  Serial.print("IP atribuído: ");
  Serial.println(Ethernet.localIP());

  client.setServer(mqtt_server, mqtt_port);
  client.setCallback(callback);

  wg.begin(WIEGAND_D0, WIEGAND_D1);

  for (int i = 0; i < 5; i++) {
    pinMode(relayPins[i], OUTPUT);
    digitalWrite(relayPins[i], LOW); // Relé desativado (NF)
  }
}

void loop() {
  if (!client.connected()) reconnect();
  client.loop();

  if (wg.available()) {
    uint32_t codigo = wg.getCode();
    byte bits = wg.getWiegandType();

    if (bits == 4) {
      char tecla = traduzTecla(codigo);
      Serial.print("Tecla pressionada: ");
      Serial.println(tecla);

      if (tecla == '#') {
        if (senhaDigitada.length() > 0) {
          String topicoSenha = "controle/" + String(condominio_id) + "/senha";
          client.publish(topicoSenha.c_str(), senhaDigitada.c_str());
          Serial.print("Senha enviada: ");
          Serial.println(senhaDigitada);
          senhaDigitada = "";
        }
      } else {
        senhaDigitada += tecla;
      }
    }
  }

  for (int i = 0; i < 5; i++) {
    if (relayActive[i] && millis() - relayTimer[i] >= 5000) {
      digitalWrite(relayPins[i], LOW);
      relayActive[i] = false;
      Serial.print("Relé ");
      Serial.print(i + 1);
      Serial.println(" desativado.");
    }
  }

  testarConexaoRede(); // Testa a conexão a cada 5 minutos
}

char traduzTecla(uint32_t codigo) {
  switch (codigo) {
    case 0: return '0'; case 1: return '1'; case 2: return '2'; case 3: return '3';
    case 4: return '4'; case 5: return '5'; case 6: return '6'; case 7: return '7';
    case 8: return '8'; case 9: return '9'; case 10: return '*'; case 13: return '#';
    default: return '?';
  }
}

void callback(char* topic, byte* payload, unsigned int length) {
  String msg;
  for (unsigned int i = 0; i < length; i++) msg += (char)payload[i];

  Serial.print("Mensagem recebida - Tópico: ");
  Serial.print(topic);
  Serial.print(" | Mensagem: ");
  Serial.println(msg);

  for (int i = 1; i <= 5; i++) {
    String topicoEsperado = "controle/" + String(condominio_id) + "/abrir/" + String(i);
    if (String(topic) == topicoEsperado) {
      ativarRele(i - 1);
    }
  }
}

void ativarRele(int index) {
  if (index >= 0 && index < 5 && !relayActive[index]) {
    digitalWrite(relayPins[index], HIGH);
    relayTimer[index] = millis();
    relayActive[index] = true;

    Serial.print("Relé ");
    Serial.print(index + 1);
    Serial.println(" ativado.");
  } else {
    Serial.print("Ignorando comando para relé ");
    Serial.print(index + 1);
    Serial.println(" (já ativo ou fora do range).");
  }
}

void reconnect() {
  while (!client.connected()) {
    Serial.println("Tentando reconectar ao MQTT...");

    String clientId = "arduino-condominio-" + String(condominio_id);
    if (client.connect(clientId.c_str(), mqtt_user, mqtt_pass)) {
      Serial.print("Conectado ao broker MQTT como ");
      Serial.println(clientId);

      for (int i = 1; i <= 5; i++) {
        String topico = "controle/" + String(condominio_id) + "/abrir/" + String(i);
        client.subscribe(topico.c_str());
        Serial.print("Inscrito no tópico: ");
        Serial.println(topico);
      }
    } else {
      Serial.print("Falha na conexão. Código: ");
      Serial.println(client.state());
      delay(2000);
    }
  }
}

// Função para testar a conexão a cada 5 minutos
void testarConexaoRede() {
  if (millis() - ultimoTeste < intervaloTeste) return;

  ultimoTeste = millis();
  Serial.print("Testando IP ");
  Serial.println(ipTeste);

  EthernetClient teste;
  if (teste.connect(ipTeste, 80)) {
    Serial.println("Conexão bem-sucedida.");
    teste.stop();
    falhasConsecutivas = 0;
  } else {
    Serial.println("Falha na conexão.");
    falhasConsecutivas++;

    if (falhasConsecutivas >= limiteFalhas) {
      Serial.println("Falhas consecutivas excedidas. Reiniciando via watchdog...");
      delay(100);
      wdt_enable(WDTO_15MS); // Ativa watchdog com timeout mínimo
      while (1); // Espera o reset
    }
  }
}

no diagrama o rele é um modulo 8 canais, porem só 5 em uso, nao sei desenhar muito mas a ligação é exatamente essa

Realmente voce está tendo problemas pela falta de um snubber.
"Snubber - Wikipedia

Monte este diodo onde mostra a seta vermelha e veja se resolve.

(Observe a polaridade correta do diodo).

perfeito, vou realizar os testes e retorno com o resultado!

Boa noite, a priore solucionou o problema, deixei o sistema funcionando durante a tarde de hoje, infelizmente tive poucos acionamento, mas continuarei testando amanhã para ter um teste mais exato!

Obrigado a todos, realmente o diodo resolveu o problema!

Olá, @weidson!

Então, não esqueça de marcar o tópico como resolvido e a resposta do @ruilviana como a solução.

Isto ajuda muito outros integrantes do fórum que tenham problemas semelhantes aos teus. E parece que são muitos, este é um problema recorrente em eletrônica.

Abração!

1 Like