|
|
View previous topic :: View next topic |
Author |
Message |
olivier
Joined: 08 Apr 2010 Posts: 11
|
timer1 with interrupt |
Posted: Fri Jun 03, 2011 1:10 pm |
|
|
Hi everyone,
I need to built a timer that start to run on a push of a inputA(pin_a2) and stop time when inputB(pin_b0) pressed. I want to use pin_b0 on the External Interrupt that way I can free the micro to do other task.
I would like the accurate to 100micro second. Is it possible?
My plan is to modify the RTC function that I found on this forum to calculate the instruction cycle to time. Then serialize it via uart1 to pc terminal and LCD.
My current pic chip is PIC18F4680 with internal clock 8Mhz.
I currently have some code but the accuracy isn't there. I use the oscilloscope (200Mhz) with channel1 monitor the pressed of start button (pin_a2) and channel2 monitor the pin_b0. By manually measuring the edge of pin_a2 and pin_b0, I'm always off by at least 50mS and up.
Anyway can I improve this? Please give me some guidance.
thank you
Olivier |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Jun 03, 2011 3:58 pm |
|
|
Quote: | I'm always off by at least 50mS and up. |
Post your current test program. (complete and compilable).
What is the duration of the input test signal ? What are the voltage levels ?
What pin (or pins) is the test signal connected to on the PIC ?
Quote: |
My plan is to modify the RTC function that I found on this forum |
Post a link to this RTC code.
Also post your compiler version. |
|
|
andrewg
Joined: 17 Aug 2005 Posts: 316 Location: Perth, Western Australia
|
|
Posted: Fri Jun 03, 2011 9:18 pm |
|
|
Also, what are switching the pins? Are they digital signals or actual switches? In the latter case, have you considered the problem of contact bounce? _________________ Andrew |
|
|
olivier
Joined: 08 Apr 2010 Posts: 11
|
|
Posted: Mon Jun 06, 2011 12:54 pm |
|
|
Code: |
#include <Delay Time Counter.h>
#include <Flex_LCD16x2.c>
#include <float.h>
#include <limits.h>
#include <locale.h>
#include <math.h>
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#define START_SW PIN_A2
#define STOP_SW PIN_B0
#define RESET_SW PIN_A3
#define ERROR_LED PIN_A1
#define EXT_INT PIN_C1
#define TMR_INT PIN_A4
#define XTAL_FREQUENCY 8000000
//#define INTERNAL_FREQUENCY (XTAL_FREQUENCY / 4)
int Seconds = 0;
char Interrupt_Flag = 0, interruption_time = 0;
float executed_time = 0.00000;
int32 Inst_Cycle_Per_Second = 0, INTERNAL_FREQUENCY = 0;
void my_time_ms (char i,j,k);
void LCD_Pwr_Initialze(void);
void Power_On_Chk (void);
void RTC_Initialize (void);
Final_Delay_Time ();
void Start_Up_Screen();
void Blink_LED (char number_flash, int flash_duty_cycle);
void main()
{
// int timer1_16bit = 65535;
// float delay_time = 0.00000;
// int i;
float delay_time = 0;
int32 temp;
setup_adc_ports(AN0|VSS_VDD);
setup_adc(ADC_CLOCK_INTERNAL|ADC_TAD_MUL_20);
setup_psp(PSP_DISABLED);
setup_spi(SPI_SS_DISABLED);
setup_wdt(WDT_OFF);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_4);
// setup_timer_1(T1_INTERNAL | T1_DIV_BY_1);
setup_timer_2(T2_DIV_BY_16,255,1);
setup_timer_3(T3_DISABLED|T3_DIV_BY_1);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
disable_interrupts(INT_TIMER1);
disable_interrupts(INT_EXT);
ext_int_edge(INT_EXT_H2L);
disable_interrupts(GLOBAL);
setup_oscillator(OSC_8MHZ|OSC_INTRC|OSC_31250|OSC_PLL_ON);
// TODO: USER CODE!!
INTERNAL_FREQUENCY = XTAL_FREQUENCY/4;
LCD_Pwr_Initialze();
Start_Up_Screen ();
Power_On_Chk ();
while (TRUE)
{
Seconds = 0; // clear all global variables before next test
Interrupt_Flag = 0;
interruption_time = 0;
executed_time = 0;
RTC_Initialize();
lcd_gotoxy (7,2);
printf (lcd_putc, "READY ! "); //do nothing
while (input(START_SW) == 1)
{
;
}
clear_interrupt(int_timer1);
set_timer1(0);
clear_interrupt(INT_EXT);
enable_interrupts(GLOBAL);
while (input(STOP_SW) == 1)
{
/* delay_ms(100);
lcd_gotoxy (7,2);
printf (lcd_putc, "\\");
delay_ms(100);
lcd_gotoxy (7,2);
printf (lcd_putc, "|");
delay_ms(100);
lcd_gotoxy (7,2);
printf (lcd_putc, "/");
*/
;
}
temp = get_timer1() + (INTERNAL_FREQUENCY - Inst_Cycle_Per_Second);
printf ("Internal Frequency Loop: %Ld\n\r", INTERNAL_FREQUENCY);
printf ("Instruction Cycle: %Ld\n\r", Inst_Cycle_Per_Second);
printf ("Timer 1: %Ld\n\r", get_timer1());
// temp = get_timer1() + (INTERNAL_FREQUENCY - Inst_Cycle_Per_Second);
printf ("temp_val: %Ld \n\r",temp);
executed_time = temp * (1/INTERNAL_FREQUENCY);
printf ("Executed Time: %4.3f \n\r",executed_time);
delay_time = Seconds + executed_time;
lcd_gotoxy (7,2);
printf (lcd_putc, "%6.5f \n",delay_time);
printf ("Delay Time: %7.7f \n\r",delay_time);
while (input(RESET_SW) == 1)
{
;//do nothing and wait for reset switch pressed to start new test
}
// for (i = 0; i <=10; i++)
// {
// printf (lcd_putc, "\b"); //clear lcd screen
Start_Up_Screen ();
// }
} //end of main while loop
}//end of main
/******************************************************************************
****** 16x2 LCD first line address 0x00
****** second line address 0x40
*******************************************************************************
*/
void LCD_Pwr_Initialze(void)
{
lcd_init();
printf (lcd_putc, "\fInitialize!\nPlease Wait");
delay_ms (1000);
}
void Start_Up_Screen (void)
{
printf (lcd_putc, "\fFUZE DELAY TIMER");
printf (lcd_putc, "\nTime: READY ! \n");
}
/*******************************************************************
** function that check the status of all i/o at power on. **
** Pin_B0 = 1 = good; Pin_B0 = 0 = bad; Message: Start SW Error **
** Pin_B1 = 1 = good; Pin_B1 = 0 = bad; Message: Stop SW Error **
********************************************************************
*/
void Power_On_Chk (void)
{
char error_flag = 0;
do
{
if (input(START_SW) == 0)
{
lcd_gotoxy(0,2);
printf (lcd_putc, "\fStart Switch Error");
error_flag = 1;
}
else
if (input(STOP_SW) == 0)
{
lcd_gotoxy(0,2);
printf (lcd_putc, "\fStop Switch Error");
error_flag = 1;
}
} while (error_flag != 0);
}
void RTC_Initialize (void)
{
Inst_Cycle_Per_Second = INTERNAL_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
clear_interrupt(int_timer1);
disable_interrupts(GLOBAL);
}
Final_Delay_Time ()
{
float delay_time = 0, i = 0.0000005;
int32 temp;
temp = get_timer1() + (INTERNAL_FREQUENCY - Inst_Cycle_Per_Second);
printf ("Internal Frequency Loop: %Ld\n\r", INTERNAL_FREQUENCY);
printf ("Instruction Cycle: %Ld\n\r", Inst_Cycle_Per_Second);
printf ("Timer 1: %Ld\n\r", get_timer1());
// temp = get_timer1() + (INTERNAL_FREQUENCY - Inst_Cycle_Per_Second);
printf ("temp_val: %Ld \n\r",temp);
executed_time = temp * i;
printf ("Executed Time: %7.6f \n\r",executed_time);
delay_time = Seconds + executed_time;
lcd_gotoxy (7,2);
printf (lcd_putc, "%7.7f \n",delay_time);
printf ("Delay Time: %7.7f \n\r",delay_time);
Blink_LED (3,100);
return(delay_time);
}
void Blink_LED (int8 number_flash, int flash_duty_cycle)
{
char i;
for ( i = 0; i <= number_flash; i++)
{
output_high (ERROR_LED);
delay_ms (flash_duty_cycle);
output_low (ERROR_LED);
delay_ms (flash_duty_cycle);
}
}
#int_TIMER1
void TIMER1_isr(void)
{
Inst_Cycle_Per_Second -= 65536; // Decrement ticker by clocks per interrupt
// interruption_time++;
output_toggle (TMR_INT);
if ( Inst_Cycle_Per_Second < 65536 ) // If second has expired
{
Inst_Cycle_Per_Second += INTERNAL_FREQUENCY; // Increment ticker by clocks per second
Seconds++; // Increment number of seconds
// interruption_time = 0;
}
}
#int_EXT
void EXT_isr(void)
{
output_high (EXT_INT);
if (input(STOP_SW)==0)
{
if (input (STOP_SW) == 0)
{
Interrupt_Flag = 0b00000001;
disable_interrupts(GLOBAL);
}
}
else
{
while (true)
{
output_toggle (ERROR_LED);
my_time_ms (10,20,30);
}
}
}
void my_time_ms (char i,j,k)
{
char x,y,z;
for (x =0; x <= i; x++)
{
for (y=0;y<=j;y++)
{
for (z=0;z<=k;z++)
{
;
}
}
}
}
|
Above is my completed test code that has problem in timing.
PCM programmer,
My input test signal is an actual switch. It pulls the RA2 to ground to start the count.
The stop button is also an actual switch that pull the RB0 to ground.
The voltage level at each pins is 5.0v. When I pressed any button, it goes to ground and trembling for about 100uS.
As far as assembly language goes, I have the code (write with Microchip assembly) that polling at RA2 to start the time and it just go as soon as the 5v line drop to 0v and ignore the switch bouncing.
My concern, why there is such a large delay offset ? I try to find out what cause the offset.
andrewg,
I do consider contact bounce however, in my application if I do the debounce, I lost the actual switch contact starting at the very first contact. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Jun 06, 2011 2:25 pm |
|
|
You have this enormous program and all you want to do is measure the
time between two events. I confess I didn't try to understand it all.
But I'm sure it can be done with less code.
What's the range of time intervals that you want to be able to measure ?
What is the minimum expected time, and the maximum expected time ?
Is it from 1ms up to 10 seconds, or what ? |
|
|
olivier
Joined: 08 Apr 2010 Posts: 11
|
|
Posted: Wed Jun 08, 2011 8:45 pm |
|
|
PCM PRogrammer,
Yes, my program is massive and not effective. as of right now, I am a very very very new and learn every line in coding so effectiveness isn't there at all. I do take your mocking however, it is a good critic in away for me to push myself more in learning and more efficient.
However, the time I would like to measure is such
start switch pressed
time starts
print time on lcd while wait for interruption on external interrupt line RB0 which connect to stop switch.
stop switch pressed
time stop
calculate time and print to lcd
i need to display time from 0.0001 second to 15 seconds.
my code is long and ridiculous for a simple function of a stop watch. |
|
|
Fusillade
Joined: 02 Aug 2007 Posts: 31
|
|
Posted: Thu Jun 09, 2011 6:36 am |
|
|
olivier wrote: | PCM PRogrammer,
Yes, my program is massive and not effective. as of right now, I am a very very very new and learn every line in coding so effectiveness isn't there at all. I do take your mocking however, it is a good critic in away for me to push myself more in learning and more efficient.
However, the time I would like to measure is such
start switch pressed
time starts
print time on lcd while wait for interruption on external interrupt line RB0 which connect to stop switch.
stop switch pressed
time stop
calculate time and print to lcd
i need to display time from 0.0001 second to 15 seconds.
my code is long and ridiculous for a simple function of a stop watch. |
Just a quick glance, it appears that the external interrupt is disabled and that you are just looping on the status of the stop switch. As a result, the accuracy of the switch press doesn't seem like it could be any better than 300mS.
Before you start looping on the stop switch, add this code and tell me what happens.
Code: | ...
clear_interrupt(int_timer1);
set_timer1(0);
clear_interrupt(INT_EXT);
enable_interrupts(INT_EXT); // NEW LINE
enable_interrupts(GLOBAL);
while(input(STOP_SW) == 1)
{
... |
You might also consider just setting a flag in the interrupt routine and looping on the flag status instead of the input switch. It is possible to press and release the switch before the loop is complete.
If I missed where you enable INT_EXT, I apologize in advance. _________________ New:
Compiler Version: 5.078
IDE Version: MPLAB X V4.15
Devices: PIC18LF****
Old:
Compiler Version: 4.121
IDE Version: MPLAB IDE V8.63
Devices: PIC18LF**** |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Jun 09, 2011 12:45 pm |
|
|
I would do it with the CCP modules. Switch 1 would be on CCP1, and
switch 2 on CCP2. Each CCP would be set to trigger on the falling edge
of the switch. This is the first edge that occurs when the switch is pressed.
(You might need to debounce it with an external RC circuit). I would
extend Timer1 to 24 or 32 bits by adding an #int_timer1 routine to
increment the upper byte (or word). |
|
|
|
|
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
|