cancel
Showing results for 
Search instead for 
Did you mean: 

Why measured pulse width using TIMER accumulates error as pulse width increases? (understanding inaccuracies in TIMER)

sarojj7
Associate III

Dear All,

Board: Nucleo - H745ZI-Q

What am I trying to do ?

I am trying to measure pulse width of an signal using counter mode of timer 2, as accurately as possible. The input pulse width varies from 1 us to 1000 us.

What have I done?

I configure the Timer 2 in counter mode.

I configure the timer2 with ARR = 0xFFFFFFFF, PSC = 0xC8-1, thus effective timer clock is 1MHz.

I monitor a GPIO pin(which is normally high) in busy loop for zero, when I get zero, I reset the clock and monitor the pin again in busy loop till high again , the Timer count gives the pulse width.

 Initializing Timer

void initTimer2Counter()
{
	// Enable the TIM2 clock.	
	RCC -> APB1LENR |= RCC_APB1LENR_TIM2EN;
	TIM2->CR1 &= ~(TIM_CR1_DIR | TIM_CR1_CMS); /* Select the up counter mode */
	TIM2->CR1 &= ~TIM_CR1_CKD;	
	TIM2->ARR = 0xFFFFFFFF; /* Set the Autoreload value */
	//TIM2->PSC = 0xA - 1; /* Set the Prescaler value */	
	TIM2->PSC = 0xC8 - 1; /* Set the Prescaler value, 1MHz*/
	//TIM2->PSC = 0x28 - 1; /* Set the Prescaler value, 5MHz*/
	TIM2->EGR  |= TIM_EGR_UG;
	TIM2->SMCR = RESET; /* Configure the Internal Clock source  or zero , slave mode disabled and trigger source is internal*/
	TIM2->SR = 0;
	TIM2->CR1 |= TIM_CR1_CEN;	/* Enable the TIM peripheral */// use this in main code to start the timer just before firing first stage
 
}

Waiting for pin to go zero in main

while(GPIOA->IDR & 1<<0);
pulseWidth = count1();

Pulse width measurement

unsigned int count1(void)
{
	TIM2->EGR = 1;//reset
	while(!(GPIOA->IDR & 1<<0) );		
	return (TIM2->CNT);
}

Issue:

The measured pulse width(pulseWidth Variable) is

9 us for 10 us input

above 10 till 100 us, reading is same as input.

after this approximately after every 100 us increase in input measured value increases by 1 us, that is for 200 it reads 202 us, for 300, its 303 us, for 400 its 404 us, 500 it reads 505 us. It is strange.

i have tried increasing the the clock resolution upto 20MHZ, but nothing changes. Initially I thought that inaccuracy in TIMER clock might be the issue, but then output is consistent over multiple readings (variation is +/- 1 uS)

Questions:

Why is it happening, is there something in code that causing it?

If TIMER2 is inherently this much inaccurate, how can measure Pulse width more accurately?

Kindly help.

Thank You

6 REPLIES 6
GwenoleB
ST Employee

Hello @sarojj7​,

I advice you to use input capture feature. While timer is counting, at each rising/falling or both edges, the counter value is copied in CCRx register.

You could refer to AN4776 which explain from section 2.3 to 2.6 how to implement this such of application.

Feel free to ask for more details or questions.

Best Regards,

Gwénolé

What is the primary clock source?

Note, that STLink3's MCO output at its default 8MHz output setting is derived from HSI, i.e. imprecise RC oscillator.

https://community.st.com/s/question/0D50X0000BiD6fISQS/stlink-provides-808-mhz-instead-of-8000-on-new-nucleoh743zi2

JW

TDK
Guru

> The measured pulse width(pulseWidth Variable) is

9 us for 10 us input

above 10 till 100 us, reading is same as input.

after this approximately after every 100 us increase in input measured value increases by 1 us, that is for 200 it reads 202 us, for 300, its 303 us, for 400 its 404 us, 500 it reads 505 us. It is strange.

Seems okay, just have a clock source that is 1% off, which if you're using the HSI as a clock source seems reasonable. A crystal will be more accurate.

Your measurement isn't great as it has some overhead. You could let the timer free-roll instead of resetting it to avoid this, and take the difference in values to capture the pulse width.

As stated above, input capture is the better method here.

If you feel a post has answered your question, please click "Accept as Solution".

Thank you.

I am aware of this method. But input capture feature gives me limited options for using pins and my application has lots of such pulse widths coming from different sources. Also, I am using many pins for functionalities like Key board and LCD. Thus I am kind of forced to use this method. Nonetheless, I shall reassess my requirements and give the suggested method a try and report.

Thanks again for the help.:face_with_tears_of_joy:

Thank you.

I notice that all of them report having found a clock value more than 8 , that is 8.002, 8.005 etc. MHZ. In such case, I wonder I should get measured pulse width less than the actual, like for example 495/496 us fr 500uS input. Isn't it.

In the meantime, I am trying to change the primary source from HSI to something more accurate as suggested by @TDK​ 

GLASS
Senior

Hi, adding (3) to the 2 already answered by decreasing priority:

  1. Clock accuracy, consider HSE,
  2. Timer input capture,
  3. If pin constrain imply using some sort of "busy loop", you must consider the probability of interrupt impact on busy loop...may be using gpio interrupt and CARREFULLY manage interrupt priority​ to avoid bad latency.