Termostato con PIC

2 octubre, 2012

El amigo Roberto ha construido un termostato basado en PIC16F876 y lo comparte con nosotros en este artículo.


El presente proyecto trata acerca de la construcción de un termostato, cuya aplicación va a ser para el control de la temperatura de un motor de corriente continua de 600w con control de velocidad por medio de un variador con SCR’s. El motor cuenta con un ventilador incorporado al rotor, y el problema surge cuando trabaja a bajas revoluciones. En este caso el ventilador no produce el caudal de aire suficiente como para refrigerarlo y se produce un aumento de la temperatura que puede llegar a destruir el bobinado y el motor.

Para evitar este problema hemos puesto detrás del motor un ventilador, similar a los de la fuente de alimentación de un ordenador, que estará siempre encendido y otro ventilador en la caja en la que está el motor. El segundo ventilador se controla por pwm y sólo le hemos dotado de dos velocidades, una al 50% y otra al 100%.

Para medir la temperatura, hemos elegido el DS18B20 de Maxim. Es un dispositivo que nos manda la temperatura de forma digital y sólo utiliza 3 cables.

Aunque no hacemos uso de esta función, al circuito le hemos dotado la posibilidad de conectarle un relé que se active por debajo de una temperatura y que desconecte el motor cuando se alcance otra temperatura.

Para mostrar la temperatura, utilizamos un display de 2 ½ dígitos, obtenido de la caja de un ordenador que mostraba la frecuencia de funcionamiento del micro (la caja es de hace unos pocos años). Este es el motivo por el que hemos elegido el PIC16f876 que cuenta con 2 puertos de 8 bits para el control de cada dígito.

Las temperaturas elegidas en el software son un poco arbitrarias y las iremos eligiendo al usar el conjunto de forma práctica. No disponemos de hojas características de rangos de funcionamiento, en cuanto a temperatura del motor y no dejamos que llegue a 100º, pues corremos el riesgo de que se queme el barniz del bobinado.

Modificando los dispositivos conectados a las salidas y/o el software podemos adaptarlo a cualquier equipo que requiera un termostato para control de la temperatura.

Circuito

Como hemos dicho, el micro elegido es un PIC16F876 que contiene dos puertos de 8 bits y el puerto A de 6 bits. Los dos puertos de 8 bits se usan para controlar cada uno de los dígitos del display de 7 led’s.

El puerto A se usa para comunicarnos con el sensor de temperatura y para actuar sobre las salidas:

  • El Pin RA0 es usado como entrada/salida para la comunicación con el DS18B20. Este sensor tiene 3 cables, dos de ellos son masa y alimentación, y el tercero es la línea de datos. Para comunicarse con el dispositivo y que nos envíe la lectura de la temperatura se usa un protocolo diseñado por el fabricante. Podemos consultar las hojas características para saber detalladamente el funcionamiento de este dispositivo.
  • Al pin RA1se conecta el ventilador que hemos llamado “1”. Este ventilador siempre está activado, ya que en la inicialización de los puertos, ponemos este bit permanentemente a 1.
  • El ventilador 2 le conectamos al pin RA2. Este ventilador se controla por pwm, pero sólo hemos definido dos velocidades, una al 50% y otra al 100%. Cada una de las velocidades la configuramos para un rango de temperatura, la de 50% a 50º y la de 100% a 65º.
  • El relé está controlado por el pin RA3. Éste permite conectar/desconectar la alimentación del motor, de forma que si la temperatura está por debajo de un valor el relé está activado y el equipo funciona normalmente. Superando una determinada temperatura se desactiva el relé y el equipo se desconecta de la alimentación de 220v.
  • En el pin RA5 hemos conectado un buzzer que sonará con una frecuencia de 10HZ y se activa cuando la temperatura alcanzada es de 65º. Esto nos sirve de alarma para que el usuario decida continuar usando el equipo o desconectarlo hasta que la temperatura descienda. Para esta función no hemos usado el pin RA4 porque es en colector abierto y requiere que se añada resistencia de pull-up.

A continuación se adjunta el esquema del Termostato. La alimentación del circuito es a 12V, ya que los ventiladores son de 12v, e internamente se estabiliza a 5V para alimentar al PIC.

Se incluye un pulsador para resetear el micro en caso de que sea necesario.

En el diseño sólo hemos puesto una clema a la que se conectan los cables de alimentación. El resto de dispositivos (sensor, ventiladores y relé) se soldarán directamente al circuito impreso, y la longitud de los cableados variará en función de la distancia entre la ubicación de la placa y de los dispositivos.

Esquema termostato con PIC

Esquema termostato con PIC

Circuito Impreso.

Una vez visto el esquema y lo que queremos, hemos diseñado un circuito impreso, lo más pequeño que de momento sabemos hacer. Hacemos uso de algunas resistencia SMD.

Debido a que la placa está realizada a una cara, es en algunos casos inevitable tirar puentes. Para fabricación casera, el metalizado de los taladros es complicado, y por eso descarto el uso de la doble cara.

El circuito impreso está realizado a mano con un programa muy sencillo, el SPRINT LAYOUT, en la siguiente imagen se puede ver el diseño de la placa.

Diseño de la placa

Diseño de la placa

La placa una vez terminada tiene el siguiente aspecto:

Placa plateada

Placa plateada

Para el acabado de la placa, hemos utilizado un plateador en frío (por ejemplo, plateador en Frío Louis XIII) que me indicó mi amigo Alejandro, que protege el cobre de la oxidación y nos proporciona un aspecto casi profesional.

Las siguientes imágenes muestran la placa terminada:

Cara de componentes

Cara de componentes

Cara de soldaduras

Cara de soldaduras

 

Montaje del Sensor DS18B20

Montaje del Sensor DS18B20

Placa final

Placa final

Software

El software se ha escrito con el programa CCS y es sencillo de seguir. Para llevar a cabo la lectura del sensor se utiliza una librería que contiene las rutinas de inicialización y lectura de la temperatura. En el programa tenemos que definir el puerto de datos para comunicación con el sensor e incluir la librería del sensor.

Para la generación del PWM hemos utilizado el Timer0. Se debe tener en cuenta que antes de leer el sensor se requiere desactivar las interrupciones, puesto que si ocurre una interrupción en el momento que estamos comunicándonos con el sensor, obtendremos un funcionamiento impredecible. Esto va a provocar que la señal pwm dé un salto, pero como es para el giro de un ventilador no tiene mayores repercusiones.

/*Termostato. Este programa lee la temperatura de un sensor DS18B20 de 1 cable y la muestra

en un display de 7 segmentos y dos digitos y medio. Cuando la temperatura sube de 99º se activa el
punto intermedio entre los dos dígitos.
El display es de ánodo común. A parte dispone de una salida a relé que es activada al dar
alimentación al módulo y que se desactiva al llegar a cierta temperatura. También dispone
de una salida transistorizada para conectar dos ventiladores. Uno de ellos está siempre encendido y el otro le dotaremos de dosvelocidades, una se activará a cierta temperatura y la otra a otra temperatura*/

#include <16F876.h>
#FUSES NOWDT //No Watch Dog Timer
#FUSES NOPUT //No Power Up Timer
#FUSES NOPROTECT
#FUSES XT
#FUSES NOBROWNOUT
#FUSES NOLVP
#FUSES NOCPD
#FUSES NOWRT
#FUSES NODEBUG
<pre>#use delay(clock=4000000)</pre>
<pre>/*Poner estas instrucciones debajo del reloj, en otro punto no funciona*/
#define ONE_WIRE_PIN PIN_A0
#include <onewire.h></pre>
<pre>// PINOUT
#byte PORTA=5
#byte PORTB=6
#byte PORTC=7</pre>
<pre>#bit ventilador1=PORTA.1 // unidades Temperatura
#bit ventilador2=PORTA.2 // decenas Temperatura
#bit rele=PORTA.3
#bit buzzer=PORTA.5</pre>
<pre>// Los segmentos se conectan al PORTB, así:
// A=portb.0
// B=portb.1
// C=portb.2
// D=portb.3
// E=portb.4
// F=portb.5
// G=portb.6</pre>
<pre>/* Catodocomun
#define cero 0x3F
#define uno 0x06
#define dos 0x5B
#define tres 0x4F
#define cuatro 0x66
#define cinco 0x6D
#define seis 0x7D
#define siete 0x07
#define ocho 0x7F
#define nueve 0x6F
*/
</pre>
<pre>// Anodocomun
#define cero 0x40
#define uno 0x79
#define dos 0x24
#define tres 0x30
#define cuatro 0x19
#define cinco 0x12
#define seis 0x02
#define siete 0x78
#define ocho 0x00
#define nueve 0x18</pre>
<pre>#define velocidad1 128
#define velocidad2 255</pre>
<pre>constintbcd[]={cero,uno,dos,tres,cuatro,cinco,seis,siete,ocho,nueve};</pre>
<pre>intunidades_temp, decenas_temp;</pre>
<pre>int Ticks=0, pwm; //un ticks es 0,5 seg</pre>
<pre>intambient;</pre>
<pre>/*control pwm*/
#int_TIMER0
TIMER0_isr()
{
 Ticks++;</pre>
<pre>if (pwm!=0 && Ticks==0)
 ventilador2=1;</pre>
<pre>if (Ticks>=pwm)
 ventilador2=0;
}</pre>
<pre>void main()
{
inti;
 setup_timer_0(RTCC_INTERNAL|RTCC_DIV_2);</pre>
<pre>set_tris_a(0x00); //todo salidas
set_tris_b(0x00); //todo salidas
set_tris_c(0x00); //todo salidas</pre>
<pre>unidades_temp=0;
decenas_temp=0;
 PORTB=bcd[unidades_temp]|0x80;
 PORTC=bcd[decenas_temp];</pre>
<pre>ventilador1=1;</pre>
<pre>pwm=0;
buzzer=0;
ambient=0;</pre>
<pre>enable_interrupts (INT_TIMER0);
enable_interrupts(GLOBAL);</pre>
<pre>while (1)
 {
disable_interrupts(GLOBAL);
ambient = ds1820_read();
enable_interrupts(GLOBAL);</pre>
<pre>unidades_temp=ambient%10;
decenas_temp=ambient/10;</pre>
<pre>if (ambient>99)
 PORTB=bcd[unidades_temp];
 else
PORTB=bcd[unidades_temp]|0x80; //es anodocomun por eso lo pongo a 1 cuando es menor de 99</pre>
<pre>PORTC=bcd[decenas_temp];</pre>
<pre>if (ambient<100)
rele=1;</pre>
<pre>if (ambient>50)
pwm=velocidad1;
if (ambient>65)
pwm=velocidad2;</pre>
<pre>if (ambient>80)
rele=0;
if (ambient>=65)
{
 for (i=0;i<10;i++)
 {
 buzzer=1;
delay_ms(50);
 buzzer=0;
delay_ms(50);
}
 }</pre>
<pre>delay_ms(500);</pre>
<pre>}
}</pre>
<pre>Rutinas utilizadas para el uso del sensor "onewire.h"
/ARCHIVO AUXILIAR CON LAS FUNCIONES PARA LEER LA
//TEMPERATURA DEL SENSOR DS18B20 DEL SISTEMA EB88.
//LA FUNCION ds1820_read() REGRESA UN VALOR
//DE PUNTO FLOTANTE CON LA TEMPERATURA LEIDA.
//NO OLVIDE INSERTAR EL SENSOR DS18B20 EN SU BASE
//DE 3 PINES EN EL MODULO EB88.</pre>
<pre>//#define PIN_A3 43
//#define ONE_WIRE_PIN PIN_A3</pre>
<pre>void onewire_reset();
void onewire_write(int8 data);
int onewire_read();
float ds1820_read();</pre>
<pre>void onewire_reset() {
 output_low(ONE_WIRE_PIN); // pull the bus low for reset
 delay_us(500);
 output_float(ONE_WIRE_PIN); // float the bus high
 delay_us(500); // wait-out remaining initialisation window
 output_float(ONE_WIRE_PIN);
}</pre>
<pre>void onewire_write(int8 data) {
 int8 count;
 for(count = 0; count < 8; ++count) {
 output_low(ONE_WIRE_PIN);
 delay_us(2); // pull 1-wire low to initiate write time-slot.
 output_bit(ONE_WIRE_PIN, shift_right(&data, 1, 0)); // set output bit on 1-wire
 delay_us(60); // wait until end of write slot.
 output_float(ONE_WIRE_PIN); // set 1-wire high again,
 delay_us(2); // for more than 1us minimum.
 }
}</pre>
<pre>int onewire_read() {
 int count, data;
 for(count = 0; count < 8; ++count) {
 output_low(ONE_WIRE_PIN);
 delay_us(2); // pull 1-wire low to initiate read time-slot.
 output_float(ONE_WIRE_PIN); // now let 1-wire float high,
 delay_us(8); // let device state stabilise,
 shift_right(&data, 1, input(ONE_WIRE_PIN)); // and load result.
 delay_us(120); // wait until end of read slot.
 }
 return data;
}</pre>
<pre>float ds1820_read() {
 int8 busy=0, temp1, temp2;
 signed int16 temp3;
 float result;
 onewire_reset();
 onewire_write(0xCC); //Skip ROM, address all devices
 onewire_write(0x44); //Start temperature conversion
 while(busy == 0) //Wait while busy (bus is low)
 busy = onewire_read();
 onewire_reset();
 onewire_write(0xCC); //Skip ROM, address all devices
 onewire_write(0xBE); //Read scratchpad
 temp1 = onewire_read();
 temp2 = onewire_read();
 temp3 = make16(temp2, temp1);
// result = (float) temp3 / 2.0; //Calculation for DS18S20 with 0.5 deg C resolution
// result = (float) temp3 / 16.0; //Calculation for DS18B20 with 0.1 deg C resolution</pre>
<pre>result = (float) temp3 / 16.0; //Calculation for DS18B20
delay_ms(200);
return(result);
}
Share

Etiquetas: , , ,