|
|
View previous topic :: View next topic |
Author |
Message |
zhiyongwoo
Joined: 18 Jul 2010 Posts: 9
|
16LF1936 Internal Oscillator Accuracy |
Posted: Sun Jul 25, 2010 7:54 am |
|
|
Hi all,
Does anyone using PIC's internal oscillator?
I use it in 16LF1936, it said it will produce a 31000Hz but when I try to blink a LED with 0.5 seconds, it blinks the LED longer than 0.5 seconds.
I also try to display the real-time clock on LCD (update every 1 second) and it shows that it has almost 5 seconds delay after 90 seconds run time.
I was design the Timer 1 to overflow time in every 0.1second so, I can get a 0.1 seconds interruption to update my software RTC.
I did checked my Timer1's prescale, value for interruption and the ISR as well and they all looks fine.
Then I suspect, could it not be 31000Hz? So, I recalculate the value for TMR1H & TMR1L based on 30100Hz and redo the test on LCD.
Now, I have 5 seconds delay after 20 minutes but still not accurate at all.
So, I am very suspicious on the internal oscillator. I think this has nothing to with the compiler.
Does anyone has similar problem? and what is your suggestion?
My next step is to use external crystal with 4MHz (XT) to drive the MCU and see how is the real time clock.
I will update this post when I got the result. But at the mean time, please welcome to post any comments and suggestion if you think it is relevant. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Jul 25, 2010 1:56 pm |
|
|
Quote: |
when I try to blink a LED with 0.5 seconds, it blinks the LED longer than 0.5 seconds.
|
1. Post your LED blinking program. It must have the #include for the PIC
and the #fuses statement, and the #use delay(), and a main().
2. What is your CCS compiler version ?
3. Are you testing this on a hardware board ? |
|
|
zhiyongwoo
Joined: 18 Jul 2010 Posts: 9
|
|
Posted: Sun Jul 25, 2010 2:25 pm |
|
|
The PIC fuse contents
Code: | #include <16LF1936.h>
#device adc=16
#FUSES INTRC_IO //Internal RC Osc, no CLKOUT
#FUSES PUT //Power Up Timer
#FUSES NOPROTECT //Code not protected from reading
#FUSES NOMCLR //Master Clear pin used for I/O
#FUSES NOCPD //No EE protection
#FUSES BROWNOUT_NOSL //Brownout enabled during operation, disabled during SLEEP
#FUSES NOIESO //Internal External Switch Over mode disabled
#FUSES NOFCMEN //Fail-safe clock monitor disabled
#FUSES WDT_SW //Watch Dog Timer controlled by the SWDTEN bit
#FUSES NOCLKOUT //Clock Out function is disabled.
#FUSES NOWRT //Program memory not write protected
#FUSES PLL_SW //Disable PLL
#FUSES STVREN //Stack full/underflow will cause reset
#FUSES BORV19 //Reset MCU at below 1.9V
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NODEBUG //No Debug mode for ICD
#use delay(clock=31000) |
The Included contents:
Code: | //Define SFR
#Byte TMR1L = getenv("SFR:TMR1L")
#Byte TMR1H = getenv("SFR:TMR1H")
#define Timer1_H 0xFC //Assume LFINTOSC is 31000Hz, so no. tick = 775
#define Timer1_L 0xF9 //Therefore, base value = 0x10000 - 0x000307
#define schedule_Task0 5
//Variable Address
addressmod (clock_variable,,, 0x020, 0x030);
#type default=clock_variable // all variable declarations in this area will be
// 0x020-0x030
int counter_ss;
int second;
int minute;
int hour;
int day;
int week;
int ss_task0;
#type default= // restores memory allocation back to normal
|
The MCU initialise contents:
Code: | //Watch Dog is OFF
setup_wdt(WDT_OFF);
//Set the Oscillator to Internal RC
setup_oscillator(OSC_31KHZ|OSC_INTRC|OSC_PLL_OFF,0);
//setup_oscillator(OSC_31250|OSC_INTRC|OSC_PLL_OFF,0);
//Set-up ADC
setup_adc_ports(sAN3| VSS_VDD);
setup_adc(ADC_OFF); //ADC_CLOCK_INTERNAL);
SETUP_DAC(DAC_OFF); //Disable DAC Module
//Disable MSSP Module (I2C/SPI)
setup_spi(SPI_SS_DISABLED);
//Setup Timers
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);//T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_timer_4(T4_DISABLED,0,1);
setup_timer_6(T6_DISABLED,0,1);
//Disable all Capture/Compare/PWM (CCPx) module
setup_ccp1(CCP_OFF);
setup_ccp2(CCP_OFF);
setup_ccp3(CCP_OFF);
setup_ccp4(CCP_OFF);
setup_ccp5(CCP_OFF);
//Disable ALL comparators
setup_comparator(NC_NC_NC_NC);
//Disable Ref Voltage module
setup_vref(FALSE);
//Initialise variables
TMR1H = Timer1_H;
TMR1L = Timer1_L;
counter_ss = 0;
second = 0;
minute = 0;
hour = 0;
day = 0;
week = 0;
ss_task0 = 0;
//Enable ALL Interrupt
enable_interrupts(INT_TIMER1);
enable_interrupts(GLOBAL); |
The source contents included main():
Code: | #include <RTClock.h>
#include <Variable.h>
#INT_TIMER1 NOCLEAR
void TIMER1_isr(void) //Interrupt every 0.1 seconds
{
clear_interrupt(INT_TIMER1);
//Reset Timer1 to minimum base value
TMR1H += Timer1_H;
TMR1L += Timer1_L;
//Happen every 0.1 second***************************************************
//Process programme's schedule
if (ss_task0!=0)
ss_task0--;
counter_ss++; //Increse by 1 (0.1sec)
if (counter_ss>9) //then check if it is >1sec
{
//Happen every 1 second*****************************************************
counter_ss = counter_ss - 10;
second++; //Increse by 1 (1sec)
if (second>59) //then check if it is >1min
{
//Happen every 1 minute*****************************************************
second = second - 60;
minute++; //Increse by 1 (1min)
if (minute>59) //then check if it is >1hour
{
//Happen every 1 hour*******************************************************
minute = 0;
hour++; //Increse by 1 (1hour)
if (hour>23) //then check if it is >1day
{
//Happen every 1 day********************************************************
hour = 0;
day++; //Increse by 1 (1day)
if (day>7) //then check if it is >1week
{
//Happen every 1 week*******************************************************
day = 0;
week++; //Increse by 1 (1week)
}
}
}
}
}
}
#define LED PIN_C0 //CHANGE PIN_XX TO YOUR LED PIN NUMBER, EX: PIN_A5
void main()
{
#include <Initialise.h>
output_low(LED);
while(true){
if (!ss_task0)//Example blinking LED program
{
ss_task0 = schedule_Task0;
output_toggle(LED); //Toggle the output state
}
}
} |
I am using CCS compiler version 4.108
I have tested on actual hardware board (Not using MPLAB SIM at all)
I hope I have given enough information. |
|
|
zhiyongwoo
Joined: 18 Jul 2010 Posts: 9
|
Test result with 4MHz XT crystal |
Posted: Sun Jul 25, 2010 2:36 pm |
|
|
Hi all,
As I promise on my previous post, I have tested the same code but using XT mode with 4MHz crystal.
My first experiment is to blink the LED in 0.5 second and the result is accurate. It does blink 0.5 second and I did make a comparison (run both MCU together) and I found the MCU (use internal crystal) has slower response compare to the other one.
The difference is very very obvious.
I will carry out another experiments which will use the LCD to display the clock and compare to my PC clock. I hope from there it should be able to show the differences in detail.
But you are welcome to prove me wrong (i.e. not the internal crystal issue) by testing my code (on my previous post). |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Jul 25, 2010 2:59 pm |
|
|
Quote: | I found the MCU (use internal crystal)
| There is no internal crystal.
The 16F1936 data sheet says the Low Frequency 31 KHz oscillator is not accurate:
Quote: |
8.5 Internal Clock Modes
The LFINTOSC (Low-Frequency Internal
Oscillator) is uncalibrated and operates at 31 kHz. |
There are two other internal oscillators that are more accurate, and
they can give 31.25 KHz. However, they are only accurate to +/- 2%.
Quote: |
1. The HFINTOSC (High-Frequency Internal
Oscillator) is factory calibrated and operates at
16 MHz. The frequency of the HFINTOSC can
be user-adjusted via software using the
OSCTUNE register (Register 8-3).
2. The MFINTOSC (Medium-Frequency Internal
Oscillator) is factory calibrated and operates at
500 kHz. The frequency of the MFINTOSC can
be user-adjusted via software using the
OSCTUNE register (Register 8-3).
bit 6-3 IRCF<3:0>: Internal Oscillator Frequency Select bits
000x =31kHz LF
0010 = 31.25 kHz MF
0011 = 31.25 kHz HF (2)
|
If you want to make a Real Time Clock, you must use an external
32.768 KHz watch crystal, using the Timer1 oscillator. |
|
|
zhiyongwoo
Joined: 18 Jul 2010 Posts: 9
|
|
Posted: Mon Jul 26, 2010 12:31 am |
|
|
Hi PCM Programmer
I did try to use the MFINT (31.25KHz or above), they have the same effect.
I don't think is 1-2% errors, I think is more than that probably is 4-6%.
I do realise that if I need an external oscillator for the real-time application. Unfortunately, I am working on a very low cost product and the cost has to be as minimum as possible.
So, less component is better. Is there any way I can get the LFINT to be more accurate like finding the right manufacturer frequency?
Is every chip has different %error in the LFINT?
Please help me! |
|
|
facuenta
Joined: 20 Dec 2010 Posts: 2
|
|
Posted: Mon Dec 20, 2010 4:47 pm |
|
|
Hello! First of all, sorry for my english.
How can I get exact timing?
I have a similar problem. I'm using the 16F1936, and I do not know how to get the exact time. I'm using the internal clock 8MHz. I tried to use the MPLAB SIM and did not work because it stayed in the library lcd.c, showing an infinite loop. I heard about "PIC Simulator IDE" but does not support the 16F1936.
I don't really know what to do.
I would really appreciate if some expert can help me.
Best regards |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19552
|
|
Posted: Tue Dec 21, 2010 3:16 am |
|
|
There are two separate problems here:
1) The accuracy of the internal oscillator. Not good enough for a clock, but 'adequate' for something not fussy about time.
2) The time taken to do things.
This latter is I suspect the 'killer' as posted. At 31000Hz master clock, the processor, will execute just 7750 instructions/second. It takes typically 30+ instructions to get into an interrupt handler - about 1/250th second at this clock speed. Now in the code posted, the clock will already have counted about 32 to 33 counts, when it gets to the point where he updated the timer count. So, relatively large errors. Worst case (the errors work the same way), you get a couple of percent error from the clock, and the added error from the code, and things start to get 'unacceptable'.
If you want a 'clock' application, the watch crystals are the answer. Typically a factor of at least 1000* more accurate than the 'best' internal PIC clock.
You will _not_ get 'accurate' times with the internal oscillator.
This obviously applies to the new poster to, if he is talking about 'exact time'....
To the new poster, you will need to add a stimulus, to have send the signal to the simulator code to say 'not busy', or switch the LCD code to not use the read ability of the LCD. LCD.C, _waits_ for the LCD to say it has finished writing data.
Best Wishes |
|
|
facuenta
Joined: 20 Dec 2010 Posts: 2
|
|
Posted: Fri Dec 24, 2010 4:29 pm |
|
|
Ttelmah,
Many thanks for your response.
Could you please explain to me how can I do to have send the signal to the simulator code to say 'not busy'?
Best regards and merry christmas! |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19552
|
|
Posted: Sat Dec 25, 2010 3:47 am |
|
|
Depends on your simulator/emulator.
On some, you can have a register value automatically 'change' after a period of time. On these, 'easy'. On most, just add a breakpoint, in the loop testing for 'busy', and manually change the register value.
Much easier to tell the LCD to simply 'wait', and not use the busy line. On flex_lcd for example, just comment out the line:
#define USE_LCD_RW 1
The code will then not attempt to read 'busy' from the LCD, and instead just pause for long enough for the commands to complete, and will run on the simulator without stopping.
Best Wishes |
|
|
|
|
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
|