Mi primer proyecto. Crono-termostato, 16f876, lcd 16x2. Ayuda!!

Hola, soy nuevo en el foro. Quisiera compartir con vosotros un proyecto que estoy desarrollando, o al menos intentándolo. Llevo un par de meses liado con esto y por fin he conseguido que coja forma.

Se trata de un crono-termostato con curvas de temperatura ajustables mediante una interfaz lcd de 16x2. Está escrito en CCS utilizando un 16f876. Ahora estoy intentando hacerlo funcionar en el hardware. El diseño del esquemático y PCB los estoy haciendo en proteus. El sensor de temperatura originalmente es un LM35, aunque tengo aquí un par de lm335 que encontré en una tienda de mi localidad. No sé cual usaré en el diseño definitivo.

Os agradecería toda ayuda posible para terminarlo, me está trayendo muchos dolores de cabeza y ya se ha convertido en un reto personal conseguirlo. No seáis demasiado duros con los fallos que habré cometido, que seguro los hay. Es mi primera incursión en el mundo de la programación / electrónica así que podéis considerarme un completo novato.

Tengo varios problemas, pero el que me está trayendo de cabeza es el lcd. No hay manera de hacer que muestre algún carácter en pantalla. He leído que es un problema común y que los tiempos de espera son críticos para que funcionen correctamente, pero probe en una protoboard de montar el circuito y a aumentar los delays con muchas combinaciones y no conseguí hacerlo funcionar, ni en modo 4 ni 8 bits. Hice muchísimas pruebas hasta quemar el lcd al cablearlo mal en una de ellas, momento en el cual aparque el hardware para acabar el código hasta ahora que me toca pelearme de nuevo con el. :unsure:

Ayer me llego un lcd nuevo y probé la primera versión de la pcb, pero esta vez acabé quemando el pic.:cry: No sé muy bien que paso, el micro parecía responder ya que la rutina de leds al comienzo se realizaba correctamente, pero no se veía nada en el lcd. Tan solo la primera línea llena de cuadros negros. Al cabo de varias pruebas empezó a oler a quemado, no sé cómo se quemo el pic pero sospecho que fue un corto al dejar algunas patitas de los componentes sin cortar en la parte posterior de la pcb.

En fin, os pego el código del programa junto con el esquemático y layout, a ver si alguien puede hacerme ver la luz al final del túnel. Perdonad si no está muy ordenado. También subo algunas fotos pero no tienen demasiada calidad.

Muchas gracias, un saludo


PHP:
//************************ Directivas para el compilador ***********************

#include <16f876.h>                      //PIC utilizado
#device *=16
#device adc=10
#fuses XT, NOWDT, PUT, NOPROTECT, NOBROWNOUT, NOLVP, NOCPD, NOWRT, NODEBUG//16F876
#use delay (clock=4000000)                 //Oscilador a 4Mhz
//#use delay (clock=20000000)                //Oscilador a 20Mhz
#include "lcd_16F876_delay.h"                   //Libreria LCD con delay
//#include "lcd_16F876.h"                           //Libreria LCD
#include "internal_eeprom.c"

#define rele 56
#define zumbador 57
#define pulsador_menu 42
#define pulsador_enter 43
#define pulsador_menos 44
#define pulsador_mas 45
#define LED1 61
#define LED2 60
#define LED3 59
#define LED4 58

#byte PORTA=0xD80                         //Dirección Puerto A
#byte PORTB=0xD81                         //Dirección Puerto B
#byte PORTC=0xD82                         //Dirección Puerto C
//#use fast_io(a)                           //Optimiza E/S del Puerto A
//#use fast_io(b)                           //Optimiza E/S del Puerto B
//#use fast_io(c)                           //Optimiza E/S del Puerto C

//******************************************************************************
//************************ Definición de funciones *****************************
//******************************************************************************

   void leds(void);
   void lcd_mensaje_inicial(void);
   void lcd_mensaje_secundario(void);
   void termostato (void);
   void termometro (void);
   void crono_termostato (void);
   void tiempo1(void);
   void crono1 (void);
   void crono2 (void);
   void crono3 (void);
   void crono4 (void);
   
//******************************************************************************
//************************* Declaración de constantes:**************************
//******************************************************************************

const char mensaje[]= {   "For UAV construction"}; //Mensaje en movimiento
   
   byte const N_Ints=30;    // Numero de interrupciones para 1 Segundo 4Mhz
//byte const N_Ints=150;     // Numero de interrupciones para 1 Segundo 20Mhz
byte const N_Ints2=500;  // Numero de interrupciones timer #2
   
//******************************************************************************
//*************************** Variables para timer0 ****************************
//******************************************************************************

char C_Ints=0;                         // Contador de Interrupciones ocurridas
char C_Ints2=2;
char Flag=0;                           // Flag que cambia cada NInterrupciones
char K=0;                              // Estado anterior del Flag
unsigned int segundos=00,minutos=00,horas=00; //Variables contador cronómetro
unsigned long int segundos_completos;

//******************************************************************************
//************* Declaración de variables para curvas de temperatura*************
//******************************************************************************
unsigned int modo = 1;
unsigned int16 Time1=5, Time2=5, Time3=5, Time4=50;//Duración de curvas en minutos 
unsigned int8 Td1=20, Td2=40, Td3=20, Td4=5;       //Temperatura deseada curvas

unsigned int temp_calculada;      //Temp deseada en cada momento de la curva       
unsigned int temp_actual;    //Temperatura actual calculada desde el sensor
unsigned int temp_inicio;         //Temperatura al inicio del ciclo      
unsigned int magnitud_rampa;      //Cantidad de grados a aumentar en cada curva
unsigned long int duracion_rampa; //Duracion curva de temperatura en minutos

float Tc = 0.0;  //  Variable en coma flotante para calcular rampa temperatura

int16 valor_sensor; //        Valor descargado del sensor temperatura
   
//******************************************************************************
//********************* Bucle interrupciones (Timer 0)**************************
//******************************************************************************

#int_RTCC                 //  Interrupción por desbordamiento
void RTCC_isr() {         // del TIMER0 RTCC. Usado para reloj

   if(++C_Ints==N_ints){
   C_Ints=0x00;
   ++segundos_completos;
      if(++segundos>59){
      segundos=0;
         if(++minutos>59){
         minutos=0;
            if(++horas>23){
            horas=0;
            }
         }
      }
   }
}

//*****************************************************************************
//********************* Bucle interrupciones (Timer 2)**************************
//******************************************************************************

#int_timer2
void timer2_isr() // TIMER2
{     
set_adc_channel( 0 );     
valor_sensor = Read_ADC();           //Timer 2 usado para leer y actualizar 
temp_actual = (valor_sensor/2); //      temperatura del sensor
}

//******************************************************************************
//*************************** Programa principal *******************************
//******************************************************************************

void main() 
{

   set_tris_A(0x3F);          //Establece puerto como entrada (3F : 6 pines)
   set_tris_B(0x00);          //Establece puerto como salida 
   set_tris_C(0x00);          //Establece puerto como salida
   #use fast_io(a)                           //Optimiza E/S del Puerto A
   #use fast_io(b)                           //Optimiza E/S del Puerto B
   #use fast_io(c)                           //Optimiza E/S del Puerto C


   setup_counters(RTCC_INTERNAL,RTCC_DIV_128); // TIMER0: Clock Interno, Presescaler 128,una RTCC cada 33.3 milisegundos.
   setup_timer_2 (T2_DIV_BY_16, 125, 5); 
   set_timer2 (0);
   enable_interrupts(INT_RTCC);     // Habilito Interrupción RTCC
   enable_interrupts(INT_TIMER2);   // Habilito Interrupción Timer2
   enable_interrupts(global);       // Habilito Interrupciones Globalmente
   setup_adc_ports(AN0);            // Puerto A0 analogico para LM35
   setup_adc( ADC_CLOCK_INTERNAL ); // Reloj interno
   set_adc_channel( 0 );
   delay_us(10);

/*
   write_int16_eeprom (0x00, Time1);//   Almacena en la eeprom interna el
   write_int16_eeprom (0x08, Time2);//    valor definido en las variables
   write_int16_eeprom (0x10, Time3);//        de tiempo y temperatura
   write_int16_eeprom (0x18, Time4);//     Usar para reinicializar eeprom.

   write_eeprom (0x04, Td1);
   write_eeprom (0x0C, Td2);
   write_eeprom (0x14, Td3);
   write_eeprom (0x1C, Td4);
*/
   Time1 = read_int16_eeprom (0x00);   //Cargo variables de tiempo y temperatura
   Td1   = read_eeprom (0x04);         //   con los valores almacenados en 
   Time2 = read_int16_eeprom (0x08);   //     la eeprom interna del PIC
   Td2   = read_eeprom (0x0C);
   Time3 = read_int16_eeprom (0x10);
   Td3   = read_eeprom (0x14);
   Time4 = read_int16_eeprom (0x18);
   Td4   = read_eeprom (0x1C);

//******************************************************************************
//************************ Selección de FUNCIONES: *****************************
//******************************************************************************

   output_low(rele);                                      //Inicializa LCD a mano
   leds ();      //Rutina LEDS
   delay_ms(100);
   lcd_init();Delay_ms(100);                       //Inicializa LCD
   lcd_mensaje_inicial();                          //Mensaje 01
   lcd_mensaje_secundario();
   
while(1)
{
switch(modo)
{
case 1: //modo configuración
While(modo==1)
{
   if(modo==1)
   {
   output_low(LED3);
   termometro();
   }
   if(modo==1)
   { 
   output_low(rele);
   termostato();
   }
   if(modo==1)
   {
   output_low(rele);
   crono_termostato();
   }
}

case 2: //modo ejecucion
   if (modo==2)
   {
   tiempo1();
   }
      else
      {
      modo=1; 
      break;
      }
   if(modo==2)
   {
   output_low(LED3);
   output_low(LED4);
   crono1();
   }
      else
      {
      modo=1; 
      break;
      }
   if(modo==2)
   {
   crono2();   
   }
      else
      {
      modo=1; 
      break;
      }
   if(modo==2)
   {
   crono3();   
   }
      else
      {
      modo=1; 
      break;
      }
   if(modo==2)
   {
   crono4();
   }
      else
      {
      modo=1;
      break;
      }

   default:
   break;
}
}

}
      
//******************************************************************************
//******************************************************************************

//******************************************************************************
//******************************** FUNCIONES: **********************************
//******************************************************************************


void leds (void)                       //Inicialización leds 
{
   int x=0;

   output_high(zumbador);       
   Delay_ms(100);
   output_low(zumbador);
   
      for (x=0; x<7; x++){
         output_high(LED1);
         output_high(LED2);
         output_low (LED3); 
         output_low (LED4);
         delay_ms(300);

         output_low(LED1);
         output_low(LED2);
         output_high (LED3); 
         output_high (LED4);
         delay_ms(300);
         ++x;
         }
         
      output_low (LED3);
      output_low (LED4);
      delay_ms(1000);

}         

void lcd_mensaje_inicial(void)         //Mensaje inicial
{      

   output_high(Zumbador);       
   Delay_ms(100);
   output_low(Zumbador);
   delay_ms(100);
         
   Lcd_putc( "\f");                 //Limpio lcd
   lcd_gotoxy(4,1);
   Lcd_putc ("mi nombre");      
   delay_ms(10);
   lcd_gotoxy(4,2);
   Lcd_putc( "empresa");
   delay_ms(1000);
   Lcd_putc( "\f");                 //Limpio lcd   

}

void lcd_mensaje_secundario (void) {   //Mensaje secundario
         
   output_high(zumbador);       
   delay_ms(100);
   output_low(zumbador);
   delay_ms(300);
         
   lcd_putc( "\f");                 //Limpio lcd
   lcd_gotoxy(1,1);                 
   lcd_putc ("Departamento UAV");    
   delay_ms(10);                  
      
   lcd_gotoxy(1,2);                
   lcd_putc( "Termostato  v.01");    //Escribo...
   delay_ms(2000);                 
   lcd_putc( "\f");                 //Limpio lcd
   delay_ms (300);
}


void termometro (void)
{

output_high(LED1);
modo=2;

Lcd_putc( "\f");                 //Limpio lcd
   do{
      
      lcd_gotoxy(4,1);
      lcd_putc ("Termometro");
      lcd_gotoxy(5,2);
      printf(lcd_putc,"Temp: %02d     "temp_actual);
      if (input(pulsador_menu)){delay_ms(300);modo=1;}
    }
  While(modo==2);
}
void termostato (void){output_low(LED1);output_high(LED2);
Lcd_putc( "\f");                 //Limpio lcd
temp_calculada=temp_actual;
int x=1;
   while(input(pulsador_enter)!=1)
   {
      lcd_gotoxy(4,1);
      printf(lcd_putc,"Termostato");
      lcd_gotoxy(5,2);
      printf(lcd_putc,"Activar?");
      if (input(pulsador_menu)){delay_ms(300);modo=1;return;}
      if (input(pulsador_enter)){modo=1;x=2;}
   }

Lcd_putc( "\f");                 //Limpio lcd
  
   if (x==2)
   output_high(LED4);
      x=1;
      do{
      lcd_gotoxy(1,1);
      printf(lcd_putc,"Temp  actual:%02d          "temp_actual);
      lcd_gotoxy(1,2);
      printf(lcd_putc,"Temp deseada:%02d         "temp_calculada);
      
      if(temp_calculada>temp_actual){output_high(rele);}
      else {output_low(rele);}   
       
      if (input(pulsador_menu)){delay_ms(300);modo=1;return;}
      if (input(pulsador_menos)){--Temp_calculada;}
      if (input(pulsador_mas)){++Temp_calculada;}
   
      }while(input(pulsador_menu)!=1);
      modo=1;
      output_low(LED4);
      return;
   
   }

void crono_termostato (void){
      output_low(LED2);
      output_high(LED3);
      Lcd_putc( "\f");                 //Limpio lc
   do{
      lcd_gotoxy(1,1);
      Lcd_putc ("Crono-termostato");      
      delay_ms(10);
      lcd_gotoxy(5,2);
      Lcd_putc( "Activar?");
      if (input(pulsador_menu)){delay_ms(300);modo=1;return;}
      if (input(pulsador_enter)){modo=2;return;}
      
   }
   While(modo!=2);
}

void tiempo1 (void){
output_high(LED4);
   Lcd_putc( "\f");                 //Limpio lcd
do{
   lcd_gotoxy(1,1);
   printf(lcd_putc,"Time1:%luMinutos         " Time1);   
   lcd_gotoxy(1,2);
   printf(lcd_putc,"Temp :%02d Grados   " Td1); 

   if (input(pulsador_menu)){modo=1; return;}
   if (input(pulsador_menos)){Time1 = Time1-5, write_int16_eeprom (0x00, Time1);}
   if (input(pulsador_mas)){Time1 = Time1+5, write_int16_eeprom (0x00, Time1);}
 }while(input(pulsador_enter)!=1);
  

   Lcd_putc( "\f");                 //Limpio lcd
do{
   lcd_gotoxy(1,1);
   printf(lcd_putc,"Time :%luMinutos         " Time1);   
   lcd_gotoxy(1,2);
   printf(lcd_putc,"Temp1:%02d Grados   " Td1); 
   
   if (input(pulsador_menu)){modo=1; return;}
   if (input(pulsador_enter)){delay_ms(50);break;}
   if (input(pulsador_menos)){Td1--, write_eeprom (0x04, Td1);}
   if (input(pulsador_mas)){Td1++, write_eeprom (0x04, Td1);}
  
 }while(input(pulsador_enter)!=1);
  

   Lcd_putc( "\f");                 //Limpio lcd
do{
   lcd_gotoxy(1,1);
   printf(lcd_putc,"Time2:%luMinutos         " Time2);   
   lcd_gotoxy(1,2);
   printf(lcd_putc,"Temp :%02d Grados   " Td2); 
   
   if (input(pulsador_menu)){modo=1; return;}
   if (input(pulsador_enter)){delay_ms(50);break;}
   if (input(pulsador_menos)){Time2=Time2-5, write_int16_eeprom (0x08, Time2);}
   if (input(pulsador_mas)){Time2=Time2+5, write_int16_eeprom (0x08, Time2);}

 }while(input(pulsador_enter)!=1);
  

   Lcd_putc( "\f");                 //Limpio lcd
do{
   lcd_gotoxy(1,1);
   printf(lcd_putc,"Time :%luMinutos         " Time2);   
   lcd_gotoxy(1,2);
   printf(lcd_putc,"Temp2:%02d Grados   " Td2); 
   
   if (input(pulsador_menu)){modo=1; return;}
   if (input(pulsador_enter)){delay_ms(50);break;}
   if (input(pulsador_menos)){Td2--, write_eeprom (0x0C, Td2);}
   if (input(pulsador_mas)){Td2++, write_eeprom (0x0C, Td2);}

 }while(input(pulsador_enter)!=1);
  

   Lcd_putc( "\f");                 //Limpio lcd
do{
   lcd_gotoxy(1,1);
   printf(lcd_putc,"Time3:%luMinutos         " Time3);   
   lcd_gotoxy(1,2);
   printf(lcd_putc,"Temp :%02d Grados   " Td3); 

   if (input(pulsador_menu)){modo=1; return;}
   if (input(pulsador_enter)){delay_ms(50);break;}
   if (input(pulsador_menos)){Time3=Time3-5, write_int16_eeprom (0x10, Time3);}
   if (input(pulsador_mas)){Time3=Time3+5, write_int16_eeprom (0x10, Time3);}

 }while(input(pulsador_enter)!=1);
  

   Lcd_putc( "\f");                 //Limpio lcd
do{
   lcd_gotoxy(1,1);
   printf(lcd_putc,"Time :%luMinutos         " Time3);   
   lcd_gotoxy(1,2);
   printf(lcd_putc,"Temp3:%02d Grados   " Td3); 

   if (input(pulsador_menu)){modo=1; return;}
   if (input(pulsador_enter)){delay_ms(50);break;}
   if (input(pulsador_menos)){Td3--, write_eeprom (0x14, Td3);}
   if (input(pulsador_mas)){Td3++, write_eeprom (0x14, Td3);}

 }while(input(pulsador_enter)!=1);

   Lcd_putc( "\f");                 //Limpio lcd
do{
   lcd_gotoxy(1,1);
   printf(lcd_putc,"Time4:%luMinutos         " Time4);   
   lcd_gotoxy(1,2);
   printf(lcd_putc,"Temp :%02d Grados   " Td4); 

   if (input(pulsador_menu)){modo=1; return;}
   if (input(pulsador_enter)){delay_ms(50);break;}
   if (input(pulsador_menos)){Time4=Time4-5, write_int16_eeprom (0x18, Time4);}
   if (input(pulsador_mas)){Time4=Time4+5, write_int16_eeprom (0x18, Time4);}

 }while(input(pulsador_enter)!=1);
  

   Lcd_putc( "\f");                 //Limpio lcd
do{
   lcd_gotoxy(1,1);
   printf(lcd_putc,"Time :%luMinutos         " Time4);   
   lcd_gotoxy(1,2);
   printf(lcd_putc,"Temp4:%02d Grados   " Td4); 

   if (input(pulsador_menu)){modo=1; return;}
   if (input(pulsador_menu)){delay_ms(50);break;}
   if (input(pulsador_menos)){Td4--, write_eeprom (0x1C, Td4);}
   if (input(pulsador_mas)){Td4++, write_eeprom (0x1C, Td4);}
   
 }while(input(pulsador_enter)!=1);
  modo=2;break;
}

void crono1 (void){

minutos = 0;
segundos = 0;
segundos_completos =0;
temp_inicio=temp_actual;  //Temperatura al inicio del ciclo   
output_low(LED3);
output_high(LED1);
Lcd_putc( "\f");                 //Limpio lcd

While(segundos_completos<=Time1*60)
{
   If(Td1>=temp_inicio)
   {
      magnitud_rampa = (float)Td1 - temp_inicio;//total de grados a aumentar
      duracion_rampa = Time1*60;                //Duracion rampa 1 en segundos
      float Dv1;
      Dv1=(float)Magnitud_rampa/Duracion_rampa; // Dv1 = Division1
      Tc=0;
      Tc = (float)Dv1*segundos_completos;
      temp_calculada = (float) Tc + temp_inicio;
      lcd_gotoxy(1,1);
      printf(lcd_putc,"Temp:%02d %02d:%02d:%02d     "temp_actual,horas,minutos,segundos);   
      lcd_gotoxy(1,2);
      printf(lcd_putc,"Calc:%02d C1:Td.%02d      "temp_calculada,Td1);
      if(segundos>=59){Lcd_putc( "\f");}
      if(minutos>=59){Lcd_putc( "\f");}
      if(horas>=23){Lcd_putc( "\f");}

      if(temp_calculada>temp_actual){output_high(rele);}
      else {output_low(rele);}
      if (input(pulsador_menu)){modo=1;return;}
      if (input(pulsador_enter)){break;}
      if (input(pulsador_menos)){if(Td1>01){--Td1;}}
      if (input(pulsador_mas)){if(Td1<99){++Td1;}}
   }

   Else If(Td1<=temp_inicio){
      
         magnitud_rampa = (float) temp_inicio - Td1;//total de grados a disminuir
         duracion_rampa = Time1*60;                 //Duracion rampa 1 en segundos
         float Dv1;
         Dv1=(float)Magnitud_rampa/Duracion_rampa; // Dv1 = Division1
         Tc = (float)Dv1*segundos_completos;
         temp_calculada = (float) temp_inicio - Tc;
         lcd_gotoxy(1,1);
         printf(lcd_putc,"Temp:%02d %02d:%02d:%02d     "temp_actual,horas,minutos,segundos);     
         lcd_gotoxy(1,2);
         printf(lcd_putc,"Calc:%02d C1:Td.%02d      "temp_calculada,Td1);

         if(segundos>=59){Lcd_putc( "\f");         }
            if(minutos>=59){Lcd_putc( "\f");            }
               if(horas>=23){Lcd_putc( "\f");               }
   
   if (input(pulsador_menu)){termometro();}
       if(temp_calculada>temp_actual){output_high(rele);}
       else {output_low(rele);}    
      
   if (input(pulsador_menu)){modo=1;return;}
   if (input(pulsador_enter)){break;}
   if (input(pulsador_menos)){if(Td1>01){--Td1;}}
   if (input(pulsador_mas)){if(Td1<99){++Td1;}}
   }
   }
}

void crono2 (void){

output_low(LED1);
output_high(LED2);
Segundos_completos=0;
While(segundos_completos<=Time2*60){

   If(Td2>=Td1)
   {
   magnitud_rampa = (float)Td2 - Td1;      //Cantidad total de grados a aumentar
   duracion_rampa = Time2*60;     
   float Dv1;
   Tc=0;
   Dv1=(float)Magnitud_rampa/Duracion_rampa; // Dv1 = Division1
   //Tc=(float) Tc + Td1;
   Tc = (float)Dv1*segundos_completos;
   temp_calculada = (float) Tc + Td1;

   lcd_gotoxy(1,1);
   printf(lcd_putc,"Temp:%02d %02d:%02d:%02d     "temp_actual,horas,minutos,segundos);     
   lcd_gotoxy(1,2);
   printf(lcd_putc,"Calc:%02d C2 Td.%02d      "temp_calculada,Td2);
   if(segundos>=59){Lcd_putc( "\f");}
   if(minutos>=59){Lcd_putc( "\f");}
   if(horas>=23){Lcd_putc( "\f");}
 
   if(temp_calculada>temp_actual){output_high(rele);}
   else {output_low(rele);}
      if (input(pulsador_menu)){modo=1;return;}
   if (input(pulsador_enter)){break;}
   if (input(pulsador_menos)){if(Td2>01){--Td2;}}
   if (input(pulsador_mas)){if(Td2<99){++Td2;}}
   }

   Else If(Td2<=Td1)
   {
      magnitud_rampa = (float) Td1-Td2;   //Cantidad total de grados a disminuir
      duracion_rampa = Time2*60;     
      float Dv1 = 1.0;
      Dv1=(float)Magnitud_rampa/Duracion_rampa; // Dv1 = Division1
      Tc = (float)Dv1*segundos_completos;
      temp_calculada = (float) Td1-Tc;

      lcd_gotoxy(1,1);
      printf(lcd_putc,"Temp:%02d %02d:%02d:%02d     "temp_actual,horas,minutos,segundos);     
      lcd_gotoxy(1,2);
      printf(lcd_putc,"Calc:%02d C2 Td.%02d      "temp_calculada,Td2);
      if(segundos>=59){Lcd_putc( "\f");}
      if(minutos>=59){Lcd_putc( "\f");}
      if(horas>=23){Lcd_putc( "\f");}
      
      if(temp_calculada>temp_actual){output_high(rele);}
      else {output_low(rele);}
      if (input(pulsador_menu)){modo=1;return;}
      if (input(pulsador_enter)){break;}
      if (input(pulsador_menos)){if(Td2>01){--Td2;}}
      if (input(pulsador_mas)){if(Td2<99){++Td2;}}
   }

}
}

void crono3 (void){

output_low(LED2);
output_high(LED3);

Segundos_completos=0;

While(segundos_completos<Time3*60){
   If(Td3>=Td2)
   {
      magnitud_rampa = (float)Td3 - Td2;  //Cantidad total de grados a aumentar
      duracion_rampa = Time3*60;     
      float Dv1;
      Dv1=(float)Magnitud_rampa/Duracion_rampa; //     Dv1 = Division1
      Tc = (float)Dv1*segundos_completos;
      temp_calculada = (float) Tc + Td2;
      lcd_gotoxy(1,1);
      printf(lcd_putc,"Temp:%02d %02d:%02d:%02d     "temp_actual,horas,minutos,segundos);     
      lcd_gotoxy(1,2);
      printf(lcd_putc,"Calc:%02d C3 Td.%02d      "temp_calculada,Td3);
      if(segundos>=59){Lcd_putc( "\f");}
      if(minutos>=59){Lcd_putc( "\f");}
      if(horas>=23){Lcd_putc( "\f");}
      if(temp_calculada>temp_actual){output_high(rele);}
         else {output_low(rele);}
      if (input(pulsador_menu)){modo=1;return;}
      if (input(pulsador_enter)){break;}
      if (input(pulsador_menos)){if(Td3>01){--Td3;}}
      if (input(pulsador_mas)){if(Td3<99){++Td3;}}
   }

   Else If(Td3<=Td2)
   {
      magnitud_rampa = (float) Td2-Td3;   //Cantidad total de grados a disminuir
      duracion_rampa = Time3*60;     
      float Dv1 = 1.0;
      Dv1=(float)Magnitud_rampa/Duracion_rampa; //     Dv1 = Division1
      Tc = (float)Dv1*segundos_completos;
      temp_calculada = (float) Td2-Tc;
      lcd_gotoxy(1,1);
      printf(lcd_putc,"Temp:%02d %02d:%02d:%02d     "temp_actual,horas,minutos,segundos);     
      lcd_gotoxy(1,2);
      printf(lcd_putc,"Calc:%02d C3 Td.%02d      "temp_calculada,Td3);
      if(segundos>=59){Lcd_putc( "\f");}
      if(minutos>=59){Lcd_putc( "\f");}
      if(horas>=23){Lcd_putc( "\f");}            
      if(temp_calculada>temp_actual){output_high(rele);}
         else {output_low(rele);}
      if (input(pulsador_menu)){modo=1;return;}      
      if (input(pulsador_enter)){break;}
      if (input(pulsador_menos)){if(Td3>01){--Td3;}}
      if (input(pulsador_mas)){if(Td3<99){++Td3;}}
   }
}
}

void crono4 (void){

output_low(LED3);
output_high(LED4);

Segundos_completos=0;
   
   While(segundos_completos<Time4*60)
   {
      If(Td4>=Td3)
      {
      magnitud_rampa = (float)Td4 - Td3;  //Cantidad total de grados a aumentar
      duracion_rampa = Time4*60;     
      float Dv1;
      Dv1=(float)Magnitud_rampa/Duracion_rampa; //     Dv1 = Division1
      Tc = (float)Dv1*segundos_completos;
      temp_calculada = (float) Tc + Td3;
      lcd_gotoxy(1,1);
      printf(lcd_putc,"Temp:%02d %02d:%02d:%02d     "temp_actual,horas,minutos,segundos);     
      lcd_gotoxy(1,2);
      printf(lcd_putc,"Calc:%02d C4 Td.%02d      "temp_calculada,Td4);
      if(segundos>=59){Lcd_putc( "\f");}
      if(minutos>=59){Lcd_putc( "\f");}
      if(horas>=24){Lcd_putc( "\f");}
      
      if(temp_calculada>temp_actual){output_high(rele);}
      else {output_low(rele);}
      if (input(pulsador_enter)){break;}
      if (input(pulsador_menu)){modo=1;break;}
      if (input(pulsador_menos)){if(Td4>01){--Td4;}}
      if (input(pulsador_mas)){if(Td4<99){++Td4;}}
      }
      Else If(Td4<=Td3)
      {
      magnitud_rampa = (float) Td3-Td4;  //Cantidad total de grados a disminuir
      duracion_rampa = Time4*60;     
      float Dv1 = 1.0;
      Dv1=(float)Magnitud_rampa/Duracion_rampa; //     Dv1 = Division1
      Tc = (float)Dv1*segundos_completos;
      temp_calculada = (float) Td3-Tc;

      lcd_gotoxy(1,1);
      printf(lcd_putc,"Temp:%02d %02d:%02d:%02d     "temp_actual,horas,minutos,segundos);     
      lcd_gotoxy(1,2);
      printf(lcd_putc,"Calc:%02d C4 Td.%02d      "temp_calculada,Td4);
      if(segundos>=59){Lcd_putc( "\f");}
      if(minutos>=59){Lcd_putc( "\f");}
      if(horas>=23){Lcd_putc( "\f");}

      if(temp_calculada>temp_actual){output_high(rele);}
      else {output_low(rele);}
      if (input(pulsador_menu)){modo=1;break;}
      if (input(pulsador_enter)){break;}
      if (input(pulsador_menos)){if(Td4>01){--Td4;}}
      if (input(pulsador_mas)){if(Td4<99){++Td4;}}
      }
   }

output_low(rele);
minutos = 0;
segundos = 0;
segundos_completos =0;
int Temp_end;
Temp_end=temp_actual;
Lcd_putc( "\f");
Output_low(LED4);
Segundos_completos=0;
   While(TRUE)
   {
      lcd_gotoxy(1,1);
      printf(lcd_putc,"Fin %02d:%02d:%02d %02dc      "horas,minutos,segundos,Temp_end);     
      lcd_gotoxy(5,2);
      printf(lcd_putc,"Deseada: %02dc         "Td4);
      if (input(pulsador_menu)){modo=1;break;}
      

   }

}

//******************************************************************************
//***************************** FIN DE PROGRAMA ********************************
//******************************************************************************

Olvidaba los adjuntos
 

Adjuntos

  • IMG_0271.JPG
    IMG_0271.JPG
    145.2 KB · Visitas: 53
  • IMG_0274.JPG
    IMG_0274.JPG
    175.2 KB · Visitas: 28
  • 16F876 - Proteus.rar
    23.3 KB · Visitas: 66
Última edición por un moderador:
Hola,
tengo una version de proteus distinta al tuyo por lo tanto no puedo abrir el archivo que pusiste, podrias exportar el circuito como grafico y ponerlo para poder ver el circuito.
Ademas podrias poner el programa completo con los include incluidos, sino, no lo puedo probar.

Saludos
 
Aqui tienes:

Libreria original ccs:

Código:
#bit lcd_enable = 7.7
//#bit lcd_rw = 7.1 //Desabilitar para poner a masa RW
#bit lcd_rs = 7.6
#byte lcd_a = 7 //portc
#byte lcd_b = 6 //portb


#define LCD_LINEA2 0x40 // Direccion de memoria para la segunda linea
#define LCD_DATO 1
#define LCD_COMANDO 0

#define LCD_CLEAR 0x01
#define LCD_HOME 0x02

#define LCD_DISPLAY_OFF 0x08
#define LCD_DISPLAY_ON 0x0f
#define LCD_CURSOR_ON 0x0E
#define LCD_CURSOR_BLINK 0x0F

#define LCD_CURSOR_SHIFT_RIGHT 0x10
#define LCD_CURSOR_SHIFT_LEFT 0x14
#define LCD_DISPLAY_SHIFT_RIGHT 0x18
#define LCD_DISPLAY_SHIFT_LEFT 0x1C


int lcd_leer()
{
int valor;

//set_tris_c(0x00);
set_tris_b(0xFF);

//lcd_rw = 1;
delay_ms(5);
lcd_enable = 1;
delay_ms(5);
valor = lcd_b;
delay_ms (5);
lcd_enable = 0;
delay_ms (5);

set_tris_b(0x00);
delay_ms (5);
return valor;
}


void lcd_enviar(int dir, int valor)
{
//set_tris_c(0x00);
//set_tris_b(0x00);

lcd_rs = 0;
while( bit_test(lcd_leer(),7) );
lcd_rs = dir;


//lcd_rw = 0;
delay_ms(10);
lcd_enable = 0;
lcd_b = valor;
delay_ms(10);
lcd_enable = 1;
delay_ms(50);
lcd_enable = 0;
delay_ms(10);
}


void lcd_init()
{
int i;
delay_ms (40);
set_tris_c(0x00);
set_tris_b(0x00);

lcd_enable = 0;
delay_ms(1);
//lcd_rw = 0;
lcd_rs = 0;
delay_ms(40);


for(i=0; i<3; i++)
{
lcd_enviar(LCD_COMANDO,0x38);
delay_ms(25);
lcd_enviar(LCD_COMANDO,LCD_DISPLAY_ON);
delay_ms(25);
lcd_enviar(LCD_COMANDO,0x06);
delay_ms(25);
lcd_enviar(LCD_COMANDO,LCD_CLEAR);
delay_ms(25);
lcd_enviar(LCD_COMANDO,LCD_HOME);
delay_ms(400);
}
}

void lcd_gotoxy( byte x, byte y) {
byte dir;

if(y!=1)
dir=LCD_LINEA2;
else
dir=0;
dir+=x-1;
lcd_enviar(LCD_COMANDO,0x80|dir);
delay_ms(50);
}


void lcd_putc( char c) {switch (c) {
case '\f' : lcd_enviar(LCD_COMANDO,0x01);
delay_ms(50);
break;
case '\n' : lcd_gotoxy(1,2); break;
delay_ms(50);
case '\b' : lcd_enviar(LCD_COMANDO,0x10); break;
delay_ms(50);
default : lcd_enviar(LCD_DATO,c); break;

delay_ms(500);
}
}

Esta es la versión con delays, le he aumentado de manera significativa todos los que había y incluso añadido alguno adicional. Va tan lenta que en la simulación se muestran los caracteres uno a uno aun así en el hardware no funciona.

Código:
 #bit lcd_enable = 7.7
//#bit lcd_rw = 7.1 //Desabilitar para poner a masa RW
#bit lcd_rs = 7.6
#byte lcd_a = 7 //portc
#byte lcd_b = 6 //portb


#define LCD_LINEA2 0x40 // Direccion de memoria para la segunda linea
#define LCD_DATO 1
#define LCD_COMANDO 0

#define LCD_CLEAR 0x01
#define LCD_HOME 0x02

#define LCD_DISPLAY_OFF 0x08
#define LCD_DISPLAY_ON 0x0C
#define LCD_CURSOR_ON 0x0E
#define LCD_CURSOR_BLINK 0x0F

#define LCD_CURSOR_SHIFT_RIGHT 0x10
#define LCD_CURSOR_SHIFT_LEFT 0x14
#define LCD_DISPLAY_SHIFT_RIGHT 0x18
#define LCD_DISPLAY_SHIFT_LEFT 0x1C


int lcd_leer()
{
int valor;

set_tris_c(0x00);
set_tris_b(0xFF);

//lcd_rw = 1;
delay_us(150);
lcd_enable = 1;
delay_us(100);
valor = lcd_b;
delay_us (50);
lcd_enable = 0;
delay_us (50);

set_tris_b(0x00);
delay_us (50);
return valor;
}


void lcd_enviar(int dir, int valor)
{
set_tris_c(0x00);
set_tris_b(0x00);

lcd_rs = 0;
while( bit_test(lcd_leer(),7) );
lcd_rs = dir;


//lcd_rw = 0;
delay_ms(1);
lcd_enable = 0;
lcd_b = valor;
delay_ms(1);
lcd_enable = 1;
delay_ms(1);
lcd_enable = 0;
delay_ms(1);
}


void lcd_init()
{
int i;
delay_ms (40);
set_tris_c(0x00);
set_tris_b(0x00);

lcd_enable = 0;
delay_ms(1);
//lcd_rw = 0;
lcd_rs = 0;
delay_ms(40);


for(i=0; i<3; i++)
{
lcd_enviar(LCD_COMANDO,0x38);
delay_ms(25);
}
lcd_enviar(LCD_COMANDO,LCD_DISPLAY_ON);
delay_ms(1);
lcd_enviar(LCD_COMANDO,0x06);
delay_ms(1);
lcd_enviar(LCD_COMANDO,LCD_CLEAR);
delay_ms(1);
lcd_enviar(LCD_COMANDO,LCD_HOME);
delay_ms(1);
}


void lcd_gotoxy( byte x, byte y) {
byte dir;

if(y!=1)
dir=LCD_LINEA2;
else
dir=0;
dir+=x-1;
lcd_enviar(LCD_COMANDO,0x80|dir);
delay_ms(5);
}


void lcd_putc( char c) {
switch (c) {
case '\f' : lcd_enviar(LCD_COMANDO,0x01);
delay_ms(50);
break;
case '\n' : lcd_gotoxy(1,2); break;
case '\b' : lcd_enviar(LCD_COMANDO,0x10); break;
default : lcd_enviar(LCD_DATO,c); break;
}
}

Y la librería para trabjar con la eeprom:

PHP:
#ifndef INTERNAL_EEPROM_UTILITIES
#define INTERNAL_EEPROM_UTILITIES

// Used to adjust the address range
#ifndef INT_EEPROM_ADDRESS
#define INT_EEPROM_ADDRESS  int8
#endif

////////////////////////////////////////////////////////////////////////////////
//// Internal EEPROM Functions
////////////////////////////////////////////////////////////////////////////////

// Purpose:    Write one bit to internal eeprom
// Inputs:     1) An eeprom address
//             2) The bit position (LSB == 0)
//             3) The bit to write
// Outputs:    None
void write_int1_eeprom(INT_EEPROM_ADDRESS address, int8 bitPosition, int1 data)
{
   int8 stored_data;

   stored_data = read_eeprom(address);

   if(data)
   {
      bit_set(stored_data, bitPosition);
   }
   else
   {
      bit_clear(stored_data, bitPosition);
   }

   write_eeprom(address, stored_data);
}


// Purpose:    Read one bit from internal eeprom
// Inputs:     1) An eeprom address
//             2) The bit position (LSB == 0)
// Outputs:    The bit read from internal eeprom
int1 read_int1_eeprom(INT_EEPROM_ADDRESS address, int8 bitPosition)
{
   return bit_test(read_eeprom(address), bitPosition);
}


// Purpose:    Write a 16 bit number to internal eeprom
// Inputs:     1) An eeprom address
//             2) The 16 bit number to write to internal eeprom
// Outputs:    None
void write_int16_eeprom(INT_EEPROM_ADDRESS address, int16 data)
{
   int8 i;

   for(i = 0; i < 2; ++i)
   {
     write_eeprom(address + i, *((int8 *)(&data) + i));
   }
}


// Purpose:    Read a 16 bit number from internal eeprom
// Inputs:     An eeprom address
// Outputs:    The 16 bit number read from internal eeprom
int16 read_int16_eeprom(INT_EEPROM_ADDRESS address)
{
   int8  i;
   int16 data;

   for(i = 0; i < 2; ++i)
   {
     *((int8 *)(&data) + i) = read_eeprom(address + i);
   }

   return(data);
}


// Purpose:    Write a 32 bit integer to internal eeprom
// Inputs:     1) An eeprom address
//             2) The 32 bit number to write to internal eeprom
// Outputs:    None
void write_int32_eeprom(INT_EEPROM_ADDRESS address, int32 data)
{
   int8 i;

   for(i = 0; i < 4; ++i)
   {
     write_eeprom(address + i, *((int8 *)(&data) + i));
   }
}


// Purpose:    Read a 32 bit integer from internal eeprom
// Inputs:     An eeprom address
// Outputs:    The 32 bit integer read from internal eeprom
int32 read_int32_eeprom(INT_EEPROM_ADDRESS address)
{
   int8  i;
   int32 data;

   for(i = 0; i < 4; ++i)
   {
     *((int8 *)(&data) + i) = read_eeprom(address + i);
   }

   return data;
}


// Purpose:    Write a floating point number to internal eeprom
// Inputs:     1) An eeprom address. Four eeprom locations will be used.
//             2) The floating point number to write to internal eeprom
// Outputs:    None
void write_float_eeprom(INT_EEPROM_ADDRESS address, float data)
{
   int8 i;

   for(i = 0; i < 4; ++i)
   {
     write_eeprom(address + i, *((int8 *)(&data) + i));
   }
}


// Purpose:    Read a floating point number from internal eeprom
// Inputs:     An eeprom address
// Outputs:    The floating point number read from the internal eeprom
float read_float_eeprom(INT_EEPROM_ADDRESS address)
{
   int8 i;
   float data;

   for(i = 0; i < 4; ++i)
   {
     *((int8 *)(&data) + i) = read_eeprom(address + i);
   }

   return data;
}

#endif

Por último el esquemático:
 

Adjuntos

  • Esquemático en JPG.rar
    339.3 KB · Visitas: 33
Última edición:
Hola, simule el lcd en proteus y funciona bien, en esta parte no deberias tener problemas.
Te muestro una imagen para que veas.


esta probado con el codigo original de ccs.
 
Bueno, revisa todas las tensiones del micro la vdd y la mclr y trata de ver si oscila y tambien la del lcd talvez haya alguna soldadura o conexion que no esta bien

Fijate si las conexiones RS E y RW se conectan como dice el esquema, no puedo identificar bien estas conexiones con las fotos del impreso.
 
Última edición:
El programa creo que corre bien en el micro. Esto lo se porque he añadido en diferentes partes del programa la orden de encender un led y funciona. El oscilador también está funcionando y las tensiones son correctas, medido con osciloscopio. Por cierto en el esquemático hay un error, a mclr en realidad le tengo puesta una R de 10k a 5v.

Estoy convencido de que es problema de código, por lo que he leído sospecho de la librería. El pcb que he construido coincide con el esquemático de proteus y las conexiones están todas correctas. También probé de hacer funcionar el lcd con un 16f84 en una protoboard y tuve el mismo problema.

Saludos

Las conexiones RS, RW y E están bien, las tengo tal y como lo has simulado en proteus.
 
Última edición:
Hola

Ya tengo un PIC para sustituir al que se quemó pero estoy probandolo y no hay manera de hacer que funcione en la placa.. Estoy bastante desesperado :enfadado: He invertido ya cientos de horas en esto y me encuentro parado por culpa del maldito LCD.

Esta mañana hice un pequeño programita que mostrase algo en la pantalla sin mas parafernalia, para simplificar todo al máximo y tampoco me funciona.

Ricber ¿pudiste mirar lo de las librerías? Agradecería mucho si alguien tiene una que funcione o me puede encaminar hacia una solución..

Muchras gracias
Saludos,
 
Perdona que te prometi lo de las librerias, se me olvido, las estoy viendo ahora pero son para c18 que es el compilador de microchip para la serie 18F....

Podria hacer el fin de semana una prueba en mi placa de pruebas, pero tiene otro micro
asi que si el codigo se adapta hago una prueba
 
Última edición:
Muchas gracias ricber, de todos modos....

YA FUNCIONA!! :aplauso::aplauso::aplauso::aplauso::aplauso::aplauso:

Estoy super contento!! (y)

Cambié de librería, he puesto la flex_lcd. Ya la había probado y no me fue bien, pero tras aumentarle un poco los delay funciono!! Llevo meses y muchas horas para hacer andar el lcd, ya estaba desesperado hasta el punto de creer que no iba a conseguirlo :enfadado: De todos modos he aprendido bastante en el proceso así que no es todo malo.

Moraleja, alejarse de la librería del CCS!!! Solo funciona en proteus por algún motivo. Sospecho que puede ser por tener la linea RW a masa o por no respetar el orden de pines indicado en la misma aunque la verdad no lo sé, ni me importa. No la quiero ver mas! jajaja

Ahora a arreglar varios bugs que han aparecido, ajustar los filtros RC y añadir algun delay antes de construir la PCB definitiva ;)

Un saludo
 
Atrás
Arriba