Arduino uno R3 se resetea o se detiene con uso de relé y corriente AC

Saludos estimados compañeros. Estoy comenzando en el mundo del Arduino y estoy desarrollando un sistema de control para una maquinaria y necesito de la ayuda de ustedes. Es un proyecto sencillo que se trata de activar y desactivar una bobina cada 6 segundos al mismo tiempo que lleva un contador programable entre 5 minutos y 50 minutos. También se miden los valores de temperatura en dos puntos de la máquina y se muestra el diferencial de temperatura en el LCD. Todo esto se muestra en una pantalla LCD conectada por I2C.

Cuando ejecuto el proyecto sin aplicarle carga a las bobinas que pasan por el relé funciona perfectamente.
El problema se presenta cuando circula la corriente por los relés (12V AC) que se encargan de activar la bovina de un contactor. Luego de arrancar el sistema, pasado un tiempo, justo en el momento que se activa o desactiva el relé cada 6 segundos viene el problema. El arduino en algunas ocasiones se resetea y en otras se congela la cuenta regresiva. Estoy utilizando dos módulos de relés optoacoplados.
Estoy energizando todo con fuente externa y del Arduino solamente saco las conexiones de los sensores.
No soy un experto. El código lo armé con la ayuda de varios proyectos que están en algunas discusiones y tutoriales.
Voy a adjuntar el código y el esquema de conexión.
Mil gracias de antemano por su ayuda.

#include <OneWire.h>
#include <DallasTemperature.h>
// Data wire is plugged into digital pin 2 on the Arduino
#define ONE_WIRE_BUS 8
// Setup a oneWire instance to communicate with any OneWire device
OneWire oneWire(ONE_WIRE_BUS);
// Pass oneWire reference to DallasTemperature library
DallasTemperature sensors(&oneWire);

int deviceCount = 0;
float tempC;
#define LED1 11
#define LED2 12
#define LED3 13
#include <EEPROM.h>
#include <Wire.h> 
#include <LiquidCrystal_I2C.h>      // Libreria del display LCD en caso que sea I2C
LiquidCrystal_I2C lcd(0X27,20,4);  // Direccion display LCD en caso que sea I2C

int ledState1 = LOW;
int ledState2 = LOW;

unsigned long previousMillisLed1 = 0;
unsigned long currentMillisLed1 = 0;
unsigned long previousMillisLed2 = 0;
unsigned long currentMillisLed2 = 0;
const long intervalLed1 = 6000;
const long intervalLed2 = 1000;

int relevo=10;    //Carga
int msg=0;        //Bandera para el mensaje de bienvenida
int star=9;       //Pulsador de Arranque

int butm=7;       //Pulsador de incremento minutos
int buts=6;       //Pulsador de incremento segundos

int varbutm=0;    //Variable para almacenar el valor del pulsador incremento de minutos
int varbuts=0;    //Variable para almacenar el valor del pulsador incremento de segundos

int varstar=0;    //Variable para almacenar el valor del pulsador de start
int ahoras=0;
int aminutos=0;
int asegundos=0;
int segundostotal = 0;     //Tiempo total

int temp_horas = 0;
int temp_minutos = 0;
int temp_segundos = 0;

int dirh=0;     //Variable para almacenar la direccion de horas de la memoria EEPROM
int dirm=1;     //Variable para almacenar la direccion de minutos de la memoria EEPROM
int dirs=2;     //Variable para almacenar la direccion de segundos de la memoria EEPROM
int dirflag=3;  //Variable para usar como bandera para saber si debo leer datos de EEPROM
int valida=0;

int segundos = 0;
unsigned long milisegundos = 0;
unsigned long tiempo1 = 0;
unsigned long tiempoSegundos = 0;
int fin=0;



void setup() {

  pinMode(LED1, OUTPUT);
  pinMode(LED2, OUTPUT);
  pinMode(LED3, OUTPUT);
  sensors.begin();  // Start up the library
  Serial.begin(9600);
  // Inicializamos el LCD
  lcd.init(); 
  lcd.begin(20, 4);         //Configuramos el n�mero de columnas y filas del lcd
  lcd.backlight();          //Encender la luz de fondo.
  pinMode(relevo, OUTPUT);
  pinMode(butm, INPUT);
  pinMode(buts, INPUT);
  pinMode(star, INPUT);
  msg=0;

  deviceCount = sensors.getDeviceCount();
  
  
valida = EEPROM.read(dirflag);  //Obtiene dato de dirflag para comprobar si debo leer EEPROM
  if(valida==1){
   aminutos = EEPROM.read(dirm);  // Obtiene el dato int de EEPROM y lo env�a a la variable aminutos
   asegundos = EEPROM.read(dirs); // Obtiene el dato int de EEPROM y lo env�a a la variable asegundos
  }
    
  lcd.setCursor(0,0);             //Ubicamos el cursor en posicion 0 LCD primera linea
  lcd.print("      SISTEMA");
  lcd.setCursor(0,1);            //Ubicamos el cursor en LCD en posicion 0 segunda linea
  lcd.print("DE CONTROL");
  lcd.setCursor(0,2);             //Volvemos a ubicar el cursor, ahora en la linea de abajo
  lcd.print("TEMPORIZADO");  //Mensaje que se muestra a partir de la posici�n anterior del cursor

}

void loop() {
if(msg==0){                         //Si esta condici�n se cumple mostraremnos el mensje de bienvenida solo una vez
      lcd.setCursor(0,0);             //Ubicamos el cursor en LCD
      lcd.print("      SISTEMA");  //Mensaje que se muestra a partir de la posici�n anterior del cursor
      lcd.setCursor(0,1);             //Volvemos a ubicar el cursor, ahora en la linea de abajo
      lcd.print("DE CONTROL");  //Mensaje que se muestra a partir de la posici�n anterior del cursor
      lcd.setCursor(0,2);             //Volvemos a ubicar el cursor, ahora en la linea de abajo
      lcd.print("    TEMPORIZADO");  //Mensaje que se muestra a partir de la posici�n anterior del cursor
      delay(3000);                    //tiempo que aparece el mensaje en pantalla
      msg=1;                          //Cambiamos el valor de msg, para que no vuelva a mostrar el mensaje, a menos que lo apaguemos o reiniciemos
      lcd.clear();                    //Borramos la pantalla
  }
 
 
                                      //Ahora, pasaremos a leer los datos que mandan los pulsadores, que seran los que programen el tiempo
                                      //Esto lo haremos con la orden "do", para que entre en bucle y este leyendo continuamente, hasta que 
                                      //terminemos de ajustar el tiempo y le demos al boton de arranque
  do {       
           
    
    varbutm=digitalRead(butm);
    varbuts=digitalRead(buts);
    varstar=digitalRead(star);
    

  
    if(varbutm==HIGH){
        aminutos=aminutos+5;
        if(aminutos>=51){
           
            aminutos=50;
           
        
        }
        delay(250);
    }
 
    if(varbuts==HIGH){
        aminutos=aminutos-5;
        if(aminutos<=0){
           
            aminutos=5;
            
           
                        
        }
        delay(250);
    }

    lcd.setCursor(0,0);
    lcd.print(" Ajuste los minutos ");
    lcd.setCursor(7,1);
    
    if(aminutos<10){              //Esto es para poner un 0 delante si los minutos son menor de 10
        lcd.print("0");
    }
    lcd.print(aminutos);
    lcd.print(":");
    if(asegundos<10){             //Esto es para poner un 0 delante si los segundos son menor de 10
        lcd.print("0");
    }
        lcd.print(asegundos);
  }while(varstar==LOW); 


    
    if(varstar==HIGH){        
       
        temp_minutos = aminutos;         //Guardo la configuracion de minutos en una variable temporal
        temp_segundos= asegundos;        //Guardo la configuracion de segundos en una variable temporal

        valida = 1;       
        EEPROM.update(dirflag, valida);  // Se escribe la direccion 3 de la EEPROM con el valor 1 si el valor es diferente de 1      
        EEPROM.write(dirm, aminutos);  // Se agrega a EEPROM con la direcci�n primero y valor de la variable despu�s
        EEPROM.write(dirs, asegundos);
        
        lcd.setCursor(0,0);
        lcd.print("                    ");   // Limpio la primer fila del LCD con 20 espacios en blanco   
    
                do {
          
        //contador de segundos
        //..........................................................................................................................     
  
        digitalWrite(relevo, HIGH);          //Activamos la carga mientras dure el contador
        lcd.setCursor(0, 2);
        lcd.print(" Temp1  Temp2  Difer");
  {
  currentMillisLed1 = millis();
   if (currentMillisLed1 - previousMillisLed1 >= intervalLed1) {

    previousMillisLed1 = currentMillisLed1;



    if (ledState1 == LOW) {

      ledState1 = HIGH;

    } else {

      ledState1 = LOW;

    }

  }
  digitalWrite(LED1, ledState1);
}
{
  currentMillisLed2 = millis();
   if (currentMillisLed2 - previousMillisLed2 >= intervalLed2) {

    previousMillisLed2 = currentMillisLed2;



    if (ledState2 == LOW) {

      ledState2 = HIGH;

      
    } else {

      ledState2 = LOW;
      
      
  sensors.requestTemperatures();
  lcd.setCursor(1, 3);
  lcd.print(sensors.getTempCByIndex(0));
  lcd.setCursor(8, 3);
  lcd.print(sensors.getTempCByIndex(1));
  lcd.setCursor(15, 3);
  lcd.print(abs((sensors.getTempCByIndex(1))-(sensors.getTempCByIndex(0))));
  
  
  
  if ((abs((sensors.getTempCByIndex(1)) - (sensors.getTempCByIndex(0)))) >= 1)  {

    digitalWrite(13, HIGH);
    
  } else {

    digitalWrite(13, LOW);
  

  }
   }
   digitalWrite(LED2, ledState2);
}

}

        milisegundos = millis();
        if(milisegundos > (tiempo1+1000)){   //Si ha pasado 1 segundo ejecuta el IF
        tiempo1 = millis();                  //Actualiza el tiempo actual
        segundos++;
        tiempoSegundos = tiempo1/1000;       //Tiempo transcurrido desde que esta encendido el Arduino
        }
        
        if (segundos==1){
          lcd.setCursor(0,0);
          lcd.print("  Tiempo Restante");
          segundos=0;
          if(asegundos>0){
              asegundos--;
              lcd.setCursor(10,1);
              if(asegundos<10){             //Esto es para poner un 0 delante si los segundos son menor de 10
                lcd.print("0");
            }
            lcd.print(asegundos);
          } 
          if(asegundos==0){
              if(aminutos>0){
                  aminutos--;
                  asegundos=60;
                  lcd.setCursor(7,1);
                if(aminutos<10){         //Esto es para poner un 0 delante si los minutos son menor de 10
                lcd.print("0");
              }
              lcd.print(aminutos);
            } 
          }
          
              
          }   
          
          
         {
              if(aminutos==0){
                  if(asegundos==0){                                           
                     digitalWrite(relevo, LOW);
                     digitalWrite(LED1, LOW);
                     fin=1;          
                  }
              }
          }
          
      }while(fin==0);
          fin=0;
          lcd.clear();
          lcd.setCursor(0,0);
          lcd.print(" PROCESO CULMINADO");
          delay(6000);
          
          aminutos = temp_minutos;       // recupero tiempo programado de la variable temporal minutos
          asegundos = temp_segundos;     // recupero tiempo programado de la variable temporal segundos
    }
    }   

Las bobinas de circuitos de continua deben tener un diodo de free wheeling o sea un diodo en antiparalelo tal que bloquee la generación de FEM durante el transitorio de desconexión.
image
Aca una ejemplo muy ilustrativo.
Y no me refiero a las bobinas de los reles activados por el Arduino sino a las bobinas que tu mencionas.

1 Like

Saludos Surbyte, valoro mucho tu acompañamiento. He leído muchas orientaciones tuyas en múltiples foros que me han ayudado enormemente.
En este caso los relé que estoy utilizando ya tienen el diodo antiparalelo en la placa.
Envío una fotografía.


He cambiado los relé para descartar que estén defectuosos y el problema persiste.

Ok. Voy a hacer la prueba. Disculpa que no me percaté que te referías a la bobina del contactor.

La bobina del contactor trabaja con corriente alterna. Cómo hacer en ese caso?

Para proteger la bobina del contactor existen dos opciones:

  • Varistor.
  • Filtro snubber.

Dependiendo de la carga de esos contactores y del presupuesto, quizás puedas usar relés/contactores de estado solido con cruce por cero que te evitarán muchos problemas.

En este tema "offtopic o casi hablemos de los snubber" hablamos sobre ello.

1 Like

Excelente. Mil gracias Victorjam. Voy a chequear el tema que me sugieres y ver si es posible hacerlo en este caso.
Lo que no entiendo es que si están separados los circuitos (porque el relé que alimenta a la bobina del contactor es optoacoplado) me genera ese problema en el arduino.

Gracias nuevamente.

Créeme, a mi me pasó lo mismo al principio.

Resumiendo y para que se entienda: cuando le quitas la corriente a una bobina esta genera una corriente y un campo magnético que se opone a la perdida de la corriente. Suele ser una tensión alta y de alta frecuencia.

El varistor lo que hace es que al aumentar es que al aumentar la tensión baja su resistencia pasando la mayor parte de la corriente por él. Si lo pones en paralelo a la bobina, cuando esta genere tensión excesiva el varistor se encarga de cerrar el circuito y re-aliementar la bobina, reduciendo así ese efecto.

Cuando energizas se produce un efecto contrario donde la bobina absorve demasiada corriente al principio alterando a la alimentación.

Aunque el circuito esté separado tanto la corriente como el campo, afectan a todo lo que haya alrededor, sobre todo a la alimentación. Si la fuente no es capaz de absorver ese "ruido" llegará a meterlo dentro del microcontrolador y hacer que se reinicie o bloquee.

Dependiendo de la situación quizás un solo varistor no sea suficiente y haya que proteger a la fuentes de alimentación e incluso las entradas del microcontrolador.

En mis circuitos suelo usar muchos condensadores en la fuente, diodos supresores de transitorios (TVS), filtros RC, etc..

1 Like

Saludos.

Efectivamente el varistor solucionó el problema. Se acabaron las fallas. Agradecido una vez más por la ayuda que brindan en los foros. Tanto la sugerencia de Surbyte como la de Victorjam son válidas.

@edujo3 Me parece un excelente aporte este tema en la comunidad, he pasado por problema similar cuando diseñé un circuito para controlar un motor. Una duda ¿al final como fue la conexión de los varistores en tu circuito? no se si podrias postear alguna imagen alusiva también Saludos!

El varistor va entre bornes del elemento a proteger.
No necesitas un esquema para eso.

Proteger la bobina, por lo tanto se infiere que el varistor o el snubber (Resistencia en serie con capacitor) van conectados a la bobina.

Si quieres mas, busca Bobina varistor o bobina snubber
Ejemplos de lo que dije y luego tocas imágenes y salen cosas asi:

image
El primero es un varistor, el segudo (al medio) un RC o snubber y el tercero simboliza la bobina
image

Varistor
image

Snubber bobina

pero mejor mira todo el cálculo

1 Like

Gracias! todo eso sirve también para otros que busquen información similar =D

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