PID con BME280

Hola a todos!
Les cuento que estoy trabajando desde hace un tiempo en el desarrollo de un sistema de control, para controlar la temperatura (en un ppio, luego la humedad) dentro de una caja.
A esto lo haria con un blower fan por medio de un sistema de control del tipo PID ( PID_V1 de Brett Beauregard) en la que aspirando aire del exterior, si la temperatura interna de la caja sobrepasa los 35°C, lograría mantener la temperatura deseada ( unos 35°C).
Este seria un esquema basico del sistema:


Un esquema mas detallado de los componentes involucrados:


Los componentes son los siguientes:

  • Arduino Uno R3 (1)
  • Conversor de nivel logico 4 canales bidireccionales 5-3.3 V (1)
  • Sensor de temp. BME280 (i2C) (2)
  • Mosfet IRF540 canal N
  • Blower fan, Servo DC12V 1.25A (1)

Ahora paso a contar el inconveniente que estoy teniendo...
No logro hacer que el fan encienda al superarse el umbral. El compilador no presenta ningun error.
Adjunto codigo:

//*****************Librerias puerto serie******************

#include <SPI.h>                           //Serial Peripheral Interface

//*****************Librerias BME280***********************

#include "cactus_io_BME280_I2C.h"

//*****************Librerias PID***********************

#include "PID_v1.h"

//**************Definiciones BME280**********************

BME280_I2C bme_Int3(0x76);                        // i2C direccion: La direccion 0x77 es para el BME modificado, y la direccion 0x76 es para el BME original
BME280_I2C bme_Ext(0x77);

float temperatura_Int;                          // Almacena la temperatura (C)

float temperatura_Ext;                          // Almacena la temperatura (C)

//*********Definiciones para el PID********

#define PIN_OUTPUT 3                             //Se define el PIN de salida

double Setpoint_T, Input_T, Output_T;           //Se definen las variables para la Temperatura


double Kp_T=2, Ki_T=5, Kd_T=1;                   //Se definen los parametros iniciales proporcionales, integrales y derivativos, para controlar la temperatura.


PID myPID_T(&Input_T, &Output_T, &Setpoint_T, Kp_T, Ki_T, Kd_T, DIRECT);


void setup(){
  
//********Seteo de frecuencia en el PIN 3********

  TCCR2B = TCCR2B & B11111000 | B00000001;          //Cambio en la frecuencia de salida del puerto 3, actual: 31372.55 Hz

//**********Inicio del puerto Serie*************
    
  Serial.begin(9600);                           
  delay(100);                                       //agregado para la transmision de datos

//**********Inicio de sensores BME280**********
  
  bme_Int3.begin();
    if (!bme_Int3.begin()) {  
      Serial.println("BME280 Box3 no encontrado");          
    }
    
  bme_Ext.begin();
    if (!bme_Ext.begin()) {  
      Serial.println("BME280 Exterior no encontrado");          
    }
    
//**********Inicio de variables - PID**********

  Input_T = temperatura_Int;
  Setpoint_T = 30;                                          //Set point de Temperatura, 35°C

  myPID_T.SetMode(AUTOMATIC);                              //Inicio del PID de temperatura

}
  
void loop(){

  //**************Lectura de sensores BME*************
  
  bme_Int3.readSensor();
    temperatura_Int = bme_Int3.getTemperature_C();
   

  bme_Ext.readSensor();
    temperatura_Ext = bme_Ext.getTemperature_C();
    
    
//******************Codigo a ejecutar por el PID*****************************

  Input_T = temperatura_Int;
  

  if (temperatura_Ext >= 20){			//condicion 
    myPID_T.Compute();                          //PID de Temperatura
    analogWrite(PIN_OUTPUT, Output_T);          //No es necesario mapear la salida a 0-255. esto ya está definido en la libreria!!!
  }
}

Si alguien puede aportar algo, les estaré muy agradecido!

Hola!
Bueno, agrego algunas cosas más que estuve haciendo en este codigo con la intención de encontrar el problema.
Paso a enumerar los cambios y luego adjunto el codigo:
Cambios más relevantes:

1- Definí los rangos de trabajo del PWM:

double commandMin = 100;
double commandMax = 250;

Como se observa en la primer definicion, con 100 logro encender el pwm. Si bien es algo alto, es el kick necesario para encenderlo.... Quizas agregando algo más al codigo, pueda encenderlo con 100 por unos 250ms para luego atender la necesidad del PID....

2- Los fatores Kp_T, Kd_ T y Ki_T se pasan a negativo debido a las caracteristicas del sistema (el aire que entra es más frio que en el interior del box). Esto según pude observarlo en un referencia (estoy buscandola en éste momento pero no tengo suerte...).

Otros cambios:

1- Agrege el uso de millis para mostrar las temperaturas (interna y externa) por el serie.

2- Se agrega un if. Esto se debe a que no puedo permitir hacer circular aire del exterior hacia el interior de mi box, si esta debajo de los 20°C.

Con dichos cambios logré que el fan encienda! :slight_smile: , pero no se observa cambios en la velocidad :confused: (da la impresion que el fan está en 100)
Quizas esto se deba a "double commandMin = 100;" también se observa que al encender el sistema de control, la temperatura interna comienza a descender debido al ingreso de aire del exterior. Esto lo hace descendiendo la temperatura interior aún más que los 35°C de temperatura objetivo... Situacion por demás extraña ya que sería esperable que el fan al menos se apage!

//*****************Librerias puerto serie******************

#include <SPI.h>                           //Serial Peripheral Interface


//*****************Librerias BME280***********************

#include "cactus_io_BME280_I2C.h"

//*****************Librerias PID***********************

#include "PID_v1.h"

//**************Definiciones BME280**********************

BME280_I2C bme_Int3(0x76);                        // i2C direccion: La direccion 0x77 es para el BME modificado, y la direccion 0x76 es para el BME original

BME280_I2C bme_Ext(0x77);

float temperatura_Int;                          // Almacena la temperatura (C)

float temperatura_Ext;                          // Almacena la temperatura (C)


//*********Definiciones para el PID********

#define PIN_OUTPUT 3                             //Se define el PIN de salida

double Setpoint_T, Input_T, Output_T;           //Se definen las variables para la Temperatura

double Kp_T=(-1), Ki_T=(-0.05), Kd_T=(-0.25);                   //Se definen los parametros iniciales proporcionales, integrales y derivativos, para controlar la temperatura.


double commandMin = 100;                              //Aqui se definen los parametros Min y Max para operar sobre el fan
double commandMax = 250;

PID myPID_T(&Input_T, &Output_T, &Setpoint_T, Kp_T, Ki_T, Kd_T, DIRECT);


//*********Definiciones para millis********

long intervaloSPrint = 3000;                       //Intervalo definido para mostrar datos por el puerto serie
long previousMillis_SPrint = 0;                   //almacena la ultima vez que el loop fue actualizado


void setup(){
  
//********Seteo de frecuencia en el PIN 3********

  TCCR2B = TCCR2B & B11111000 | B00000001;          //Cambio en la frecuencia de salida del puerto 3, actual: 31372.55 Hz

//**********Inicio del puerto Serie*************
    
  Serial.begin(9600);                           

  delay(100);                                       //agregado para la transmision de datos

//**********Inicio de sensores BME280**********
  
  bme_Int3.begin();
    if (!bme_Int3.begin()) {  
      Serial.println("BME280 Box3 no encontrado");          

    }
    
  bme_Ext.begin();
    if (!bme_Ext.begin()) {  
      Serial.println("BME280 Exterior no encontrado");          

    }
    
//**********Inicio de variables**********

  Input_T = temperatura_Int;
  Setpoint_T = 35;                                          //Set point de Temperatura, 35°C
  
  myPID_T.SetMode(AUTOMATIC);                              //Inicio del PID de temperatura

  myPID_T.SetOutputLimits(commandMin, commandMax);

}
  
void loop(){

  //**************Lectura de sensores BME*************
  
  bme_Int3.readSensor();
    temperatura_Int = bme_Int3.getTemperature_C();


  bme_Ext.readSensor();
    temperatura_Ext = bme_Ext.getTemperature_C();

    
   
//******************Codigo a ejecutar por el PID*****************************


  Input_T = temperatura_Int;


  if (temperatura_Ext >= 20){
    myPID_T.Compute();                          //PID de Temperatura
    analogWrite(PIN_OUTPUT, Output_T);          
  }
  else analogWrite(PIN_OUTPUT, 0);

  
       
  if(millis() - previousMillis_SPrint >= intervaloSPrint){
    previousMillis_SPrint = millis();
    
    Serial.print(" TInt_Box3(BME): ");
    Serial.print(temperatura_Int);
    Serial.print(" C");


    Serial.print(" Text(BME): ");
    Serial.print(temperatura_Ext);
    Serial.println(" C");

    }
}

Lo proximo que voy a hacer es definir el rango optimo de trabajo de mi fan... y seguir investigando más sobre este tema.
Cualquier ayuda es bienvenida!
Saludos!!