El relé no me funciona si no hay un Serial.print() en el codigo

Hola, estoy haciendo la parte proporcional de un control PID de presión con un Arduino y un relé, hice este código, que creo que tiene lógica, todos los Serial.print() que tiene son únicamente para ver su comportamiento, el plan es borrarlos después. El problema es que cuando comento esos Serial.print() el código deja de funcionar, pero si están sin comentar, el código si funciona, la verdad no logro entender porque ocurre esto. Básicamente, lo que ocurre es que el relé se queda eternamente en HIGH y no cambia pasado el intervalo de tiempo, pero si agrego un Serial.print() empieza a funcionar bien.

int relayPin = 13;  
int sensorPin_A = A0;
float Setpoint_A = 2.5;
float Presion_A = 1;
float diferencia_presion = 0;
float Porcentaje = 1;
unsigned long previousMillis = 0;
int intervalo = 10000;
float intervalo_auxiliar = 0;
unsigned long currentMillis = 0;
int Sensor_A;
float Voltaje_A;


void setup()
{
  pinMode(relayPin, OUTPUT);
  pinMode(sensorPin_A, INPUT);
  Serial.begin(9600);
}

void loop()
{ 
  Sensor_A = analogRead(sensorPin_A); // Medimos el sensor A
  Voltaje_A = Sensor_A*(5.00 / 1023.00); // Convertimos la medida del sensor a voltaje
  Presion_A = 0.46*(Voltaje_A-0.5); // Convertiimos este voltaje a presion

  diferencia_presion = Setpoint_A - Presion_A; // Calculamos la diferencia entre el setpoint y la presion medida
  Porcentaje = abs(diferencia_presion / Setpoint_A); // Calculamosun porcentaje con base en el Setpoint
  currentMillis = millis(); // Contamos cuantos milisegundos han pasado
  intervalo_auxiliar = Porcentaje*intervalo; // Calculamos cuanto tiempo debemos activar o desactivar el relé

  //Serial.print("int = ");
  //Serial.println(intervalo_auxiliar);
  
  //Serial.print("Presion_A = ");
  //Serial.println(Presion_A);
  //Serial.print("diferencia_presion = ");
  //Serial.println(diferencia_presion);
  //Serial.print("Porcentaje =  ");
  //Serial.println(Porcentaje);

  if(diferencia_presion >= 0) // Vemos si debemos activar o desactivar el relé
  {

    //Serial.println("diferencia_presion > 0");

    digitalWrite(relayPin, HIGH);

    //Serial.println("HIGH_1");

    //Serial.println(intervalo_auxiliar);  

    //Serial.println(currentMillis);
    //Serial.println(previousMillis);


    if(currentMillis - previousMillis >= intervalo_auxiliar) // Lo mantenemos prendido hasta llegar al tiempo del intervalo auxiliar
    {
      previousMillis = currentMillis;

      digitalWrite(relayPin, LOW);

      Serial.println("LOW_1");
      
    }
  }
  
  else
  {
    digitalWrite(relayPin, LOW);

    //Serial.println("LOW_2");

    if (currentMillis - previousMillis >= intervalo_auxiliar) // Lo mantenemos apagado hasta llegar al tiempo auxiliar
    {
      previousMillis = currentMillis;
      digitalWrite(relayPin, HIGH);

      //Serial.println("HIGH_2");

    }
  }
}

Llevo mucho rato revisando el código y no logro encontrar la razón del fallo.
Aprovecho de preguntar, tengo un modulo relé de 2 canales, sin embargo el led del modulo se enciende cuando el relé está en LOW y se apaga cuando está en HIGH, estoy casi seguro de que debería ser al revés, alguien sabe porque puede pasar esto?

Gracias de antemano :grin:

De manera rápida y observando el código veo que...

intervalo_auxiliar debería ser de tipo unsigned long. Hay que tener cuidado con los tipos ya que el resultado no puede ser el deseado.

El cálculo de la presión nunca va a llegar al valor de Setpoint_A

Presion_A = 0.46*(Voltaje_A-0.5);

Si el voltaje fuese de 5V el valor de presión_A será de 2.07, por lo tanto diferencia_presion será siempre mayor que cero.

En el momento de entrar en el "if" siempre lo hace en el primero: enciende el relé siempre.

Serial.print es una operación relativamente lenta, lo que hace que haya retrasos entre las ejecuciones del código, sobretodo en tiempos pequeños. Si el intervalo es mas pequeño que el tiempo que tarda en ejecutarse los serial.print te dará sensación de retraso, como si hubiera un delay.

La mayoría de los modulos relé funcionan con lógica inversa: HIGH lo apaga y LOW lo enciende. Tan solo tienes que probar tu módulo y ver que hacen los contactos cuando enciendes o apagas.

A ver si esto se acerca un poco mas a lo que deseas

int relayPin    = 13;  
int sensorPin_A = A0;
float Setpoint_A = 2.5;
float Presion_A = 1;
float diferencia_presion = 0;
float diferencia_presionAnt;
float Porcentaje = 1;
unsigned long previousMillis = 0;
int intervalo = 10000;
unsigned long intervalo_auxiliar = 0;
unsigned long currentMillis = 0;
int Sensor_A;
float Voltaje_A;
bool activar = false;

void setup() {
  pinMode(relayPin, OUTPUT);
  pinMode(sensorPin_A, INPUT);
  Serial.begin(9600);
}

void loop() { 
  Sensor_A = analogRead(sensorPin_A); // Medimos el sensor A
  Voltaje_A = Sensor_A*(5.00 / 1023.00); // Convertimos la medida del sensor a voltaje
  Sensor_A = constrain(Voltaje_A, 0.5, 5.0);  // habitualmente los sensores entregan valores entre 0.5 y 4.5V
  Presion_A = 0.46*(Voltaje_A-0.5); // Convertimos este voltaje a presion

  diferencia_presion = Setpoint_A - Presion_A; // Calculamos la diferencia entre el setpoint y la presion medida
  Porcentaje = abs(diferencia_presion / Setpoint_A); // Calculamos un porcentaje con base en el Setpoint
  currentMillis = millis(); // Contamos cuantos milisegundos han pasado
  intervalo_auxiliar = (unsigned long) (Porcentaje*intervalo); // Calculamos cuanto tiempo debemos activar o desactivar el relé

  if (abs(diferencia_presion - diferencia_presionAnt) > 0.2 ) {
      if(diferencia_presion >= 0) { // Vemos si debemos activar o desactivar el relé
          Serial.println("Presion_A  = " + String(Presion_A));
          Serial.println("dif_pres   = " + String(diferencia_presion));
          Serial.println("Porcentaje = " + String(Porcentaje));
          Serial.println("Int Aux    = " + String(intervalo_auxiliar));
          if (!activar) { // no esta activo
              digitalWrite(relayPin, LOW);
              Serial.println("HIGH_1");
              activar = true;
              previousMillis = currentMillis;
          }
     }
      diferencia_presionAnt = diferencia_presion;
  }
  if (activar) {
      if(currentMillis - previousMillis >= intervalo_auxiliar) { // Lo mantenemos prendido hasta llegar al tiempo del intervalo auxiliar               
        digitalWrite(relayPin, HIGH);  // desactivo rele
        Serial.println("LOW_1");
        activar = false;
      }
  }
}

Finalmente logré resolverlo haciendo algo similar a lo que @Surbyte propuso, y también logré entender porque medio funcionaba cuando ponía Serial.print(), muchas gracias :grinning:

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