| 
	
	|  |  |  
	
		| View previous topic :: View next topic |  
		| Author | Message |  
		| JamesW 
 
 
 Joined: 23 Apr 2007
 Posts: 93
 Location: Rochester, England
 
 
			      
 
 | 
			
				| Is there a correct way to read a real time clock? |  
				|  Posted: Thu Oct 30, 2014 8:56 am |   |  
				| 
 |  
				| Hi folks, 
 Two posts in one day - a personal best!
 
 This is an unusual one - is there a "correct" order in which to read the registers of a real time clock?
 
 I've used various real time clocks over the years, both internal and external and have seen this behaviour on both.
 
 The reason I ask is this.  I've done a project a couple of years ago to control outside clocks running on synchronous ac motors, and to make sure they display the correct time.  (Basically involves turning the motor off for 1H or 11H to do summer/winter time changes - and in the event of a power cut, not restarting the motor until the time is equal to the time the power went off)
 
 I am running one of these clocks on the outside of our building, and have also used a spare relay output to drive the dinner bell for the workshop.
 
 At 9:00:00 the bell starts work
 at 12:30:00 the bell stops work
 at 13:30:00 the bell restarts work
 at 18:00 the bell stops work
 
 The bell involved a bit of a hack into the normal code of the unit and basically involves adding into the main loop a bit of code to read the RTC and saying something like :
 
 
  	  | Code: |  	  | if ( (hours == 9) && (minutes == 0) && (Seconds == 0) )
 {
 output_high(RELAY);
 BellTimer = 5;
 }
 
 | 
 
 and so on for the other times (Bell timer is decremented in an IRQ and when it reaches zero, stops decrementing and turns the relay off;
 
 This works great - but once or twice a week the bell also goes off at 10am and 7pm.  (not 14:30 though - which I think is key).
 
 Do real time clocks actually cascade the time? - so if read in the wrong order could potentially actually give me two 9am's and 6pm's if only for a fraction of a second?
 
 If so - is there a correct order to read the registers in order to prevent this happening.
 
 Thanks in advance
 
 James
 |  |  
		|  |  
		| Ttelmah 
 
 
 Joined: 11 Mar 2010
 Posts: 19962
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Thu Oct 30, 2014 9:46 am |   |  
				| 
 |  
				| Which RTC?. 
 It matters.
 
 Normally chips like the DS1307, 'latch' all the registers when one particular one is read (normally the lowest in memory), so that the others won't update, until a 'complete' read is performed.
 
 In many cases, 'sequential' tests are much safer performed on a 'tick'. If (for instance), you have a simple 1/second counter from the RTC interrupt, which then counts minutes, and is reset at midnight, then
 your 'bell' becomes:
 
  	  | Code: |  	  | if (mins>=540 && mins<750)
 
 | 
 
 Which will work correctly, even if the exact count 'at' 540 is missed.
 
 For the internal RTCC, there is an RTSYNC bit which goes true, when the registers are about to update. You wait for this to go off, then read all 4 word registers into RAM, and do your calculations on the RAM copy.
 |  |  
		|  |  
		| JamesW 
 
 
 Joined: 23 Apr 2007
 Posts: 93
 Location: Rochester, England
 
 
			      
 
 | 
			
				|  |  
				|  Posted: Thu Oct 30, 2014 11:45 am |   |  
				| 
 |  
				| Thanks again. 
 The RTC is a DS1305 that I'm having the issues with.
 
 Do the CCS routines they have supplied for the internal RTC's take into account the RTSYNC when you do a read, or should you do that yourself?
 
 if so, I assume a basic bit test like this, will work?
 
 
  	  | Code: |  	  | #word RCFGCAL = 0x0860
 
 if (bit_test(RCFGCAL, 12) == 0)
 {
 /* UPDATE TIME HERE */
 }
 
 
 | 
 |  |  
		|  |  
		| Ttelmah 
 
 
 Joined: 11 Mar 2010
 Posts: 19962
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Fri Oct 31, 2014 2:06 am |   |  
				| 
 |  
				| OK. 
 The reason for your problem, is that the CCS supplied DS1305 driver doesn't take advantage of the latching of the chip. They use sequential single reads, rather than the burst read needed to ensure this.
 The code needed (with the ds1305 driver already included), is:
 
  	  | Code: |  	  | void rtc_get_time_burst(unsigned int8 & hr, unsigned int8 & min, unsigned int8 & sec) {
 int8 buffer[3];
 int8 ctr;
 output_high(RTC_RST); //select chip
 write_ds1305_byte(0); //start at register 0
 for (ctr=0;ctr<3;ctr++)
 buffer[ctr]=DS1305_SPI_XFER(0);
 //Burst read three bytes
 output_low(RTC_RST); //de-select
 hr = rm_bcd(buffer[2]); //Now decode the received bytes
 min = rm_bcd(buffer[1]);
 sec = rm_bcd(buffer[0]);
 }
 
 | 
 and use this to get the time.
 |  |  
		|  |  
		| JamesW 
 
 
 Joined: 23 Apr 2007
 Posts: 93
 Location: Rochester, England
 
 
			      
 
 | 
			
				|  |  
				|  Posted: Fri Oct 31, 2014 11:54 am |   |  
				| 
 |  
				| I will give it a go, and keep you posted. 
 Thanks
 
 James
 |  |  
		|  |  
		| Mike Walne 
 
 
 Joined: 19 Feb 2004
 Posts: 1785
 Location: Boston Spa UK
 
 
			    
 
 | 
			
				| Re: Is there a correct way to read a real time clock? |  
				|  Posted: Fri Nov 07, 2014 5:10 pm |   |  
				| 
 |  
				|  	  | JamesW wrote: |  	  | Hi folks, 
 Two posts in one day - a personal best!
 
 This is an unusual one - is there a "correct" order in which to read the registers of a real time clock?
 
 I've used various real time clocks over the years, both internal and external and have seen this behaviour on both.
 
 The reason I ask is this.  I've done a project a couple of years ago to control outside clocks running on synchronous ac motors, and to make sure they display the correct time.  (Basically involves turning the motor off for 1H or 11H to do summer/winter time changes - and in the event of a power cut, not restarting the motor until the time is equal to the time the power went off)
 
 I am running one of these clocks on the outside of our building, and have also used a spare relay output to drive the dinner bell for the workshop.
 
 At 9:00:00 the bell starts work
 at 12:30:00 the bell stops work
 at 13:30:00 the bell restarts work
 at 18:00 the bell stops work
 
 The bell involved a bit of a hack into the normal code of the unit and basically involves adding into the main loop a bit of code to read the RTC and saying something like :
 
 
  	  | Code: |  	  | if ( (hours == 9) && (minutes == 0) && (Seconds == 0) )
 {
 output_high(RELAY);
 BellTimer = 5;
 }
 
 | 
 
 and so on for the other times (Bell timer is decremented in an IRQ and when it reaches zero, stops decrementing and turns the relay off;
 
 This works great - but once or twice a week the bell also goes off at 10am and 7pm.  (not 14:30 though - which I think is key).
 
 Do real time clocks actually cascade the time? - so if read in the wrong order could potentially actually give me two 9am's and 6pm's if only for a fraction of a second?
 
 If so - is there a correct order to read the registers in order to prevent this happening.
 
 Thanks in advance
 
 James
 | 
 
 I ran this code to test how often the seconds counter rolls over without the minutes counter appearing to advance.
 
  	  | Code: |  	  | // Clock roll over test 
 #include <18F252.h>
 #fuses HS,NOWDT,NOPROTECT,NOLVP
 #use delay(clock=4000000)
 #use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
 
 int8 year, mth, day, hr, min, sec;
 int16 roll_over = 0;
 int16 no_min_change = 0;
 
 #include "DS1302.C"
 
 int8 old_sec, old_min;
 
 void main()
 {
 rtc_init();
 rtc_get_time (hr, min, sec);
 old_sec = sec;
 old_min = min;
 
 while (1)
 {
 while (old_sec == sec) {rtc_get_time (hr, min, sec);}
 
 if (sec == 0x59)
 {
 printf (" \n\r ");
 printf( " clock roll over test  %xhr %xmin %xsec \n\r ", hr, min, sec);
 }
 
 if (sec == 0x00)
 {
 printf( " clock roll over test  %xhr %xmin %xsec \n\r ", hr, min, sec);
 roll_over++;
 if (min == old_min) {no_min_change++; }
 printf( " %ld roll_over  %ld with no_min_change \n\r " , roll_over, no_min_change );
 }
 old_sec = sec;
 old_min = min;
 }
 }
 | 
 The result was that on roughly 1 in 3 occasions the seconds display rolled over to zero before the minutes counter appeared to advance.
 For example, 23min 59sec was followed by 23min 00sec, rather than the correct 24min 00sec.
 This tallies with your observation and supports Mr T's assertion regarding the CCS driver.
 
 I've used a DS1302 rather than your DS1305, but suspect the problem lies in the CCS supplied driver.
 
 The CCS driver reads hr, min, sec in turn.
 If the seconds counter rolls over during the read_hr my code detects NO error.
 If the seconds counter rolls over during the read_min my code WILL detect an error.
 If the seconds counter rolls over during the read_sec my code detects NO error.
 
 My code spends virtually all its time reading the DS1302 clock.
 It should detect an error roughly once per three readings, which agrees with my measurements.
 
 I don't know anything about the internal workings of the DS1302 chip.
 I would hope the clock chip's counters operate synchronously and do not introduce significant reading errors.
 
 Mike
 |  |  
		|  |  
		| Ttelmah 
 
 
 Joined: 11 Mar 2010
 Posts: 19962
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Sat Nov 08, 2014 1:52 am |   |  
				| 
 |  
				| Yes, and no....   
 Reading the data sheet of the 1305, it specifically says that you have to use burst mode, then the registers will all be latched till the read completes.
 The 1302, is fractionally different, it latches the registers, till CE rises. So with this you can do 'separate' reads, provided you don't release CE. The burst mode implementation is slightly different on this chip, making it less convenient to use, which is probably 'why' they give this alternative.
 However the CCS driver, as written releases the CE line between each read, so will give the same problem...
 
 The old 'read the data sheet' problem at CCS.....
 |  |  
		|  |  
		|  |  
  
	| 
 
 | 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
 
 |