View previous topic :: View next topic |
Author |
Message |
P. Frank Guest
|
Show Time on LCD Display |
Posted: Wed Apr 14, 2004 3:23 am |
|
|
Hi,
i want to write a program which measure time from pulses with the accuracy of 10ms. I wait for the first positive edge of my signal which i want to measure and then start the Timer 1 which give me an interrupt all 10ms. Now i count this interrupts until the edge is negative.
Then i want to show the actual value in the format hh:mm:ss:ms on the display. Additionaly i want to store the last 10 measured values in 10 variabels and calculate the average off this. After calculating i want also to show it on the display in the format hh:mm:ss:ms.
My problem is now that i am not sure which variables i should use to store the 10 average values and the actual value.
1. I can use 11 U32 Variables to save the value from the 10ms counter and change the format to hh:mm:ss:ms if i want to show it on the display.
2. I can use int8 hour[11], minute[11],second[11],millisecond[11] and refresh this variables every time the Timer 1 interrupt occur.
What would you do? I don`t know a really good way to make the format hh:mm:ss:ms from a U32 which counts every 10ms.
Pic is a 16F876@20MHz.
Best regards
Patrick Frank |
|
|
Couch
Joined: 20 Jan 2004 Posts: 9 Location: Ottawa, Ontario Canada
|
|
Posted: Wed Apr 14, 2004 7:15 am |
|
|
Hello,
Use an int32 format to make your interrupt sequence (and your last 10 memory) as clean as possible. The downside as you mentioned is that the LCD formatting is a bit trickier, but not too bad - just perform some modulus math to extract the hour, then minute, then seconds (subracting their contribution from the int32 value as you go). If you make this a function, you can make this pretty compact to use for all 10 time values.
thanks
Dave |
|
|
Neutone
Joined: 08 Sep 2003 Posts: 839 Location: Houston
|
|
Posted: Wed Apr 14, 2004 7:35 am |
|
|
This is the most accurate aproach using a crystle that is does not divide to an integer number of interupts per second. You could use what ever timer you wish by altering the number of instruction per interupt.
Code: |
/*********************************************
* Initialize RTC *
*********************************************/
void Initialize_RTC(void)
{ Ticker = XTAL_FREQUENCY;
setup_timer_2 ( T2_DIV_BY_4, 0xff, 4 ); // initialize 8 bit counter/timer 2 to interupt every 16384 clock cycles
enable_interrupts( INT_TIMER2 ); // Start RTC
}
// Global Real Time Clock Information
#int_TIMER2 // Clock interrupt adjusted to occurs ~ 1ms
void TIMER2_isr() // -=Process Zero Drift Real Time Clock Information=-
{ tickmSec = 1; // set each MS very approximately
Ticker -= 16384; // Decrement ticker by clocks per interupt
if ( Ticker < 16384 ) // If second has expired
{ Ticker += XTAL_FREQUENCY; // Increment ticker by clocks per second
second++; // Increment number of seconds
tickSec = 1; // set each Second very accuratly
}
}
|
|
|
|
P. Frank Guest
|
|
Posted: Fri Apr 16, 2004 1:54 am |
|
|
Hello,
thanks for the response. Now i am a big step ahead.
@Neutone
I use a pic 16F876@20MHz.
I setup my timer following:
Code: |
setup_timer_1(T1_INTERNAL|T1_DIV_BY_1); // setup interrupts
set_timer1 (15536);//10ms(=65536-(0.01/(4/20000000))
|
This gives me a interrupt every 10ms. I need this accurate for a week.
Is this possible our should i use our function? I don`t have much experience with this.
@All
Now i use the U32 variables to save the timer values.
I have programmed a function which convert this in dd:hh:mm:ss:ms to show it on the LCD. Here is the function:
Initalisation:
Code: |
int32 aktuelle=0; //measured time
int32 maketime_1=0; //temp
int32 maketime_2=0; /temp
int8 ms; //milliseconds
int8 s; //seconds
int8 m; //minutes
int8 h; //hours
int8 d; //days
void MakeTime (int32 zeit,short hours);
|
Program:
Code: |
MakeTime(aktuelle,0); //gives the U32 time to the function
void MakeTime (int32 zeit,short hours) //calculates the Time from U32 Value.
{
h=0;d=0; //12345678=Value to Calculate
maketime_1=zeit/100; //Time in 10ms/100 =Seconds //123456
maketime_2=maketime_1*100; //Time without ms*100 //12345600
ms=zeit-maketime_2; //Milliseconds //78=12345678-12345600
maketime_2=maketime_1/60; //Time in Seconds/60 = Minutes //2057
zeit=maketime_2; //2057
maketime_2=maketime_2*60; //123420
s=maketime_1-maketime_2; //Seconds //36=123456-123420
maketime_2=zeit/60; //Time in Minutes/60 = Hours //34
maketime_1=maketime_2; //34
maketime_2=maketime_2*60; //2040
m=zeit-maketime_2; //Minutes //17=2040-2057
if(hours)
{
maketime_2=maketime_1/24; //Time in Hours/24 = Days //1
d=maketime_2; //Days //1
maketime_2=maketime_2*24; //24
h=maketime_1-maketime_2; //Hours //10
}
Anzeigen(); //shows the values on lcd.
}
void Anzeigen (void)
{
LCD_SetPosition ( LINE_16_2);
printf ( LCD_PutChar, "%02ud%02uh%02um%02us%02u",d,h,m,s,ms);
}
|
It works :-) But i think it`s very time intensive. Is there another way? |
|
|
Neutone
Joined: 08 Sep 2003 Posts: 839 Location: Houston
|
|
Posted: Fri Apr 16, 2004 7:40 am |
|
|
To get accuracy you must let the timer run freely. Never attempt to load it with a value to achieve accuracy. You can setup timer2 to interupt every 1mS with no error at all. The interupt would occure every 5000 instruction cycles. I don't think thats over taxing the program. |
|
|
P. Frank Guest
|
|
Posted: Mon Apr 19, 2004 1:18 am |
|
|
Neutone wrote: | This is the most accurate aproach using a crystle that is does not divide to an integer number of interupts per second. You could use what ever timer you wish by altering the number of instruction per interupt.
Code: |
/*********************************************
* Initialize RTC *
*********************************************/
void Initialize_RTC(void)
{ Ticker = XTAL_FREQUENCY;
setup_timer_2 ( T2_DIV_BY_4, 0xff, 4 ); // initialize 8 bit counter/timer 2 to interupt every 16384 clock cycles
enable_interrupts( INT_TIMER2 ); // Start RTC
}
// Global Real Time Clock Information
#int_TIMER2 // Clock interrupt adjusted to occurs ~ 1ms
void TIMER2_isr() // -=Process Zero Drift Real Time Clock Information=-
{ tickmSec = 1; // set each MS very approximately
Ticker -= 16384; // Decrement ticker by clocks per interupt
if ( Ticker < 16384 ) // If second has expired
{ Ticker += XTAL_FREQUENCY; // Increment ticker by clocks per second
second++; // Increment number of seconds
tickSec = 1; // set each Second very accuratly
}
}
|
|
Hello Neutone,
i want to use your source code, but i don`t understand it complete.
Can you give me a little help?
I think i must use the function "Initialize_RTC" only one time. This function writes the XTAL_Frequency (20000000) in the variable Ticker (Int32 ?) and initalise the timer 2. That`s clear.
But what your are doing in the TIMER2_isr? I don`t no what i should do with the variables "tickSec","tickmSec" and in which format they are (INT8 or something?). What you doing with "Ticker" in the interrupt?
Best regards and thanks for the help
Patrick Frank |
|
|
Neutone
Joined: 08 Sep 2003 Posts: 839 Location: Houston
|
|
Posted: Mon Apr 19, 2004 7:51 am |
|
|
In main wait to the input to change and then clear both seconds and mseconds. In main wait for it to change again and then print the time.
Code: |
#int_TIMER2
void TIMER2_isr()
{ mSecond++;
if ( mSecond > 999 )
{ second++;
mSecond=0;
}
}
|
|
|
|
|