• No se han encontrado resultados

Maqueta de control PID con Arduino

N/A
N/A
Protected

Academic year: 2021

Share "Maqueta de control PID con Arduino"

Copied!
16
0
0

Texto completo

(1)

Maqueta de control PID con Arduino

.

.

Con el motivo de la primera VirtualCamp (Julio 2011), el proyecto ha sido crear una maqueta de

control didáctica con un presupuesto de menos de 10 euros (Arduino no incluido). La idea fue hacer un

proyecto en 48h durante el fin de semana del 16-17 de Julio.

El proceso elegido es el control de temperatura. Para ello dos resistencias de potencia generan el calor y

un ventilador actua como control para la refrigeración. Un sensor resistivo de tipo NTC se encarga de

registrar la temperatura del habitáculo.

Se ha instalado el sensor de temperatura en medio de las resistencias de potencia para que el proceso

disponga de la menor inercia posible, y así se comporte más rápido ante cambios de la entrada.

Colaboradores del proyecto:

Igor R.

Alberto Yebra -> Interfaz gráfica en python para la visualización del proceso. [se ampliará este

proyecto con su trabajo].

(2)

Componentes necesarios:

Ventilador 12v usado para refrigeración de componentes en ordenadores.

Resistencias de potencia (47ohm) --> 2 unidades

Un sensor temperatura resistivo (NTC) + resistencia 3k pull up

Transistor Mosfet.

Diodo 1N4148.

Un recipiente.

Transformador externo para alimentación a 12v.

Los objetivos del proyecto usando Arduino han sido:

1. Creación física de la maqueta.

2. Control de un proceso usando un PID.

3. Captura de señal analógica.

4. Convertir la señal eléctrica a física mediante una tabla guardada en memoria de programa

(flash) para evitar uso de RAM del microcontrolador.

5. Control carga de potencia mediante PWM.

6. Monitorización en el PC de resultados.

(3)

Veámos una foto de como ha quedado la maqueta:

(4)

La instalación eléctrica necesaria es bastante sencilla. La podemos dividir en dos partes: control del

ventilador mediante transistor mosfet y adquisición de la temperatura mediante NTC.

A continuación, se puede observar un esquema de la conexión del ventilador. La salida utilizada en

Arduino es el pin 9 (PWM).

La salida de control PID es el tiempo encendido del ventilador. Es decir, el duty cycle de nuestro PWM.

Se ha modificado el registro del timer 1, que controla la frecuencia del pin 9, para que la frecuencia sea

aproximadamente 32 kHz.

Veámos una captura real de la misma:

Un ventilador es una carga inductiva, por lo que es necesario añadir un diodo cómo indica la figura

anterior.

(5)

Para evitar resolver operaciones matemáticas en el microcontrolador, se ha creado una tabla de valores

obtenidos del conversor ADC del Arduino versus temperatura en grados centígrados.

Dicha tabla, será guardada en memoria de programa, evitando consumir memoria RAM

innecesariamente de nuestro Arduino.

Se observa que la respuesta de un sensor NTC no es lineal.

La NTC se ha situado entre las dos resistencias calentadoras. De esta forma, se consigue que el sistema

tenga menos inercia y su respuesta sea rápida.

(6)
(7)

CONTROL PID

El control Proporcional Integral Derivativo (PID) es mecanismo de control mediante realimentación

negativa, el cual aplica una acción correctora al sistema para obtener el valor de consigna (Setpoint).

Existe multitud de recursos en internet acerca del mismo, por lo que aquí se verá desde el punto de

vista práctico. Por ejemplo, wikipedia dispone de una buena introducción.

El nuestro sistema:

Set Point -> Temperatura de consigna del sistema. El algoritmo oscila entre dos temperaturas,

con el motivo de ver como se comporta ante cambios de la entrada. Es decir, es a la temperatura

que queremos que se encuentre nuesto recipiente.

La realimentación o información de cómo se encuentra el sistema, es adquirida por la NTC.

El actuador es el ventilador, el cual regulamos su velocidad mediante modulación de ancho de

pulsos (PWM).

Para la visualización, se ha utilizado el software gratuito para Windows Stamp Plot Lite

(http://www.selmaware.com/stampplotlite/index.htm).

(8)

Empezaremos por realizar sólo un control PROPORCIONAL. El programa de Arduino, cambia cada

120 segundos el Set Point entre 60 y 59 grados centígrados.

(9)

Existe un límite en el valor de la constante proporcional, ya que nuestro sistema se vuelve oscilatorio,

ya que un pequeño cambio en el error, hace que la salida de controlador sea muy grande. A

(10)

Como se ha observado, la parte proporcional no tiene en cuenta el tiempo, por lo que para corregir el

error permanente, necesitamos añadirle la parte INTEGRAL.

Para poder observar cómo se comporta, se ha introducido un retraso a la actuación de la misma.

La parte integral consigue que nuestro sistema alcance los valores objetivo (Set Points de 60 y 58

grados).

La parte DERIVATIVA,sólo actua si hay un cambio en el valor absoluto del error. Es decir, si el error es

constante, no actuará.

El objetivo final de un sistema de control, es que el sistema siga lo más fielmente a su entrada ante

perturbaciones externas y que responda ante cambios de consigna (SetPoint). Veámos un video, en el

cual se altera el sistema (tapando la salida de aire-cables) y como al subir la temperatura, el sistema

aumenta la velocidad del ventilador para tratar de contrarrestar la perturbación.

(11)

Sketch:

//---// MAQUETA DE CONTROL PID

// VIRTUALCAMP JUL 2011 // IGOR R. //---#include <avr/pgmspace.h> //CONSTANTES #define cte_kp 500.0 //300 #define cte_ki 10.0 //5.0 #define cte_kd 3500.0 #define Margin_Int 0.9 #define target1 60.0 //60 #define target2 58.0 //58 //Variables de control de flujo long tInit; long tSerial; //Input float Target; //Sensor float temp; //Output float dutycycle; //PID float error; float prev_error; float Proportional; float Integral; float Derivative; float Kp; float Ki; float Kd; long LastTime; long SampleTime; long timeOutInt;

//Tabla guardada en memoria de programa del Arduino (FLASH) PROGMEM prog_uint16_t ntc[21][2] = { {861,0}, {778,10}, {678,20}, {570,30}, {463,40}, {366,50}, {285,60}, {219,70}, {168,80}, {128,90},

(12)

{99,100}, {77,110}, {60,120}, {47,130}, {38,140}, {30,150}, {24,160}, {20,170}, {16,180}, {14,190}, {11,200}, }; void setup() {

//Empiezo comunicacion serie a 19200(maxima velocidad de StampPlot) Serial.begin(19200);

delay(10);

//Configuro el StampPlot (maximo, minimo, grabar en un archivo los datos, etc). config_StampPlot();

//Configuro el pin 9 como salida (PWM) pinMode(9,OUTPUT);

//Capturo tiempos para el control de mi programa. tInit=millis();

LastTime=millis();

//Valor de mis constantes del control PI Kp=cte_kp;

Ki=cte_ki; Kd=cte_kd;

//Modificar frecuencia PWM

//Setting Divisor Frequency //0x01 1 31250 //0x02 8 3906.25 //0x03 64 488.28125 //0x04 256 122.0703125 //0x05 1024 30.517578125 //TCCR1B = TCCR1B & 0b11111000 | <setting>; //Configuro el PWM a 30 kHz. TCCR1B=TCCR1B & 0b11111000 | 0x01; } void loop() {

//Recojo 10 veces el dato del sensor y hago la media for (int i=0; i<10;i++)

{

temp+=calcTemp(analogRead(A5)); //Función que transforma mi lectura del ADC en grados usando una tabla guardad en memoria FLASH

}

(13)

// Cambio el SetPoint a target1 y target2 cada 120 segundos Target=target1;

long time=(millis()-tInit)/1000; if ((time>60) && (time<120) ) { Target=target2; }else if ( time>120 ) { tInit=millis(); } //CONTROL PID

//Hago los calculos de manera periodica SampleTime=(millis()-LastTime); if (SampleTime>=100) { LastTime=millis();

//Calculo de error (diferencia entre SetPoint y temperatura actual prev_error=(float)error;

error=(float)temp-(float)Target;

Proportional=(float)Kp*(float)error;

//El control integral solo entra cuando esta lo suficientemente cerca //Esto es para evitar saturar el control

if ( (abs(error)<=Margin_Int)) {

if (timeOutInt++ >10) //Si se cumple durante X veces el SampleTime (delay de la parte integral)

{

Integral+=(float)Ki*(float)error;

timeOutInt=3000; //Para evitar desbordamiento del numero si esta durante mucho tiempo

} }else { Integral=0; timeOutInt=0; } //Parte derivativa Derivative=(float)Kd*((float)error-(float)prev_error); dutycycle=(int)Proportional+ (int)Integral + (int)Derivative; //Limites de la salida. PWM de Arduino 0-255 (8 bits).

if (dutycycle <0) { dutycycle=0; }else if (dutycycle>255) { dutycycle=255; }

(14)

//Actualizo salida

analogWrite(9,(int)dutycycle);

//Mando datos a Stamplot Serial.print(temp); Serial.print(13,BYTE); Serial.print("D="); Serial.print(dutycycle); Serial.print(";E="); Serial.print(error); Serial.print("; P="); Serial.print(Proportional); Serial.print("; I="); Serial.print(Integral); Serial.print("; D="); Serial.print(Derivative); Serial.print(13,BYTE); } //--- }

// Funcion de conversion lectura ADC a grados mediante una tabla guardada en memoria de programa del micro

// para no gastar memoria RAM. float calcTemp(uint16_t myADC) {

//Recorro la tabla de valores del sensor NTC for(int i=0; i<21;i++)

{

//No extrapola, si es menor se queda con el primer valor de la tabla if (myADC>=pgm_read_word(&(ntc[0][0])))

{

temp=pgm_read_word(&(ntc[0][1])); break;

}

//No extrapola, si es mayor se queda con el ultimo valor de la tabla if (myADC<=pgm_read_word(&(ntc[20][0]))) { temp=pgm_read_word(&(ntc[20][1])); break; } uint16_t actualADC=pgm_read_word(&(ntc[i][0])); if (myADC>=actualADC) { if (i>0) { uint16_t previousADC=pgm_read_word(&(ntc[i-1][0])); uint16_t previousTemp=pgm_read_word(&(ntc[i-1][1])); uint16_t actualTemp=pgm_read_word(&(ntc[i][1]));

(15)

temp=( ((float)myADC - (float)previousADC) * ((float)actualTemp - (float)previousTemp) / ((float)actualADC - (float)previousADC) )+previousTemp; break; } } } return (temp); } void config_StampPlot() { //CONFIGURACION STAMP PLOT LITE

//Titulo de la ventana (FORM)

Serial.print("!TITL Arduino Power!"); Serial.print(13,BYTE);

//Titulo de usuario (STATUS)

Serial.print("!USRS Control PID"); Serial.print(13,BYTE);

//Valor maximo del eje Y Serial.print("!AMAX 62"); Serial.print(13,BYTE); //Valor minimo del eje Y Serial.print("!AMIN 57"); Serial.print(13,BYTE); //Valor maximo de tiempo Serial.print("!TMAX 500"); Serial.print(13,BYTE);

//Configuro el numero de puntos Serial.print("!PNTS 8000"); Serial.print(13,BYTE);

//Ayadir Tiempo en la lista de mensajes Serial.print("!TSMP OFF");

Serial.print(13,BYTE); //Plot ON

Serial.print("!PLOT ON"); Serial.print(13,BYTE);

//Borra el valor Max y Min almacenado despues del RESET Serial.print("!CLMM");

Serial.print(13,BYTE); //Limpio la lista de mensajes Serial.print("!CLRM");

Serial.print(13,BYTE);

//Borro el fichero stampdat.txt Serial.print("!DELD");

Serial.print(13,BYTE);

//Borro el fichero stampmsg.txt Serial.print("!DELM");

Serial.print(13,BYTE);

//Salvar datos Analogicos y digitales en stampdat.txt Serial.print("!SAVD ON");

(16)

Serial.print(13,BYTE);

//Salvar Mensajes en stampmsg.txt Serial.print("stampmsg.txt"); Serial.print(13,BYTE);

//RESET DEL GRAFICO PARA COMENZAR A PLOTEAR Serial.print("!RSET");

Serial.print(13,BYTE);

Referencias

Documento similar

This section provides guidance with examples on encoding medicinal product packaging information, together with the relationship between Pack Size, Package Item (container)

Package Item (Container) Type : Vial (100000073563) Quantity Operator: equal to (100000000049) Package Item (Container) Quantity : 1 Material : Glass type I (200000003204)

Cedulario se inicia a mediados del siglo XVIL, por sus propias cédulas puede advertirse que no estaba totalmente conquistada la Nueva Gali- cia, ya que a fines del siglo xvn y en

De acuerdo con Harold Bloom en The Anxiety of Influence (1973), el Libro de buen amor reescribe (y modifica) el Pamphihis, pero el Pamphilus era también una reescritura y

The part I assessment is coordinated involving all MSCs and led by the RMS who prepares a draft assessment report, sends the request for information (RFI) with considerations,

De hecho, este sometimiento periódico al voto, esta decisión periódica de los electores sobre la gestión ha sido uno de los componentes teóricos más interesantes de la

Ciaurriz quien, durante su primer arlo de estancia en Loyola 40 , catalogó sus fondos siguiendo la división previa a la que nos hemos referido; y si esta labor fue de

información que el individuo puede procesar por su sistema nervioso, y los factores relacionados van a influir en las habilidades y destrezas sociales, que pondrá al uso al