|
|
View previous topic :: View next topic |
Author |
Message |
maxikys
Joined: 25 Jul 2013 Posts: 17
|
HELP, RTC on Timer1 32768. |
Posted: Thu Jan 16, 2014 1:45 am |
|
|
I am developing a device PIC16LF1824 with real time clock. My DEVICE observed a day care for about 3 seconds ahead. Load capacitance of 12.5 pF crystal. Frequency of 32768 Hz. In the circuit mounted capacitors 22pF. Powered by batteries and supercapacitors. If you want I can send the circuit and PCB. Help please, thank you.
This code:
Code: |
#include <16LF1824.h>
#fuses INTRC_IO,NOWDT,NOBROWNOUT
#use delay(internal=32M)
#use rs232(baud=300,rcv=PIN_C5)
#Byte TMR1H = 0x017 // TIMER1 HIGH BYTE LOOK DATASHEET
#Byte T1CON = 0x018 //TIMER1 CONFIG REGISTER LOOK DATASHEET
#Byte intcon = 0x00B //TIMER1 CONFIG REGISTER LOOK DATASHEET
#Byte wpua = 0x20c
#Byte wpuc = 0x20e
#Byte ANSELA = 0x18c
#Byte ANSELB = 0x18e
#Bit wpua1 = 0x20c.1
#Bit wpuc3 = 0x20e.3
#Bit RXDTSEL = 0x11d.7
#Bit trisc3 = 0x08e.3//IN_STATE( опрос IN74HC251)
#Bit trisc2 = 0x08e.2//rc2
#Bit trisc4 = 0x08e.4//rc2
#Bit trisa1 = 0x10c.1//SQW
#define A0 PIN_C0 //Адрес для IN74HC251 "А0"
#define A1 PIN_C2 //Адрес для IN74HC251 "А1"
#define A2 PIN_C1 //Адрес для IN74HC251 "А2"
#define IN_POWER PIN_A0 //Вход опроса вкл. внешнего питания
#define DIRECT_MOC PIN_A1 //Выход управления на МОС3041
#define IN_STATE PIN_C3 //Вход опроса для IN74HC251
#define RX PIN_C5 //данные для задания время
#define jamp_prog_time PIN_C4 //джампер на программирование
#define DIRECT_PWM PIN_A2 //выход ШИМ
int1 flag_t1=false;
unsigned char Buffer[20], sec=0,min=0,hour=0,day=0,month=0,year=14,i_buff=0,i=0;
int16 CRC;
//=====================CRC=========================================
int16 Calc_Crc16(int8 *Buffer, int16 Len)
{
int16 x;
int16 crc = 0xFFFF;
while(Len--)
{
x = make8(crc,1) ^ *Buffer++;
x ^= x>>4;
crc = (crc << 8) ^ (x << 12) ^ (x <<5) ^ x;
}
return crc;
}
void crc_detect(void)
{
CRC = Calc_Crc16(Buffer, sizeof(Buffer)-2);
if( make8(CRC, 1)==Buffer[18] && make8(CRC, 0)==Buffer[19])
{
year=Buffer[13];
month=Buffer[14];
hour=Buffer[15];
min=Buffer[16];
sec=Buffer[17];
output_toggle(A0);
//enable_interrupts(INT_TIMER1);
}
}
void prog_time(void)
{
disable_interrupts(INT_TIMER1);
if(kbhit())
{
if(i_buff==20)
{
if(buffer[0] == 80)output_toggle(A1);
i_buff=0;
crc_detect();
}
buffer[i_buff]=getc();
++i_buff;
}
enable_interrupts(INT_TIMER1);
}
#int_TIMER1
void TIMER1_isr() // 2^16= 65536/2 = 32768 * 1/32.768Hz <--- (1sec)
{
flag_t1=true;
//set_timer1(get_timer1()+2);
//bit_clear(T1CON,7); //Enable access to the individual bytes of the timer register
//Bit_Set(TMR1H,7); //Add 32768 to timer1 by setting high bit or timer register
//Bit_Set(T1CON,7); //Disable access to the individual bytes of the timer register
//flg_timer1=true;
/****************************************************/
}
void main()
{
// настройка портов для уменьшения потрнбления
output_low(A2);//адреса
output_low(A1);
output_low(A0);
output_low(DIRECT_PWM);//PWM
RXDTSEL=0;
setup_timer_1(T1_EXTERNAL|T1_DIV_BY_1|T1_ENABLE_T1OSC);
bit_clear(INTCON,0);
bit_set(INTCON,3);
setup_adc( ADC_OFF );
// setup_timer_2(T2_DISABLED);
// setup_timer_6(T6_DISABLED);
// setup_timer_4(T4_DISABLED);
setup_ccp1(CCP_OFF);
setup_ccp2(CCP_OFF);
setup_ccp3(CCP_OFF);
setup_ccp4(CCP_OFF);
setup_spi(SPI_DISABLED);
setup_vref(VREF_OFF);
setup_dac(DAC_OFF);
for(i=0;i<20;i++)Buffer[i]=0;
setup_oscillator(OSC_8MHZ|OSC_NORMAL|OSC_PLL_ON,0);
delay_ms(5000);
enable_interrupts(INT_TIMER1);
enable_interrupts(GLOBAL);
sleep();
while(true)
{
if(flag_t1 == true)
{
++sec;
if(sec==30)
{
output_toggle(DIRECT_PWM);
sec=0;
++min;
if(min==60)
{
min=0;
++hour;
if(hour==24)
{
hour=0;
++day;
if(year%4==0&&month==2&&day==30){day=1;++month;}// если год высокосный
if(year%4!=0&&month==2&&day==29){day=1;++month;}// если год невысокосный
if(month==1||month==3||month==5||month==7||month==8||month==10||month==12){if(day==32){day=1;++month;}}//месяцы с 31 днем
if(month==4||month==6||month==9||month==11){if(day==31){day=1;++month;}}//месяцы с 30 днями
if(month==13)
{
month=0;
++year;
if(year==100)
{
year=0;
min=0;
hour=0;
month=0;
}
}
}
}
}
flag_t1 = false;
}
if(input(jamp_prog_time) == 1){sleep();}
else prog_time();
}
}
|
|
|
|
C Turner
Joined: 10 Nov 2003 Posts: 40 Location: Utah
|
|
Posted: Thu Jan 16, 2014 11:53 am |
|
|
The first time I used a 32.768 kHz crystal in an RTCC application (it wasn't even on a PIC) I had a problem with the crystal being too slow by 15-20 seconds a day, but I'd neglected to pay attention to several things:
- The data sheet/app notes for the crystal. In reviewing the manufacturer's information I found suggested values for the various crystals in example circuits and noted that I'd picked less than optimal capacitor values.
- Remembering that the board layout/oscillator itself has a bit of capacitance that needs to be taken into account.
Your ISR seems simple enough in that it rolls over every other second, so I do suspect that the capacitance in the circuit is very slightly off. Since you state that clock runs 3 seconds/day fast you are in luck since its usually a bit easier to pad a crystal down in frequency than go the other way: A couple of pF in across the crystal - say, a 1-10pF trimmer capacitor in parallel with it - should allow you to get the frequency very close.
Please note, however, that these "Tuning Fork" mode crystals should not expected to be able to hold accuracy to better than a few seconds a day over any reasonable sort of temperature range, so unless you can guarantee that your circuit will stay at a constant temperature, it may be more hassle than it's worth try to get it even closer than it is. In other words, 2-3 seconds a day may well be within its specifications.
* * *
One thing that you might consider doing is to modify your code to keep track of the clock cycles that have gone by. For example, using an 32 bit counter, you know that every time your T1 flag goes active that 65536 oscillations have occurred and every time it did so, add 65536 to its value. You could then look at the top 2 bytes of this variable and determine every time 2 seconds had gone by. Now, if you were to add something *other* than 65536 - say, 65532 - you would effectively be slowing down your crystal as it would now take slightly longer than 65536 oscillations for that 32 bit integer's top two bytes to change and indicate that 2 seconds had gone by. Using this scheme, you could correct for 0.5 Hz errors (e.g. 1 out of 65536) but if you were to write it so that it added/subtracted an "offset" value every, say, 100 seconds, you could effectively "adjust" the crystal frequency by 0.01 Hz steps!
* * *
Also, probably do not need an ISR at all: If you can guarantee that your main() function can "look" at Timer 1's MSB at least every half second, you could increment your second counter every time it changes - and this occurs at 1 Hz rather than 0.5 Hz!
* * *
I also note that you are using the PIC16F1824 and this part has a built-in temperature indicator which is a diode biased such that its absolute voltage is a function of temperature. If you wanted to get really fancy, you could use this to calibrate your crystal and obtain much better accuracy by applying corrections to the time indicated by the ISR.
If you wanted to be even more thorough, you would also take into account the operating voltage for the PIC (which could be determined by using its voltage reference) - yet another factor that affects frequency slightly - but that effect is far smaller than that of of temperature on the crystal and its capacitors.
Now the monitoring of temperature and voltage is a way to make an otherwise simple project into a complicated one - and if you were to make many of these, it would become difficult to calibrate each one - but it may be fun to think about and, perhaps, do just once!
CT |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9221 Location: Greensville,Ontario
|
|
Posted: Thu Jan 16, 2014 12:18 pm |
|
|
In the 'code library' there's a nice, working 'software RTC' program.Just use the search option to find it. Just be sure to edit the timer and clock values for your osc.
As for the timing issue, I'd reduce the caps to say 15 puff to compensate for loading.
hth
jay |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19499
|
|
Posted: Thu Jan 16, 2014 1:06 pm |
|
|
It is worth also being aware, that the crystal can be perfect, and trimmed correctly, and you can still gain time, if the track layout round the circuit is not done properly. Look at the Microchip notes about not running any digital signals close to these lines. They can easily pickup extra pulses if this is not followed....
Best Wishes |
|
|
maxikys
Joined: 25 Jul 2013 Posts: 17
|
|
Posted: Mon Jan 20, 2014 2:54 am |
|
|
Thank you very much everyone for your answers, especially the "C Turner" According to your advice, I changed the capacitance, and received not bad enough precision.
Because device to be used in conditions (-30 ... +50) and battery-powered, you have to use and offers, internal temperature sensor and an internal voltage reference.
I have more questions:
1) The internal temperature sensor + (internal reference voltage source + ADC) is it possible to use in battery-powered.
2) How to recalculate correction factor for the frequency dependence on temperature. Temperature tolerance of quartz (-40 ° ~ +85 C):-0.042ppm / ° C ² typ
KX-38T GEYER (part n. 12.80100 / 12.80101-T ) |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19499
|
|
Posted: Mon Jan 20, 2014 3:33 am |
|
|
Several comments here:
1) Don't assume the crystal is the only thing affecting the stability. Remember the capacitors also have a temperature co-efficient. One 'sneaky' thing is that by careful choice of the capacitor types, you can make these partially compensate for the crystal.
2) 'Watch' crystals give really very good stability if kept close to body temperature. The curve involved though is not simple linear. The frequency is given by:
f=f0(1-0.042(t-t0)^2)
3) Different crystal cuts have different behaviour. The point about the watch crystal is that it is a cheap cut with little change around the body temperature, and small. Hence ideal for a 'watch'. However for something in a less controlled environment, look for something like a GT cut crystal. This 'self compensates' over a range between perhaps -25, and +75C. More expensive, but much simpler. Also a larger crystal. Typically 100KHz min.. Talk to a crystal supplier, rather than just pulling 'off the shelf' types out of a catalogue.
4) Trying to compensate in software, is certainly to some extent 'doable', but remember that crystals also age. So frequency will drift for other reasons than just temperature. Since the temperature curve is -ve, away from 25C, You'd calculate the square of temperature from this point, multiply by the factor, and add counts to the clock.
5) You can use anything in the chip 'battery powered', but obviously the more things you run, the more power is drawn. Remember you can turn things on for a short time though. The crystal temperature won't be the die temperature though....
6) Just how good do you need the clock to be?. The watch crystal, even if held 10 degrees away from 25C, for the whole year will still be within 5 minutes at the end of the year. Since the error is a square law though, if your environment is going to go to negative temperatures for example, then far easier and better to look at choosing a crystal that will give better accuracy at such temperatures, than make the project very complex trying to 'compensate'....
Have fun. |
|
|
|
|
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
|