Sintonizar PID con Arduino – Control de temperatura

Sintonizar PID con Arduino – Control de temperatura

Introducción

Existen un montón de artículos sobre la implementación de controladores PID con Arduino, pero en la mayoría de ellos me encuentro que la sintonización se hace con el método de prueba y error. En este aspecto el algoritmo PID ha demostrado ser muy robusto, lo suficiente como para salir airoso incluso ante una «mala» sintonización. Esto no quiere decir que el método de prueba y error no sea válido, de hecho, cuando montamos algo serio por primera vez y no tenemos referencias de funcionamiento es normal recurrir a métodos pragmáticos, pero mi intención es que tengáis una alternativa de sintonización analítica.

No voy a aburriros con conceptos matemáticos ni espero perderme en la selva con las explicaciones, la intención de este artículo es que con un breve análisis y con unas sencillas herramientas desarrolladas para la ocasión seamos capaces de evitar el uso del famoso método de «prueba y error» y aplicarlo a la mayoría de nuestras implementaciones.

Sistema empleado

El sistema empleado es muy sencillo, en esencia consta de de una fuente de calor, un sensor de temperatura y un ventilador.

Alzado y planta del sistema

La fuente de calor es una resistencia de 12V como las que podemos encontrar para calentar el filamento de las impresoras 3D. Ojo porque a 12V se calienta hasta 350ºC por lo que para nuestro sistema la alimentaremos a 4,5V obteniendo unos 120ºC. En el interior y pegando a la fuente de calor he situado un sensor de temperatura DS18B20 y en la parte superior hay un ventilador de 12V capaz de girar a 7500 rpms para bajar la temperatura del sistema. El objetivo es mediante un controlador PID mantener estable la temperatura del interior aprovechando una salida PWM de Arduino.

Tanto el calentador como el ventilador son dos bestias pardas y necesitan de fuentes de alimentación externas. Como hemos comentado la resistencia la alimentaremos a 4,5V obteniendo 120ºC. El ventilador de 12V es de 4 pines por lo que aprovecharemos uno de sus pines para controlar mediante una salida PWM de Arduino la velocidad de giro. Una característica común en este tipo de ventiladores es que cuando la señal PWM que reciben es 0, estos giran a unas revoluciones mínimas, es decir, nunca paran. En nuestro caso con PWM 0 el ventilador gira a 1200 rpms enfriando nuestro sistema de 120ºC a 80ºC.

Montaje del sistema

Componentes

El coste aproximado si tienes que comprar todos los componentes es de entre 40-50€ sin contar con las fuentes externas.

Esquema de conexiones

Conexiones del sistema

Para el montaje la única consideración es que cuando trabajamos con varios voltajes las masas deben ir unidas.

Código de Arduino

//***************************************************************
// Desarrollado por Garikoitz Martínez [garikoitz.info] [05/2020]
// https://garikoitz.info/blog/?p=638
// https://garikoitz.info/blog/?p=674
//***************************************************************
//===============================================================
// Librerías
//===============================================================
#include <Arduino.h>
#include <OneWire.h>
#include <DallasTemperature.h>   
#include <Wire.h>
#include <LCD.h>            
#include <LiquidCrystal_I2C.h>
#include <math.h>
#include <PID_v1.h>
//===============================================================
// Variables globales & Constantes
//===============================================================
OneWire onewire(8);
DallasTemperature sensors(&onewire);
double Setpoint, Input, Output;
double Kp=55, Ki=29, Kd=0;
PID myPID(&Input, &Output, &Setpoint, Kp, Ki, Kd, REVERSE);
boolean modo = false; //false=auto true=manual
String modos = "";
float OP;
const int pot =0; // Potenciómetro conectado al pin A0
const int vent =5; // ventilador conectado al pin 5
int velocidad;
LiquidCrystal_I2C lcd(0x3F,2, 1, 0, 4, 5, 6, 7);
//===============================================================
// SETUP
//===============================================================
void setup(void) {
    Serial.begin(9600);
    pinMode(vent, OUTPUT);
    sensors.begin();
    sensors.setResolution(0, 11);
    lcd.begin(20,4);
    lcd.setBacklightPin(3,POSITIVE);
    lcd.home(); 
}
//===============================================================
// BUCLE PRINCIPAL
//===============================================================
void loop() {
      // Interruptor Auto/Manual
      if (digitalRead(12) == HIGH){
        modo=true;
        modos="MANUAL";
        myPID.SetMode(MANUAL);
      }else{
          modo=false;
          modos="AUTOMATICO";
          myPID.SetMode(AUTOMATIC);
       }
       sensors.requestTemperatures();
       Input = sensors.getTempCByIndex(0);
     // MODO MANUAL Potenciómetro ---> PWM Ventilador
     if (modo==true){
         velocidad = analogRead (pot);
         OP = map(velocidad, 0, 1023, 0, 255);
         analogWrite(vent, OP);
         myPID.SetMode(MANUAL);
         //LCD en MANUAL
         lcd.clear();
         lcd.setCursor(0,0);
         lcd.print("====== ");
         lcd.print(modos);
         lcd.print(" ======");
         lcd.setCursor(0,1);
         lcd.print("  T: ");             
         lcd.print(Input,2);
         lcd.print("\337C ");
         lcd.setCursor(0,2);
         lcd.print(" OP: "); 
         lcd.print(OP*0.3921);
         lcd.print(" % ");
         lcd.setCursor(0,3);
         lcd.print("PWM: ");
         lcd.print(OP,0);
        // DEBUG PUERTO SERIE (Para Arduino COM Plotter)
        Serial.print("#");            //Char inicio
        Serial.print(0);              //Dejo vacío para ACP
        Serial.write(" ");            //Char separador
        Serial.print(Input,2);        //PV
        Serial.write(" ");            //Char separador
        Serial.print(OP*0.3921,0);    //OP
        Serial.println();
     }
     // MODO AUTOMÁTICO---------------------------------------------
     if (modo==false){
        float set=analogRead(pot);
        Setpoint=map(set,0,1023,60.0,40.0); 
        Input = sensors.getTempCByIndex(0);
        myPID.SetMode(AUTOMATIC);
        //-----------------------------
        //LCD en AUTO
        lcd.clear();
        lcd.setCursor(0,0);
        lcd.print("==== ");
        lcd.print(modos);
        lcd.print(" ====");
        //
        lcd.setCursor(0,1);
        lcd.print("PV: ");
        lcd.print(Input,2);
        lcd.print(" \337C ");
        lcd.setCursor(0,2);
        lcd.print("SP: ");
        lcd.print(Setpoint,2);
        lcd.print(" \337C ");
        lcd.setCursor(0,3);
        lcd.print("OP: ");
        lcd.print(Output*0.3921,2);
        lcd.print(" %");
        //
        myPID.Compute();
        analogWrite(vent, Output);
       //===============================================================
       // DEBUG PUERTO SERIE (Para Arduino COM Plotter)
       //===============================================================
        Serial.print("#");              //Char inicio
        Serial.print(Setpoint,0);       //SP
        Serial.write(" ");              //Char separador
        Serial.print(Input,2);          //PV
        Serial.write(" ");              //Char separador
        Serial.print(Output*0.3921,0);  //OP
        Serial.println();
    }
    delay(1000);
}//Fin void loop

Identificación del sistema

Recopilación de datos en lazo abierto

Con el controlador de temperatura en manual hacemos una serie de movimientos en la salida PWM del ventilador para ver como reacciona la temperatura.

StepTest

Se observa que la zona donde mejor trabaja el ventilador es en los tres primeros escalones, es decir, entre 55 y 45ºC. Por debajo de 45ºC y a medida que nos acercamos al límite inferior el tiempo de establecimiento es cada vez más corto y las constantes del sistema que hemos obtenido ya no son totalmente representativas y por lo tanto nuestro control se degradará.

Ejemplo de cálculo de K, To y Tp
Escalón analizado
Cálculo de las constantes con ACP

Con la ayuda de ACP obtenemos las siguientes constantes del sistema.

K0,120%/%
To8,5segundos
Tp103,5segundos
Constantes del sistema

Facilidad de control

El cociente entre To y Tp nos sugiere la facilidad de control de un sistema. En este caso estamos en la zona de muy fácil ya que 8,5/103,5=0,08.

Ajuste y simulación en lazo cerrado

A continuación un resumen de las posibles sintonías ofrecidas por ACP para nuestro sistema.

Se aprecia que los métodos clásicos como el de Cohen Coon o Ziegler Nichols proponen sintonías más agresivas (>Kp y <Ti) y más centradas en la ganancia proporcional que los métodos más modernos como el Improved SIM C de Skogestad.

Algunos métodos tienen condiciones de aplicación normalmente relacionados con To y Tp. Si se da alguna condición, ACP nos avisará con una ventana emergente. Esto no significa que no lo podamos usar, sencillamente que el método tiene restricciones de aplicación.

Resultados

NOTA: en cuanto pueda los subo corregidos. Disculpad las molestias.

A continuación compararemos la respuesta real del sistema con la simulación en lazo cerrado. Si hemos identificado medianamente bien nuestro sistema, la respuesta real debe coincidir con la simulación en todos los casos.

CC-10 (PI)

CC-10 (PID)

ZN-LA-10 (PI)

Lambda (PI)

IMC (PI)

SIM C (PI)

Improved SIM C (PI)

Conclusiones

Desde el punto de vista de control se puede decir que todos los métodos probados han tenido una respuesta aceptable y por lo tanto con una dedicación mínima podemos realizar una sintonía robusta de nuestros sistemas para evitar el prueba y error.

Puede que le llame la atención al lector el «poco caso» que se le ha dado al termino derivativo, y es que en el 90% de los casos con un controlador PI es más que suficiente y por lo tanto os recomiendo que antes de usar un PID os hagáis la siguiente pregunta, ¿me aporta alguna mejora incluir el termino derivativo?. En nuestro caso, al incluir el término derivativo la única diferencia ha sido que la salida se ha vuelto más oscilante sin una mejora notable en la respuesta de control. Como norma general no se recomienda el uso del termino derivativo si T0 es pequeño en comparación con Tp (como es nuestro caso) y suele ser útil si T0 está en torno a Tp/2 y siempre y cuando la PV no tenga ruido.

Ha quedado patente que es factible caracterizar la dinámica de un sistema relativamente sencillo por pocos datos que tengamos. Aún así, lo más importante que me gustaría remarcar es la importancia que tiene conocer bien el sistema que queremos controlar.

Finalmente espero haber arrojado algo de luz sobre la sintonía PID y que os animéis a utilizar ACP para evitar el método prueba y error siempre que sea posible.

Referencias

Enlaces

Libros y Publicaciones

[1] Aidan O’Dwyer. Handbook of PI and PID controller tuning rules, 3rd edition, Imperial College Press. ISBN: 978-1-84816-242-6

[2] Karl J. Astrom, Tore Hagglund. Control PID avanzado, Pearson, ISBN: 978-84-8322-511-0

[3] Daniel Chuck. Los sistemas de primer orden y los controladores PID, edición 2012. [Link] [Link2]

[4] J.G. Ziegler, N.B. Nichols. Optimum Settings For Automatic Controllers, 1942 edition, American Society of Mechanical Engineers. [Link]

[5] G.H. Cohen, G.A. Coon. Theoretical Consideration of Retarded Control, 1953 edition, American Society of Mechanical Engineers. [Link] [Link2]

[6] Daniel E. Rivera. Internal Model Control: A Comprehensive View, 1999 edition, College of Engineering and Applied Sciences. [Link]

[7] R. Vilanova, A. Visioli. PID Control in the Third Millennium. Chapter 5, The SIMC Method for smooth PID Controller Tuning, Springer. ISBN: 978-1-4471-2424-5.

[8] Chriss Grimholt, Sigurd Skogestad. The improved SIMC method for PI controller tuning, IFAC-conference PID’12, Brescia, Italy, March 2012. [Link]

[9] Guillermo J. Silva, Aniruddha Datta, S.P. Bhattacharyya. PID Controllers for Time-Delay Systems. Chapter 10, Analysis of Some PID Tunning Techniques. Birkhäuser. ISBN: 0-8176-4266-8

4 comentarios en «Sintonizar PID con Arduino – Control de temperatura»

    1. Esta sería la lista completa:
      Arduino UNO R3 + cable USB
      Sensor de temperatura DS18B20
      Ventilador de 12V y 7500 rpms (4 pines)
      Controlador de Motor L298N
      Resistencia/Calentador 12V 50W
      Un potenciómetro de 10K
      Un micro interruptor
      Una resistencia de 220 ohm
      Una fuente externa de 12V
      Una fuente externa regulable (para alimentar el cartucho calefactor a 4,5V)
      Cables dupont para el conexionado
      Una protoboard
      Display LCD 20×4
      Adaptador I2C para Display LCD

      *Para replicar la práctica no hace falta que uses exactamente los mismos componentes. Si dispones de otro ventilador, cartucho calefactor, sensor de temperatura, etc. Incorpóralos a tu proyecto y adecua el código. Si tienes cualquier duda no dudes en consultar.

      1. Buenos dias, la programacion en arduino no me funciona, podria explicarme por que el error?
        LiquidCrystal_I2C lcd(0x3F,2, 1, 0, 4, 5, 6, 7);
        en esta parte no me funciona

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Información básica sobre protección de datos
Responsable Garikoitz Martínez Moreno +info...
Finalidad Gestionar y moderar tus comentarios. +info...
Legitimación Consentimiento del interesado. +info...
Destinatarios Automattic Inc., EEUU para filtrar el spam. +info...
Derechos Acceder, rectificar y cancelar los datos, así como otros derechos. +info...
Información adicional Puedes consultar la información adicional y detallada sobre protección de datos en nuestra página de política de privacidad.