Autor Tema: 16F877 con DS1307, SHT75 y 24LC256, no encuentro el error  (Leído 4179 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado kenniata

  • PIC10
  • *
  • Mensajes: 12
16F877 con DS1307, SHT75 y 24LC256, no encuentro el error
« en: 08 de Septiembre de 2009, 10:19:03 »
Buenas a todos,

Estoy haciendo una tarjeta para un amigo para controlar una especie de invernadero. La temperatura y la humedad la captura con un SHT75. Tengo puesto un reloj DS1307 y una eeprom 24LC256 para guardar unos parametros. La idea es activar y desactivar unos relés en función de la hora, temperatura y humedad detectada. El problema es que el código no me arranca de ninguna manera. Antes, cuando quitaba la interrupción de RDA, en protoboard me funcionaba. Esta tarjeta a funcionado, este fin de semana me pase horas con ella, y cambie algo en el código que dejó de funcionar. Espero que alguien me pueda ayudar.
Muchas gracias de antemano

Código: [Seleccionar]
#include <16F877.h>
#FUSES NOWDT, XT, NOPUT, NOPROTECT, NOBROWNOUT, NOLVP
#use delay(clock=4000000)
#define num 10
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8, stream=pc)
#use i2c(Master,sda=PIN_C4,scl=PIN_C3)


#include <DS1307.C>  //Driver reloj
#include <LCD420.C>  //driver lcd 4x20
#include <sht75.c>  //sensor temp & hum
#include <24256.c>   //driver eeprom 256

float restemp, truehumid;
char C_Ints=0;                         
char Flag=0;                           
char k, keys[num];
int hora_inicio, hora_final,i;
byte const NInts=15;

#int_RTCC
void  RTCC_isr(void)
{
    if(C_Ints > NInts)  // Si las ints ocurridas > ints para 0.5 Seg.
    {                 

    if(Flag==0){
      Flag=1;
    }
    else{
      Flag=0;
    }
    C_Ints=0;                          // Reinicializo Contador de Ints
  }
  ++C_Ints; 
}

#int_RDA
void  RDA_isr(void)
{
   if(kbhit(pc))
    {
      gets(keys);
      switch (keys[0])
      {
         case 'H':
           ds1307_set_date_time(keys[3],keys[4],keys[5],1,keys[1],keys[2],0);
            break;
         case 'L':
           hora_inicio=keys[1];
           hora_final=keys[2];
           fprintf(pc,"%d-%d",hora_inicio,hora_final);
           break;
         default:
            break;
      }
    }
}

void main()

  int aux;
  BYTE sec;
  BYTE min;
  BYTE hrs;
  BYTE day;
  BYTE month;
  BYTE yr;
  BYTE dow;

   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_128);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);

   

   // INICIALIZACIÓN DE LOS DISPOSITIVOS
   lcd_init();
   ds1307_init();
   sht_init();
   
   enable_interrupts(INT_RTCC);
   enable_interrupts(INT_RDA);
   enable_interrupts(GLOBAL);
   init_ext_eeprom();
   
   
   if (read_ext_eeprom(0)!=2)
   {
    ds1307_set_date_time(8,9,9,5,9,54,0);
    write_ext_eeprom(0,2);
   }
   
   while(1)
   {
    if(Flag==K){}
    else
    {
       sht_rd (restemp, truehumid);
       delay_ms(1);
       ds1307_get_date(day,month,yr,dow);
       delay_ms(1);
       ds1307_get_time(hrs,min,sec);
       delay_ms(1);
       lcd_gotoxy(1,1);
       printf(lcd_putc, "Temp : %3.1f %cC   ", restemp, 223);
       lcd_gotoxy(1,2);
       printf(lcd_putc, "RH   : %3.1f %%   ", truehumid);
       lcd_gotoxy(1,3);
       printf(lcd_putc,"\%02d/\%02d/\%02d",day,month,yr);
       lcd_gotoxy(1,4);
       printf(lcd_putc,"\%02d:\%02d:\%02d", hrs,min,sec);
       
    k=Flag;                                // Guardo estado anterior de Flag
    }
   }
}

Código: [Seleccionar]
///////////////////////////////////////////////////////////////////////////////
//                                                                           //
// Driver file for SHT75 Temperature & Humidity Sensor                       //
//                                                                           //
// ***** To initialise SHT75 sensor upon power up *****                      //
//                                                                           //
// Function : sht_init()                                                     //
// Return   : none                                                           //
//                                                                           //
//                                                                           //
// ***** To measure and caluculate SHT75 temp & real RH *****                //
//                                                                           //
// Function : sht_rd (temp, truehumid)                                       //
// Return   : temperature & true humidity in float values                    //
//                                                                           //
///////////////////////////////////////////////////////////////////////////////

#define sht_data_pin   PIN_D3
#define sht_clk_pin    PIN_C4


//***** Function to alert SHT75 *****

void comstart (void)
{
 output_float(sht_data_pin);  //data high
 output_bit(sht_clk_pin, 0);  //clk low
 delay_us(1);
 output_bit(sht_clk_pin, 1);  //clk high
 delay_us(1);
 output_bit(sht_data_pin, 0); //data low
 delay_us(1);
 output_bit(sht_clk_pin, 0);  //clk low
 delay_us(2);
 output_bit(sht_clk_pin, 1);  //clk high
 delay_us(1);
 output_float(sht_data_pin);  //data high
 delay_us(1);
 output_bit(sht_clk_pin, 0);  //clk low
}


//***** Function to write data to SHT75 *****

int1 comwrite (int8 iobyte)
{
 int8 i, mask = 0x80;
 int1 ack;

 //Shift out command
 delay_us(4);
 for(i=0; i<8; i++)
  {
   output_bit(sht_clk_pin, 0);                          //clk low
   if((iobyte & mask) > 0) output_float(sht_data_pin);  //data high if MSB high
   else output_bit(sht_data_pin, 0);                    //data low if MSB low
   delay_us(1);
   output_bit(sht_clk_pin, 1);                          //clk high
   delay_us(1);
   mask = mask >> 1;                                    //shift to next bit
  }

 //Shift in ack
 output_bit(sht_clk_pin, 0);  //clk low
 delay_us(1);
 ack = input(sht_data_pin);   //get ack bit
 output_bit(sht_clk_pin, 1);  //clk high
 delay_us(1);
 output_bit(sht_clk_pin, 0);  //clk low
 return(ack);
}


//***** Function to read data from SHT75 *****

int16 comread (void)
{
 int8 i;
 int16 iobyte = 0;
 const int16 mask0 = 0x0000;
 const int16 mask1 = 0x0001;

 //shift in MSB data
 for(i=0; i<8; i++)
  {
   iobyte = iobyte << 1;
   output_bit(sht_clk_pin, 1);                //clk high
   delay_us(1);
   if (input(sht_data_pin)) iobyte |= mask1;  //shift in data bit
   else iobyte |= mask0;
   output_bit(sht_clk_pin, 0);                //clk low
   delay_us(1);
  }

 //send ack 0 bit
 output_bit(sht_data_pin, 0); //data low
 delay_us(1);
 output_bit(sht_clk_pin, 1);  //clk high
 delay_us(2);
 output_bit(sht_clk_pin, 0);  //clk low
 delay_us(1);
 output_float(sht_data_pin);  //data high

 //shift in LSB data
 for(i=0; i<8; i++)
  {
   iobyte = iobyte << 1;
   output_bit(sht_clk_pin, 1);                //clk high
   delay_us(1);
   if (input(sht_data_pin)) iobyte |= mask1;  //shift in data bit
   else iobyte |= mask0;
   output_bit(sht_clk_pin, 0);                //clk low
   delay_us(1);
  }

 //send ack 1 bit
 output_float(sht_data_pin);  //data high
 delay_us(1);
 output_bit(sht_clk_pin, 1);  //clk high
 delay_us(2);
 output_bit(sht_clk_pin, 0);  //clk low

 return(iobyte);
}


//***** Function to wait for SHT75 reading *****

void comwait (void)
{
 int16 sht_delay;

 output_float(sht_data_pin);                     //data high
 output_bit(sht_clk_pin, 0);                     //clk low
 delay_us(1);
 for(sht_delay=0; sht_delay<30000; sht_delay++)  // wait for max 300ms
  {
   if (!input(sht_data_pin)) break;              //if sht_data_pin low, SHT75 ready
   delay_us(10);
  }
}


//***** Function to reset SHT75 communication *****

void comreset (void)
{
 int8 i;

 output_float(sht_data_pin);    //data high
 output_bit(sht_clk_pin, 0);    //clk low
 delay_us(2);
 for(i=0; i<9; i++)
  {
   output_bit(sht_clk_pin, 1);  //toggle clk 9 times
   delay_us(2);
   output_bit(sht_clk_pin, 0);
   delay_us(2);
 }
 comstart();
}


//***** Function to soft reset SHT75 *****

void sht_soft_reset (void)
{
 comreset();           //SHT75 communication reset
 comwrite(0x1e);       //send SHT75 reset command
 delay_ms(15);         //pause 15 ms
}


//***** Function to measure SHT75 temperature *****

int16 measuretemp (void)
{
 int1 ack;
 int16 iobyte;

 comstart();             //alert SHT75
 ack = comwrite(0x03);   //send measure temp command and read ack status
 if(ack == 1) return;
 comwait();              //wait for SHT75 measurement to complete
 iobyte = comread();     //read SHT75 temp data
 return(iobyte);
}


//***** Function to measure SHT75 RH *****

int16 measurehumid (void)
{
 int1 ack;
 int16 iobyte;

 comstart();            //alert SHT75
 ack = comwrite(0x05);  //send measure RH command and read ack status
 if(ack == 1) return;
 comwait();             //wait for SHT75 measurement to complete
 iobyte = comread();    //read SHT75 temp data
 return(iobyte);
}


//***** Function to calculate SHT75 temp & RH *****

void calculate_data (int16 temp, int16 humid, float & tc, float & rhlin, float & rhtrue)
{
 float truehumid1, rh;

 //calculate temperature reading
 tc = ((float) temp * 0.01) - 40.0;

 //calculate Real RH reading
 rh = (float) humid;

 rhlin = (rh * 0.0405) - (rh * rh * 0.0000028) - 4.0;

 //calculate True RH reading
 rhtrue = ((tc - 25.0) * (0.01 + (0.00008 * rh))) + rhlin;
}


//***** Function to measure & calculate SHT75 temp & RH *****

void sht_rd (float & temp, float & truehumid)
{
 int16 restemp, reshumid;
 float realhumid;
 restemp = 0; truehumid = 0;

 restemp = measuretemp();    //measure temp
 reshumid = measurehumid();  //measure RH
calculate_data (restemp, reshumid, temp, realhumid, truehumid);  //calculate temp & RH
}


//***** Function to initialise SHT75 on power-up *****

void sht_init (void)
{
 comreset();    //reset SHT75
 delay_ms(20);  //delay for power-up
}

[code]
////////////////////////////////////////////////////////////////////////////////
///                               DS1307.C                                   ///
///                     Driver for Real Time Clock                           ///
///                                                                          ///
/// ds1307_init() - Enable oscillator without clearing the seconds register -///
///                 used when PIC loses power and DS1307 run from 3V BAT     ///
///               - Disable squarewave output                                ///
///                                                                          ///
/// ds1307_set_date_time(day,mth,year,dow,hour,min,sec)  Set the date/time   ///
///                                                                          ///
/// ds1307_get_date(day,mth,year,dow)               Get the date             ///
///                                                                          ///
/// ds1307_get_time(hr,min,sec)                     Get the time             ///
///                                                                          ///
////////////////////////////////////////////////////////////////////////////////

#define RTC_SDA  PIN_C4
#define RTC_SCL  PIN_C3

#use i2c(slave, sda=RTC_SDA, scl=RTC_SCL)

BYTE bin2bcd(BYTE binary_value);
BYTE bcd2bin(BYTE bcd_value);

void ds1307_init(void)
{
   BYTE seconds = 0;

   i2c_start();
   i2c_write(0xD0);      // WR to RTC
   i2c_write(0x00);      // REG 0
   i2c_start();
   i2c_write(0xD1);      // RD from RTC
   seconds = bcd2bin(i2c_read(0)); // Read current "seconds" in DS1307
   i2c_stop();
   seconds &= 0x7F;

   delay_us(3);

   i2c_start();
   i2c_write(0xD0);      // WR to RTC
   i2c_write(0x00);      // REG 0
   i2c_write(bin2bcd(seconds));     // Start oscillator with current "seconds value
   i2c_start();
   i2c_write(0xD0);      // WR to RTC
   i2c_write(0x07);      // Control Register
   i2c_write(0x80);     // Disable squarewave output pin
   i2c_stop();

}

void ds1307_set_date_time(BYTE day, BYTE mth, BYTE year, BYTE dow, BYTE hr, BYTE min, BYTE sec)
{
  sec &= 0x7F;
  hr &= 0x3F;

  i2c_start();
  i2c_write(0xD0);            // I2C write address
  i2c_write(0x00);            // Start at REG 0 - Seconds
  i2c_write(bin2bcd(sec));      // REG 0
  i2c_write(bin2bcd(min));      // REG 1
  i2c_write(bin2bcd(hr));      // REG 2
  i2c_write(bin2bcd(dow));      // REG 3
  i2c_write(bin2bcd(day));      // REG 4
  i2c_write(bin2bcd(mth));      // REG 5
  i2c_write(bin2bcd(year));      // REG 6
  i2c_write(0x80);            // REG 7 - Disable squarewave output pin
  i2c_stop();
}

void ds1307_get_date(BYTE &day, BYTE &mth, BYTE &year, BYTE &dow)
{
  i2c_start();
  i2c_write(0xD0);
  i2c_write(0x03);            // Start at REG 3 - Day of week
  i2c_start();
  i2c_write(0xD1);
  dow  = bcd2bin(i2c_read() & 0x7f);   // REG 3
  day  = bcd2bin(i2c_read() & 0x3f);   // REG 4
  mth  = bcd2bin(i2c_read() & 0x1f);   // REG 5
  year = bcd2bin(i2c_read(0));            // REG 6
  i2c_stop();
}

void ds1307_get_time(BYTE &hr, BYTE &min, BYTE &sec)
{
  i2c_start();
  i2c_write(0xD0);
  i2c_write(0x00);            // Start at REG 0 - Seconds
  i2c_start();
  i2c_write(0xD1);
  sec = bcd2bin(i2c_read() & 0x7f);
  min = bcd2bin(i2c_read() & 0x7f);
  hr  = bcd2bin(i2c_read(0) & 0x3f);
  i2c_stop();

}

BYTE bin2bcd(BYTE binary_value)
{
  BYTE temp;
  BYTE retval;

  temp = binary_value;
  retval = 0;

  while(1)
  {
    // Get the tens digit by doing multiple subtraction
    // of 10 from the binary value.
    if(temp >= 10)
    {
      temp -= 10;
      retval += 0x10;
    }
    else // Get the ones digit by adding the remainder.
    {
      retval += temp;
      break;
    }
  }

  return(retval);
}


// Input range - 00 to 99.
BYTE bcd2bin(BYTE bcd_value)
{
  BYTE temp;

  temp = bcd_value;
  // Shifting upper digit right by 1 is same as multiplying by 8.
  temp >>= 1;
  // Isolate the bits for the upper digit.
  temp &= 0x78;

  // Now return: (Tens * 8) + (Tens * 2) + Ones

  return(temp + (temp >> 2) + (bcd_value & 0x0f));
}
[/code]

Desconectado geronimoo

  • PIC10
  • *
  • Mensajes: 34
    • Divide & Conquer
Re: 16F877 con DS1307, SHT75 y 24LC256, no encuentro el error
« Respuesta #1 en: 09 de Septiembre de 2009, 02:38:28 »
Hola  :mrgreen:
Estas lineas no te dan un error al compilar????
Código: [Seleccionar]
       printf(lcd_putc,"\%02d/\%02d/\%02d",day,month,yr);
       lcd_gotoxy(1,4);
       printf(lcd_putc,"\%02d:\%02d:\%02d", hrs,min,sec);

Estas escapando el simbolo %, asi que los parametros day,month e yr, estan demas.
Intenta eliminando la barra invertida asi:

Código: [Seleccionar]
       printf(lcd_putc,"%02d/%02d/%02d",day,month,yr);
       lcd_gotoxy(1,4);
       printf(lcd_putc,"%02d:%02d:%02d", hrs,min,sec);
Saludos!
.::GERO::.

Desconectado kenniata

  • PIC10
  • *
  • Mensajes: 12
Re: 16F877 con DS1307, SHT75 y 24LC256, no encuentro el error
« Respuesta #2 en: 09 de Septiembre de 2009, 04:36:59 »
Hola Geronimoo,

Siempre me ha compilado correctamente. Las barras es para hacer la separación de la fecha. Ahora he probado otro código, haciendo uso de uno que publicó J1M en su web. Funciona todo pero cuando activo la interrupción de RDA, entonces se cuelga el pic, no hace nada. Deshabilito la interrupción, vuelve todo a la normalidad. Estoy que me subo por las paredes!

Desconectado MLO__

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 4581
Re: 16F877 con DS1307, SHT75 y 24LC256, no encuentro el error
« Respuesta #3 en: 09 de Septiembre de 2009, 15:11:20 »
Hola.

Creo que el I2C se va -por decirlo de alguna manera- cuando se activa alguna interrupción y se esta en pleno proceso de comunicación. Prueba deshabilitar la int_RDA cuando estes haciendo uso del I2C a ver que sucede.

Saludos
El papel lo aguanta todo

Desconectado geronimoo

  • PIC10
  • *
  • Mensajes: 34
    • Divide & Conquer
Re: 16F877 con DS1307, SHT75 y 24LC256, no encuentro el error
« Respuesta #4 en: 09 de Septiembre de 2009, 15:26:17 »
O de ultima, no uses interrupciones en RDA y reemplaza el codigo por polling  :(
.::GERO::.

Desconectado kenniata

  • PIC10
  • *
  • Mensajes: 12
Re: 16F877 con DS1307, SHT75 y 24LC256, no encuentro el error
« Respuesta #5 en: 10 de Septiembre de 2009, 03:31:11 »
Hola MLO_,

Si deshabilito la interrupción de RDA, todo funciona correctamente. He puesto varios leds en la placa para que se activen en función de la linea del código que están. Se cuelga en la de enable RDA. Me tiene loco

Geronimo, cómo podría hacerlo sin que se quedase colgado esperando a la recepción de un caracter? Al PC sólo se conecta de vez en cuando, no está conectado siempre.

Gracias a ambos

Desconectado MLO__

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 4581
Re: 16F877 con DS1307, SHT75 y 24LC256, no encuentro el error
« Respuesta #6 en: 10 de Septiembre de 2009, 10:37:07 »
Hola.

Lo mas recomendable, es que la interrupción no tome mucho tiempo, y veo que tienes un printf(); dentro de la interrupción. Mejor seria, asignar un flag dentro de la int_RDA y hacer todo lo que hace en el main.

Lo de deshabilitar la int_RDA seria momentáneo, solo cuando vas a usar el i2C, luego la podrías volver a activar.

Si solo vas a usar una USAR no es necesario el stream.

Saludos
El papel lo aguanta todo

Desconectado geronimoo

  • PIC10
  • *
  • Mensajes: 34
    • Divide & Conquer
Re: 16F877 con DS1307, SHT75 y 24LC256, no encuentro el error
« Respuesta #7 en: 10 de Septiembre de 2009, 12:19:23 »
Hola MLO_,

Si deshabilito la interrupción de RDA, todo funciona correctamente. He puesto varios leds en la placa para que se activen en función de la linea del código que están. Se cuelga en la de enable RDA. Me tiene loco

Geronimo, cómo podría hacerlo sin que se quedase colgado esperando a la recepción de un caracter? Al PC sólo se conecta de vez en cuando, no está conectado siempre.

Gracias a ambos

La funcion kbhit te sirve para hacer el poll al buffer del hardware.
En la ayuda de CCS hay un ejemplo, aunque basicamente se usa como la usaste en la rutina de la interrupcion.
Citar
kbhit( )
Returns:
 0 (or FALSE) if getc() will need to wait for a character to come in, 1 (or TRUE) if a character is ready for getc()
Function:
 If the RS232 is under software control this function returns TRUE if the start bit of a character is being sent on the RS232 RCV pin.  If the RS232 is hardware this function returns TRUE if a character has been received and is waiting in the hardware buffer for getc() to read.  This function may be used to poll for data without stopping and waiting for the data to appear.  Note that in the case of software RS232 this function should be called at least 10 times the bit rate to ensure incoming data is not lost.
.::GERO::.

Desconectado mbainotti

  • PIC10
  • *
  • Mensajes: 1
Re: 16F877 con DS1307, SHT75 y 24LC256, no encuentro el error
« Respuesta #8 en: 16 de Noviembre de 2009, 22:43:02 »
Che loco Soy Mariano, estudio en la UTN de Cordoba - Arg.
Estamos haciendo un trabajo similar, sensor de temperatura y humedad  + un real time. y para poder visualizarlo en un LCD 2x16. Buscando en la red , llegue a tu POST.  Y te funciono?  jeje no se de donde sos prometo que te llega un fernet de litro a tu casa si me pasas el codigo . Saludos! un abrazo!


 

anything