Está en la página 1de 14

“Control de temperatura con PWN usando PIC

(Pic C CCS) con protección de cortocircuito”.

Imagen del Circuito:

Parto de dos sencillas ideas:


Un MOSFET permite la coducción de corriente de Source a Drain en proporción
directa al voltaje existente en la base, por tanto se dice que el MOSFET es un
dispositivo controlado por voltaje a diferencia del BJT que es controlado por
corriente. (MOSFET)
Un microcontrolador puede ser programado para mandar una señal PWM a
frecuencia y DutyCicle variables. Si sabemos que podemos variar el voltaje
promedio de esa señal PWM a la salida del microcontrolador (de 0v a 5v),
amplificando esa señal y mandándola a la base de un MOSFET lograríamos
controlar en cierto rango controlar la corriente que pasa de Source a Drain en
el mismo.
Con las dos ideas anteriores podemos partir para hacer un controlador de
corriente, pero para hacer esto un poco más práctico, si hacemos pasar esta
corriente controlada por una resistencia de carga haríamos que esta se
calentara, logrando ahora un control de la temperatura de la resistencia al
variar la corriente que pasa a través de esta.

Bien, para que todo esto funcione, dividiré el desarrollo del proyecto en dos
etapas:
Etapa de control
Etapa de Potencia (se incluye la protección contra cortos)

Etapa de Control

Material:
4 potenciometros de 1kohm
2 leds
3 resistencias 330 ohms
1 pic16f887
1 pantalla lcd (JHD 162A)
1 LM35 (sensor de Temperatura de Precisión)

Usando un microcontrolador PIC 16f887 lograremos hacer un control del


DutyCicle del PWM conforme a la temperatura. Conforme la temperatura
aumenta el DutyCicle delPWM disminuirá de tal forma que cuando la
resistencia llegue a la temperatura deseada el DutyCicle será 0% por tanto la
corriente que pasará a través de la resistencia será 0A haciendo que la
temperatura se mantenga estable en ese punto, hasta que esta se enfríe y la
señal PWM vuelva a polarizar el MOSFET.

He aquí el esquemático:
Como se muestra en la imagen pueden armar el circuito de control de
temperatura y simularlo en Isis Proteus.

Al momento de simularlo pueden:


Variar la frecuencia de la señal PWM por medio del potenciómetro conectado a
RA0.
Variar la Temperatura por medio del sensor LM35 y ver como el DutyCicle del
PWM disminuye conforme la temperatura se acerca al SetPoint (Temperatura
deseada)
Variar el SetPoint de 0ºC a 150ºC por medio del potenciómetro conectado a
RA1.
/*
Huamán Rivera Jonathan Benjamín
Montesinos Max
Adriana Rodríguez Liñán
Yamunaqué patricia, Febrero 2013
*/

/*
Programa de Control de Temperatura con un PIC
Permite variar el DutyCicle y Frecuencia de una señal PWM
que controla la corriente que recibe una resistencia de carga

La Temperatura a la que llega dicha resistencia se puede variar de 0 a 150ºC


(SetPoint)
La frecuencia del PWM va de 0Hz a 1KHz (Teoricamente ya que practicamente
nunca baja de 477Hz)

INFO:
El comportamiento es simple, por medio del sensor LM35 se procede a medir la
temperatura
si esta no ha llegado aún a la temperatura deseada (SetPoint) manda un PWM
con un DutyCicle
proporcional a la diferencia entre la temperatura medida y la deseada, si la
diferencia es grande
el DutyCicle tambíen lo será y viceversa
Al llegar a la teperatura deseada el Control la mantiene.

El circuito está diseñado sólo para calentar no para enfriar por tanto
si se elige un SetPoint abajo de temperatura ambiente, el DutyCicle siempre
permanecerá en 0%.

*/

#include <16f887.h> //Nuestro pic


#device adc = 10 //Convertidor AD a 10bits
#fuses XT, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay (clock=8000000) //Fosc=8Mhz
#include <lcd.c> //Libreria de la lcd

//Declaracion de variables publicas


float TOC;
float Prescaler;

//Prototipos de Funciones
void Refresh_lcd(float _Frecuencia_, float _DutyCicle_, float _SP_, float
_Temperatura_);
float Get_Lectura(int channel);
float Relacion_LineaRecta_m(float m, float valorEjeIndep);
float Calcula_PR2(float _Frecuencia);
void Refresh_PWM_Duty(float _DCValue);
void Refresh_PWM_Frec(float _Period2);
float Calcula_Value_DC(float _SP_, float _Temp_);
float CalculaPendiente (float Xmin, float Ymin, float Xmax, float Ymax);

void main()
{
//int i = 0;

float Value_DC = 0.0;


float bits_frecuencia = 0.0;
float bits_temperatura = 0.0;
float bits_setPoint = 0.0;
float bits_dutyCicle = 0.0;
float SetPoint = 150.0; //Valor que se desea de Temperatura
float DutyCicle = 0.0;
float Frecuencia = 0.0;
float Temperatura = 0.0;
float mFrec = 0.977517106; //Pendiente de la recta para Frecuencia m =
(1000 - 0)/(1023 - 0)
float mT = 0.65625; //Pendiente de la temperatura m = ( 21 - 0 ) /
( 32 - 0 )
float mVDC = 0.0;
//float mDC = 0.000977517065; //Pendiente de la recta para DutCicle m =
(1 - 0)/(1023 - 0)
float mDC = 0.392156862; //Pendiente de la recta para DutCicle m =
(100 - 0)/(255 - 0)
float mSP = 0.146627566; //Pendiente de la recta para SetPoint m =
(150 - 0)/(1023 - 0)

float Period2 = 0.0;


float PWMValue = 0.0;
float Period2_ = 0.0; //Valor de Period2 inmediato anterior
float PWMValue_ = 0.0; //Valor de PWMValue inmediato anterior

TOC = 0.000000125; // TOC = 1 / clock = 1 / 8000000


Prescaler = 16.0;

//Programar el oscilador interno del pic y usar CCP afecta al PWM


//setup_oscillator(OSC_8MHZ|OSC_INTRC); //Programamos oscilador interno
del Pic a 8MHZ
//setup_oscillator(OSC_8MHZ);
set_tris_b(0); //Puerto B como salida
output_low(PIN_C2); // Set CCP1 output low
setup_ccp1(CCP_PWM); // Configure CCP1 as a PWM
lcd_init(); //Inicializamos LCD
lcd_putc("Iniciando..."); //"Hola Mundo"

//Frecuencia del PWM


setup_timer_2(T2_DIV_BY_16, 249, 1); // 500 Hz
set_pwm1_duty(500);

delay_ms(5);
while(1)
{

output_toggle(PIN_B5); //Parpadeamos Led, output_toggle cambia


el estado logico del pin pasado de parametro

//Obtenemos las lecturas del convertidor A/D para cada parametro de


entrada (frecuencia, temperatura y setPoint)
bits_frecuencia = Get_Lectura(0);
bits_temperatura = Get_Lectura(1);
bits_setPoint = Get_Lectura(4);

//Obtenemos el valor del eje dependienta pasando el valor del eje


independiente (bits) y el valor de la pendiente
Frecuencia = Relacion_LineaRecta_m(mFrec, bits_frecuencia);
SetPoint = Relacion_Linearecta_m(mSP, bits_setPoint);
Temperatura = Relacion_Linearecta_m(mT, bits_temperatura);

//Calculamos el valor del DC


Value_DC = Calcula_Value_DC(SetPoint, Temperatura);

mVDC = CalculaPendiente(0, 0, SetPoint, 255);//Calculamos la pendiente

bits_dutyCicle = Relacion_Linearecta_m(mVDC, Value_DC);

DutyCicle = Relacion_Linearecta_m(mDC, bits_dutyCicle);

PWMValue = bits_dutyCicle;

Period2 = Calcula_PR2(Frecuencia);
if(PWMValue != PWMValue_)
{Refresh_PWM_Duty(PWMValue);}

if(Period2 != Period2_)
{Refresh_PWM_Frec(Period2);}

Refresh_lcd(Frecuencia, DutyCicle, SetPoint, Temperatura);

PWMValue_ = PWMValue;
Period2_ = Period2;

delay_ms(10); //Esperamos a lo sonso 250 ms


}
}

//Metodo que calcula y regresa la pendiente para una recta que posee los
puntos
//(Xmax,Ymax) y (Xmin,Ymin)
float CalculaPendiente (float Xmin, float Ymin, float Xmax, float Ymax)
{
float m = 0.0;
float num = 0.0;
float den = 0.0;

num = Ymax - Ymin;


den = Xmax - Xmin;
m = num / den;

return m;
}

//Metodo que calcula el valor del DutyCicle que se enviará


//No es más que la diferencia entre el valor de temperatura que
//se desea (SetPoint _SP_) y el valor de temperatura actual (_Temp_)
float Calcula_Value_DC(float _SP_, float _Temp_)
{
float Value_DC = 0.0;
Value_DC = _SP_ - _Temp_;

if(Value_DC < 0)
{ Value_DC = 0; }

return Value_DC;
}

//Asigna un nuevo valor de DutyCicle al PWM usado


void Refresh_PWM_Duty(float _DCValue)
{
set_pwm1_duty((int)_DCValue);
}

//Asigna un nuevo valor de frecuencia al PWM


void Refresh_PWM_Frec(float _Period2)
{
setup_timer_2(T2_DIV_BY_16, _Period2, 1);
}

//Calcula el valor del Periodo(PR2) para la frecuencia


//pasada de parametro
float Calcula_PR2(float _Frecuencia)
{
float _PR2 = 0.0;
float div = 0.0;

div = _Frecuencia * 4 * TOC * Prescaler;


_PR2 = (1 / div) - 1;

if(_PR2 < 0.0)


{ _PR2 = 0.0;}

return _PR2;
}

//Metodo que regresa el valor del eje dependiente para un valor


//del eje independiente (valorEjeIndep) de una recta de pendiente m
//que pasa por el origen
float Relacion_LineaRecta_m(float m, float valorEjeIndep)
{
float Valor = 0.0;
Valor = (m * valorEjeIndep); //Calculamos el Valor del eje dependiente
return Valor;
}

//Obitiene una lectura del canal analógico pasado de parámetro


float Get_Lectura(int channel)
{
float medicion=0; //variable entera que contendra la medicion
del convertidor AD
int1 done = 0; //Contendra 1 si el convertidor terminó de
convertir

setup_adc (adc_clock_internal); //Usando el oscilador interno


setup_adc_ports (all_analog); //Todo el puerto analogico como entrada
analogica
set_adc_channel (channel); //Establecemos el canal de lectura
analogica
delay_ms(1); //a small delay is required after setting the
channel
medicion=read_adc (); // Hace conversión AD
done = adc_done(); //done = 1 si el convertidor termino de
convertir
while(!done)
{
done = adc_done(); //Mientras no acabe de convertir se seguira
ciclando
}
setup_adc (adc_off); //detenemos al convertidor
return medicion; //Regresamos la medicion
}

//Reasigana los valores en la pantalla lcd


void Refresh_lcd(float _Frecuencia_, float _DutyCicle_, float _SP_, float
_Temperatura_)
{
lcd_putc("\f");
printf(lcd_putc,"F:%4.1f DC:%4.1f", _Frecuencia_,_DutyCicle_);
lcd_putc("%");
lcd_putc("\n");
printf(lcd_putc,"SP:%4.1f T:%4.1f", _SP_, _Temperatura_);
}

Con respecto a la codificación cabe aclarar ciertas cosas:

Se dejan comentadas ciertas lineas de codigo que no se usaron al final debido


a que causaban errores o no era conveniente usarlas, esto por si alguien que
desea modificar el código no cometa el mismo error.
Oscilador Interno: Aún no estoy muy seguro del porque, pero la
linea: //setup_oscillator(OSC_8MHZ|OSC_INTRC);   //Programamos oscilador
interno del Pic a 8MHZ Me ocasionó que el PWM se saliera de control y actuara
como loco.
Se necesitan hacer calibraciones en la variable mT (linea 67) del programa de
acuerdo a tu circuito y dispositivos (esta variable representa la pendiente que
se forma en la recta Temperatura vs Bits del ADC), es sencillo, sigue estos
pasos:
Una vez tengas el circuito armado, cambia la linea 135 de codigo en el
programa:
Refresh_lcd(Frecuencia, DutyCicle, SetPoint, Temperatura);
por: Refresh_lcd(Frecuencia, DutyCicle, SetPoint, bits_temperatura);
Compila y programa el PIC
Conectalo a VCC (5v) y ponlo a funcionar.
Veras que en la pantalla LCD se mostrarán ahora los bits que arroja el
convertidor analógico digital, si estas a Temperatura ambiente normalmenteno
pasan de 45 bits (si pasa de 45 es porque estas a una temperatura mayor no
que este mal ok!!!). T: 45 como se ve en la simulación en ISISIMG3. A este
valor le llamaremos bits_Temperatura
Mide el voltaje (con un Voltímetro) que te entrega el LM35 y deduce la
temperatura a la que te encuentras. Ejemplo: si dice 0.021V están a 21ºC, si
dice 0.035V estan a 35ºC que calor!!!!. A este valor le llamaremosTemperatura
Haz la división sencilla de de Temperatura entre
bits_Temperatura:Temperatura / bits_Temperatura.
Coloca el valor de esa división en la linea correspondiente (linea 66), así: float
mT = Valor_Division;
Ejemplo: Para Temperatura = 21ºC y bits_Temperatura = 32, Valor_División =
Temperatura / bits_Temperatura = 0.65625, por tanto la linea 65 es : float mT
= 0.65625;
Regresas la linea 135 a su valor original, compilas y Voila!!!!, ya tienes tu
etapa de control lista.

También podría gustarte