CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Help in a Real Time Clock application

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
pattousai



Joined: 23 Aug 2006
Posts: 37

View user's profile Send private message

Help in a Real Time Clock application
PostPosted: Fri Jul 18, 2008 4:19 pm     Reply with quote

Hi everybody.

I'm using the code posted by ckielstra to implement a Real Time Clock, and every minute i set a flag that make a led to blink. the problem is that after a couple of hours the led just don't blink anymore.
i'm using the pic16f628a, xtal of 17287200 Hz and (i believe that is the source of the problem) a battery charger as the power source (5,6V).

So... my hardware isn't right? or there could be another problem?

Here is the code that i'm actually using.

thanks everybody.

Code:

///////////////////////////////////////////////////////////
// Zero Drift Real Time Clock
// Original code supplied by Neutone.
// Some small optimizations by C.Kielstra.
///////////////////////////////////////////////////////////
#include <16F628a.h>
#use delay(clock=17287200)
#fuses HS, NOWDT, NOLVP, NOMCLR
#use rs232(baud=9600, xmit=PIN_B3, rcv=PIN_B0, stream=PC)

//RTC variables
#define XTAL_FREQUENCY  17287200
#define TIMER1_FREQUENCY (XTAL_FREQUENCY / 4 )  // 1 clock tick = 1 instr. cycle = crystal frequency / 4

int32 Ticker;
int8 Seconds=0;

//optional:
 int16 Year = 2008;
 int8 Month = 7, Days = 17, Hours = 8, Minutes = 19;
 
 int1 flag1 = false;

////////////////////////////////////////////////////////////////////////////////
// Test whether a given year is a leap year.
// This optimized version only works for the period 2001 - 2099
////////////////////////////////////////////////////////////////////////////////
#define IS_LEAP(year) (year%4 == 0)


////////////////////////////////////////////////////////////////////////////////
//    Initialize RTC
////////////////////////////////////////////////////////////////////////////////
void Initialize_RTC(void)
{
  Ticker = TIMER1_FREQUENCY;                  // initialize clock counter to number of clocks per second
  setup_timer_1( T1_INTERNAL | T1_DIV_BY_1 ); // initialize 16-bit Timer1 to interrupt
                                              // exactly every 65536 clock cycles
                                              // (about 76 times per second)
  enable_interrupts( INT_TIMER1 );            // Start RTC
}

////////////////////////////////////////////////////////////////////////////////
//  -=Process Zero Drift Real Time Clock Information=-
//
// Most algorithms configure the timer to generate an interrupt every 100ms, and
// then count the number of interrupts. The problem in that approach is that most
// clock frequencies can't be divided by 256 and you don't get an exact 100ms.
// The small errors will add up to an error of several seconds a day.
//
// The algorithm presented here is exact in the long run because it doesn't
// count the number of interrupts but counts the number of clock cycles.
////////////////////////////////////////////////////////////////////////////////
#int_TIMER1                               
void TIMER1_isr()                         
{
   Ticker -= 65536;                        // Decrement ticker by clocks per interrupt
   if ( Ticker < 65536 ){                  // If second has expired
      Ticker += TIMER1_FREQUENCY;          //   Increment ticker by clocks per second
      Seconds++;                           //   Increment number of seconds
   }

   // --- Optional part start ---
   if( Seconds == 60 ){
      flag1 = true;
     
      Minutes++;
      Seconds=0;
      if( Minutes == 60 ){     
         Hours++;
         Minutes=0;
         if( Hours == 24 ){
            Days++;
            Hours=0;
            if( ( Days == 29 && Month==2 && !IS_LEAP(Year))
                || (Days == 30 && Month==2)
                || (Days == 31 && (Month==4 || Month==6 || Month==9 || Month==11 ))
                || (Days == 32) ){
               
               Month++;
               Days=1;
            }
            if( Month == 13 ){
               Year++;
               Month=1;
            }
         }
      }
   }
   // --- Optional part end --- 
}

////////////////////////////////////////////////////////////////////////////////
// Example program for using the RTC
////////////////////////////////////////////////////////////////////////////////
void main()
{
  int8 prev_second = -1;
  Initialize_RTC();
  enable_interrupts( GLOBAL );

  // loop forever
  while(1)
  {
    // Toggle output every second
    if( flag1 == true )
    {
      output_toggle(PIN_A2);
     
      flag1 = false;
    }   
  }
}
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Fri Jul 18, 2008 7:15 pm     Reply with quote

Using a battery charger as a power supply is not a very reliable solution. The 5.6V is within the absolute maximum ratings but outside the guaranteed specifications of 5.5V.
If the battery charger is one of the 'smarter' types the voltage could easily change...
I strongly recommend another power supply. Or at least try reducing the voltage by adding a low drop voltage regulator, or 1 or 2 diodes in series (0.6V drop for each diode).

To rule out software problems try testing with a simple as possible program.
Code:
#include <16F628a.h>
#use delay(clock=17287200)
#fuses HS, NOWDT, NOLVP, NOMCLR

void main()
{
  while(1)
  {
    // Toggle output every second
    output_toggle(PIN_A2);
    delay_ms(1000);
  }   
}


What is your compiler version number?
pattousai



Joined: 23 Aug 2006
Posts: 37

View user's profile Send private message

PostPosted: Mon Jul 21, 2008 8:49 am     Reply with quote

my compiler version is 4.057 and this simple program works fine.

i will try add a diode in series, really haven't think about that.


thanks
pattousai



Joined: 23 Aug 2006
Posts: 37

View user's profile Send private message

PostPosted: Wed Jul 23, 2008 4:55 pm     Reply with quote

ok, i bought 2 diodes and put them in series with the power source and the program stop to behave strangely.

But now I'm printing the time, and after 12 hours the program delay a couple of seconds and that is critical to me (maybe the code will run for years). So... I'm wondering is there any precise crystal? To be honest i know nothing about crystals, the only thing i know is that i bought a "crystal of 24MHz" :S


Thanks for the help
pattousai



Joined: 23 Aug 2006
Posts: 37

View user's profile Send private message

PostPosted: Wed Jul 23, 2008 5:31 pm     Reply with quote

i was doing some research, and found the ds1307 hardware. this already implements a RTC.

ok, but i think this not fit for me... because i want to send a configuration to the pic and depending on this configuration, the pic will send a data with the time specified.

example... the pic receive a configuration string, and are set to send a data every hour... 15 minutes later, the pic receive another configuration string, and are set to send a data every minute...

so... using this hardware i will have to read the time every minute anyway... and the pic will continue to delay some seconds in long hours, isn't right?

so... anyone have a suggestion to how should make my hardware?

thanks again
cmdrdan



Joined: 08 Apr 2005
Posts: 25
Location: Washington

View user's profile Send private message

PostPosted: Wed Jul 23, 2008 9:22 pm     Reply with quote

I would think that the DS1307 would work well from what you describe.

Set the SQW output of the 1307 to interrupt your PIC once per second via the external interrupt pin. In the interrupt service routine, decrement a sample_delay variable, and when it is zero, set a flag to be read in main(). In main(), check for the flag, and when set, read the time from the DS1307, process your data, and output the results.

The sample delay could be sent in as part of your configuration word, and there is no reason to read the time from the DS1307 until you want to. If timing accuracy is critical, check out the DS32KHZ TCXO to augment the accuracy of the DS1307.

Hope this helps....

Dan
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group