PROYECTO: Control temperatura LM35 en PIC16F877A con LCD y teclado 4x4

ACTUALIZACIÓN 22/11/2018: He hecho algunas mejoras al código por problemas con el teclado y mostrar valores que no correspondían, además detallaré mejor la explicación del proyecto y su simulación.


¡Hola SkullTraper! Bienvenidos a un nuevo artículo "Publicación de un proyecto"  Donde Vamos a ver  un proyecto 100% funcional lo hemos desarrollado con unos compañeros de la Universidad en algunos 3 o 4 días tuvimos algunos líos de manejo de teclado con el PIC pero todo bien.



¿DE QUÉ TRATA EL PROYECTO? 
Mira el funcionamiento del proyecto en este vídeo ;)

El Proyecto como el título lo indica se trata de controlar temperatura con un LM35 pero más a fondo el problema planteado es el siguiente:

Se desea implementar un sistema regulador de temperatura, que adquiera y visualice en una pantalla LCD el valor de temperatura registrado por medio de un LM35, y lea por un teclado matricial valores de alarma de temperatura alta y baja. Si los valores límites son alcanzados debe mostrarse en la pantalla mensajes que así lo indiquen. En la pantalla debe mostrarse siempre la temperatura leída, y un mensaje que indique si está baja, normal o alta.


DESARROLLO COMPLETO DEL PROYECTO

Aclaro de inicio como siempre se usó MPLAB y PIC C para ejecutar archivos, además se hizo uso de librerías para LCD y el teclado es importante que no modifiques nada de las librerías salvo que seas excelente manejando C, si no mueves nada y lo haces tal cuál el proyecto te funcionará:

1. Materiales y componentes

Para este proyecto los materiales y componentes a precisión fueron los siguientes:

- x1 Programador de PICS (Pickit 2 el que usamos).
- x1 PIC16F877A.
- x1 LCD 16x2.
- x1 teclado matricial 4x4.
- x1 fuente de voltaje, 5 voltios está bien para trabajar.
- Jumpers o puentes de cable UTP para conexiones.
- x1 Potenciometro de 10k.
- x1 LM35 para sensar la temperatura.
- x1 Cristal de Cuarzo de 4MHz.
- x1 Protoboard (Ahí cabe todo el proyecto).

¡Listo! con esto iniciamos el proyecto sin problema alguno.


2. Simulación Proteus

La simulación en Proteus aunque es una captura apenas, sería algo así, recuerden que al final del post dejaré el link para descargar el proyecto completo si lo desean:

2.1. ¿Cómo probar el código en la simulación?

Muchos me han escrito para probar la simulación en proteus antes de montar el circuito con el PIC, para hacerlo es muy fácil, cuando descargues el proyecto al final del post, abrirásla carpeta simulación > templm35, esto será un archivo proteus que se verá como la imagen anterior, luego daremos doble click sobre el PIC y nos saldrá la siguiente ventana:
Carga de archivo .hex en el pic en proteus

- Daremos click en la carpeta de "Program file" y buscaremos luego el archivo con extensión (.HEX) luego click en abrir:

Una vez cargado el archivo procedemos a simular nuestro proyecto y comprobar el funcionamiento de forma correcta como se ve en la siguiente imagen todo pinta bien al ver en el display el mensaje "HOLA USUARIO BIENVENIDO":
Simulación funcionando

Si ves que todo está OK sólo queda que realices el montaje y montes el archivo finalemente en el pic de forma física. 


3. Código completo, programar PIC 

En el proyecto completo están incluídas las librerías las cuales son "DriverTec4x4.c" y "LCD.c" no hace falta modificarlas en lo absoluto ¡No lo hagas!.

El código del proyecto en sí completo (Hay que tener en cuenta las librerías de teclado y LCD) es el siguiente:
 #include <16F877A.h>  
#device ADC=10    
#fuses XT,NOWDT,NOPROTECT,NOLVP,PUT,BROWNOUT
#use delay(clock=4000000)
#use fast_io(A)
#use fast_io(B)
//LIBRERÍAS AÑADIDAS *NO MODIFICAR LIBRERÍAS*
#include <lcd.c>
#include <DriverTec4x4.c>

int8 dig1,min0,dig2,min3,imprime,dig3,atencion,dig,max0,max3;
int1 detector;
int16 ayuda,temperatura,temp,Tmax,Tmin,min1,max1;

lcd_init();

void EjecuConversor(){
   setup_adc(ADC_CLOCK_INTERNAL);    // Configura el conversor
   setup_adc_ports(AN0);          // Entrada RA0 como analógica
   set_tris_A(0xFF);            // Todo el PortA como entrada
   set_adc_channel(0);            // Seleccionar un canal (en este caso Canal 0)
   delay_us(10);               // Retardo necesario entre la selección de canal y la adquisición.
}
void DescomponerDigitos(int16 Dato){
   int16 aux;
   
   Dig1= Dato/1000;
   Dig2= (Dato%1000)/100;
   aux= Dato%100;
   Dig3= aux/10;   
}
void ProcesarSenal(){
   int32 Read;
   
   Read= ayuda;
   temperatura=(100)*((Read*5.0)/1023.0)*(100);
   //temperatura=*100;
   DescomponerDigitos(temperatura);
      
   Dig1+= '0';
   Dig2+= '0';
   Dig3+= '0';
}

// Esta función ejecuta la acción requerida por cada pulsador del teclado.

void ProcesarTeclado(){   
      
   switch (atencion){
   
      case 0:   //TECLA 1            
           imprime="1";
         dig=1;
          detector=1;
            break;
            
      case 1:   //TECLA 2            
          imprime="2";
         dig=2;
          detector=1;
            break;
            
      case 2:  //TECLA 3             
          imprime="3";
         dig=3;
          detector=1;
            break;
         
      case 3:  //TECLA A             
         imprime="A";
          break;
          
      case 4:  //TECLA 6      
          imprime="6";
          dig=6;
          detector=1;
          break;
          
      case 5:   //TECLA 5      
          imprime="5";
          dig=5;
          detector=1;
          break;
          
      case 6:   //TECLA 4           
          imprime="4";
          dig=4;
          detector=1;
          break;
          
      case 7:   //TECLA B           
          imprime="B";
          break;
          
      case 8:  //IMPRIME 7             
          imprime="7";
          dig=7;
          detector=1;
          break;
          
      case 9:   //TECLA 8            
          imprime="8";
          dig=8;
          detector=1;
          break;
          
      case 10:  //TECLA 9         
          imprime="9";
          dig=9;
          detector=1;
          break;
          
      case 11:  //TECLA C        
           imprime="C";
           break;
           
      case 12:  //TECLA ASTERISCO          
          imprime="x";
          break;
          
      case 13:   //TECLA CERO          
          imprime="0";
          dig=0;
          detector=1;
          break;
          
      case 14:  //TECLA NUMERAL           
           imprime="X";
           break;
           
      case 15:   //TECLA D         
          imprime="D";
    }

   if(atencion!=16){  // Si se oprimió algún pulsador se
      delay_ms(150);  // elimina rebote.
   }
}   
void VisualizarLCD(){

   lcd_gotoxy(1,2);
   lcd_putc("Temp: ");
   lcd_putc(Dig1);
   lcd_putc(Dig2);
   lcd_putc(".");
   lcd_putc(Dig3);
   lcd_putc("    ");
}

//===========EJECUCIÓN DEL PROGRAMA 

void main() {

   lcd_init();
   EjecuConversor();
   set_tris_B(0x0F);
    port_b_pullups(TRUE);
   while(TRUE){
   
lcd_gotoxy(13,1);
    lcd_putc("fHOLA USUARIO");
    lcd_gotoxy(1,2);                 
          lcd_putc("BIENVENIDO");
          delay_ms(4000);
   lcd_putc("fIngresar limites");
   lcd_putc("nTmin: ");
   
   while(TRUE){      
   atencion=LeerTeclado(); //Lee la funcion teclado
   ProcesarTeclado();
   min1=dig;
   lcd_gotoxy(7,2);
   lcd_putc(imprime);
   delay_ms(150);
   
   if(detector==1){
      break;
      }
   }
   
   imprime=" ";
   detector=0;
   while(TRUE){
   atencion=LeerTeclado();
   ProcesarTeclado();
   min0=dig;
   lcd_gotoxy(8,2);
   lcd_putc(imprime);
   delay_ms(150);
   if(detector==1){
      break;
      }
      }
   imprime="  ";
   detector=0;
      while(TRUE){
   atencion=LeerTeclado();
   ProcesarTeclado();
   min3=dig;
   lcd_gotoxy(9,2);
   lcd_putc(".");
   lcd_putc(imprime);
   delay_ms(150);
   if(detector==1){
      break;
      }
      }
      
   imprime=" ";
   detector=0;
   
   Tmin=(min1*100)+(min0*10)+min3;
   
   lcd_putc("fIngresar limites");
   lcd_putc("nTmax:");
  
   while(TRUE){  
   atencion=LeerTeclado();
   ProcesarTeclado();
   max1=dig;
   lcd_gotoxy(7,2);
   lcd_putc(imprime);
   delay_ms(150);
   if(detector==1){
      break;
      }
   }
   
   detector=0;   //DETECTA MI PULSACIÓN DE TECLA ANTES DE DAR
                 // UN SALTO AL SIGUIENTE DIGITO O TEMP
   imprime="  ";
   
   while(TRUE){
   atencion=LeerTeclado();
   ProcesarTeclado();
   max0=dig;
   lcd_gotoxy(8,2);
   lcd_putc(imprime);
   delay_ms(150);
   if(detector==1){
      break;
      }
      }
      detector=0;
      imprime="  ";
      while(TRUE){
   atencion=LeerTeclado();
   ProcesarTeclado();
   max3=dig;
   lcd_gotoxy(9,2);
   lcd_putc(".");
   lcd_putc(imprime);
   delay_ms(150);
   
   if(detector==1){    //SI EL DETECTOR SE ACTIVA PASA AL 
                       //SIGUIENTE REGISTRO LUEGO DE LEER LOS DATOS
      break;
      }
      }
    
   Tmax=(max1*100)+(max0*10)+max3;
   
   lcd_putc("fmin=");
   if(min1==0)
   {min1="0";
      }else
      {
   min1=min1+'0';
   }
   min0=min0+'0';
   lcd_putc(min1);
   lcd_putc(min0);
   if(min3==0){
   min3=" ";
   }else{
   min3=min3+'0';
   lcd_putc(".");
   }
   lcd_putc(min3);
   lcd_gotoxy(9,1);
   
   lcd_putc("max=");
      if(max1==0)
   {max1=" ";
      }else
      {
   max1=max1+'0';
   }
   max0=max0+'0';
    lcd_putc(max1);
   lcd_putc(max0);
   if(max3==0){
   max3=" ";
   }else{
   max3=max3+'0';
   lcd_putc(".");
   }
   lcd_putc(max3);
   

   
   while (true){
      delay_ms(200);
      ayuda= read_adc();         // Adquisición de la señal   
      ProcesarSenal();      // Función encargada de procesar el dato adquirido
      temp=temperatura/10;
      if(temp<=Tmin)
      {
         lcd_gotoxy(1,2);
         VisualizarLCD();
         lcd_gotoxy(13,2);
          lcd_putc("Bajo");
       }else if(temp>Tmin && temp<Tmax)  //COMPARACION BOOLEANA !!!!importante!!!!
         {
            VisualizarLCD();
            lcd_gotoxy(13,2);
            lcd_putc(" :)");
            }else if(temp>=Tmax)
            {
               lcd_gotoxy(1,2);
               VisualizarLCD();
               lcd_gotoxy(13,2);
                  lcd_putc("Alto");
               }   
               
//============INICIO MANEJO DE ERRORES
   if(Tmax==Tmin){
    lcd_gotoxy(13,1);
    lcd_putc("fLOS LIMITES NO");
    lcd_gotoxy(1,2);                 
          lcd_putc("DEBEN SER IGUAL");
          delay_ms(4000);
           lcd_gotoxy(13,1);
           lcd_putc("fINGRESE DATOS");
    lcd_gotoxy(1,2);                 
          lcd_putc("VALIDOS DE NUEVO");
          delay_ms(5000);
          break; 
           
   }
    if(Tmax<Tmin){
        lcd_gotoxy(13,1);
    lcd_putc("fTMin NO DEBE SER");
    lcd_gotoxy(1,2);                 
          lcd_putc("MAYOR QUE TMax");
          delay_ms(4000);
           lcd_gotoxy(13,1);
           lcd_putc("fINGRESE DATOS");
    lcd_gotoxy(1,2);                 
          lcd_putc("VALIDOS DE NUEVO");
          delay_ms(5000);
          break;
             
   }
    
   //=============FIN MANEJO DE ERRORES
      }
      }
}


4. Montaje final proyecto 

El montaje final no siempre es el más estético y no todos deben parecerse jajaja después de todo son proyectos un poquito apresurados pero funcionan al 100 de 100 entonces algo así a los afanes el montaje nos quedó como vemos todo en una sola protoboard:


Es todo el contenido de este proyecto si notas algún error o problema puedes comentar estamos para resolver dudas recuerda visitar nuestra tienda para adquirir nuestros productos.

https://drive.google.com/open?id=0B8xtMFpL-ixBYkhjSnpQUFFtME0


Hasta la próxima,  
Compartir:

29 comentarios:

  1. Respuestas
    1. Hola Oscar ja! Que bien que gusto que te sirva un saludo...

      Eliminar
    2. una pregunta amigo buenas noches cuando lo trato de implementar la simulación las coordenadas de la matriz estan incorrectas si las tengo conectadas como tu la tienes en la simulación de antemano espero que me puedas ayudar y buen aporte la vd

      Eliminar
    3. Hola Jesús, ¿Qué tipo de error te genera? no comprendo muy bien lo que mencionas.

      Saludos,

      Eliminar
    4. al querer poner las conexiones de la matriz 4x4 no me queda como los pones y tuve que probar como iban conectados y si cambia la forma en como los conectas

      Eliminar
    5. Tienes la misma versión de proteus?

      Saludos,

      Eliminar
    6. Me pasa lo mismo, pulso una tecla y me imprime otro número que no corresponde a la tecla que pulse, a qué crees que se deba?

      Eliminar
  2. PERO NO SALE LO DE EL SET POIN??

    ResponderEliminar
    Respuestas
    1. Hola Juan los Set point se configuran cuando el usuario escribe por teclado los dígitos por ejemplo en dichas variable

      dig1,min0,dig2,min3

      Se hace el barrido y las almacena...

      Saludos,

      Eliminar
  3. muchísimas gracias amigo...... me salvaste la vida

    ResponderEliminar
    Respuestas
    1. BUENAS NOCHES AMIGO DISCULPA INTENTO HACER EL PROYECTO PERO CON UN PIC 16F887 PERO NO ME ACEPTA LA ENTRADA ANALÓGICA A LA HORA DE CAMBIAR DE LIBRERIA DEL PIC, A QUE SE DEBERA?

      Eliminar
    2. Lo mejor es usar los materiales tal cual aquí tenemos pues algunos PICS su configuración es diferente.

      Saludos.

      Eliminar
  4. hola ayudame con la libreria que as modificado del kbd4x4
    por favor

    ResponderEliminar
  5. hola ayudame por favor, cual es la manera correcta de usar la libreria de kbd4x4 para compilarlo que es lo unico que no me deja avanzar

    ResponderEliminar
  6. hola que tal, excelente proyecto, solo que me manda errores en el teclado, las teclas me las cambia ho no las reconoce

    ResponderEliminar
    Respuestas
    1. Hola que error te sale exactamente?

      Saludos,

      Eliminar
    2. aplasto teclas por ejemplo el 9 y me aparece el 5, en el uno el signo # etc, y al quemarlo en el pic, somo se representa en la LCD valores al asar y no lo escrito :(
      ayuda porfavor

      Eliminar
    3. Hola, ya lo he corregido estaré subiendo la nueva actualización del código el día de mañana (aunque en estos momentos estoy editando el post) explicaré un poco mejor como entenderlo y si es muy raro eso de las teclas a mi pasó cuando estuve verificando. Respecto a la LCD con valores aleatorios debes cuadrar bien el display que haga todos sus contactos correctamente.

      Te pido que estés pendiente de este post ya algunas horas subiré la actualización.

      Saludos,

      Eliminar
  7. disculpa en que versión de MPLA esta echo

    ResponderEliminar
    Respuestas
    1. Yo uso la 8.92 aquí la puedes obtener:

      http://www.skulltrap.co/2016/09/descargar-mplab-ultima-version-mas-util.html

      Saludos,

      Eliminar
  8. Disculpa amigo! Muchísimas gracias, me salvaste el semestre, solo una pregunta cómo podría agregar una señal que se active cuando diga alto y active un relee

    ResponderEliminar
    Respuestas
    1. Hola Gael, gracias por comentar puedes crear una varible extra que será la encargada de ponerse en 1 para activar el relé entonces donde está la comparación que dice alto en la línea 318 dentro de esa condicional puedes colocar tal variable rele=1; claro la variable siendo de tipo booleana.

      Saludos,

      Eliminar
  9. disculpa me manda errores con la variable LeerTeclado esta variable de donde sale?

    ResponderEliminar
    Respuestas
    1. Hola, no es una variable es una función, debe estar en la librería de teclado4X4 incluíste las librerías?

      Saludos,

      Eliminar
  10. Este comentario ha sido eliminado por el autor.

    ResponderEliminar

SkullTrapers

 

CLICK AQUI PARA IR A NUESTRA TIENDA ON LINE ARDUINO, ELECTRÓNICA, COMPONENTES