Timer_Counter too slow

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
lock attach
Attachments are accessible only for community members.
MuKa_284621
Level 3
Level 3

Hello,

I've created a project that is essentially a pulse generator. It is implemented using the TCPWM block set as a Timer Counter. I'm using the CY8CKIT-042 Pioneer Kit.

The count frequency is set to 20 kHz (50 us between counts) and it runs continuously. What I did was the following:

1) Init Compare register of the counter with a first value.

2) After the counter reaches the set value, the compare register performs a swap with the Compare Buffer. This is done by ticking the option given in the Counter tab.

3) An interrupt is signaled at the time of compare equal, and it updates the Compare Buffer with the next value (with a counter increment after update).

4) The signal from the cc output of the TCPWM was hooked to the reload input in order to reset the counter.

All the compare values are below 20000, so in theory I expect to get a pulse every less than a second or so. But in this setting, I had about 2-3 seconds interval before the next pulse arrives. To make sure it wasn't the compare value that I got wrong, I used 20000 as a fixed value in both Compare and Compare Buffer registers (without any update of these values) and it still outputs one pulse every 3 seconds.

I'm wondering if I did something wrong. I attach the project in this post. UART is for debug. Alternatively, you can reroute HR_Out_Pin to the polychromatic LED pins.

Thanks,

0 Likes
1 Solution
lock attach
Attachments are accessible only for community members.
Ekta_N
Moderator
Moderator
Moderator
750 replies posted First like given 250 solutions authored

Hello

The pulse takes 2 to 3 seconds interval to arrive in the initial project because although the compare buffer values are being continuously changed, the period value remains a constant 65535 (i.e., reload does not happen) as shown in the figure below:

pastedImage_0.png

The interrupt will be generated once the counter value equals the compare value but this will happen only once during a period. This is because even after the interrupt is generated the counter will keep on incrementing upto the maximum value and reload only after that. Thus the interrupt interval will be around 65535/20000 = 3.27 sec

In order to generate pulse within 1 or less than 1 sec (depending upon the hrCountVal), we need to change the 'period' value also along with the compare value.

In order to do this we need to use the API: HR_Trigger_Counter_WritePeriod(hrCountVal[hrCountIdx++]); in the sampling part of the code

pastedImage_5.png

Also set the initial period, compare value and compare buffer value as 20000 as shown in the figure below.

pastedImage_4.png

I have attached the modified project below.

Regards

Ekta

View solution in original post

0 Likes
5 Replies
lock attach
Attachments are accessible only for community members.
MotooTanaka
Level 9
Level 9
Distributor - Marubun (Japan)
First comment on blog Beta tester First comment on KBA

Hi,

I notices some points I'd like to suggest to change

(1) make index which is updated in the ISR to volatile

volatile uint16 hrCountIdx = 0; // modified

(2) WriteCompareBuf should be changed to WriteCompare

(3) The reload may not working correctly, so I added WriteCounter(0) ;

(4) Do not put UartPutString() inside an ISR instead I used the red led.

At least the LED's on/off interval seems to be around 1sec or less on my CY8CKIT-042.

so my modified main.c looked like

===============

/* Heart-Rate Sensor

*

* Muhammad Haziq Kamarul Azman

* Universiti Kuala Lumpur

* British Malaysian Institute

*

*/

#include <device.h>

#define HR_COUNTER_IDX_NUM 748

uint16 hrCountVal[HR_COUNTER_IDX_NUM] = {

/* removed to make it shorter to display here */

17425,  17689,  17749,  17423,  17342,  17620 };

volatile uint16 hrCountIdx = 0; // modified

CY_ISR_PROTO(HR_Update_Swap_Int_EXISR);

CY_ISR(HR_Update_Swap_Int_EXISR)

{

//    HR_Trigger_Counter_WriteCompareBuf(hrCountVal[hrCountIdx]) ;

    HR_Trigger_Counter_WriteCompare(hrCountVal[hrCountIdx]) ;

    HR_Trigger_Counter_WriteCounter(0) ;

    hrCountIdx = (hrCountIdx + 1) % HR_COUNTER_IDX_NUM ;

  

    LED_Write(!LED_Read()) ;

//    Comm_UART_UartPutString("Sample!\r\n");

    HR_Update_Swap_Int_ClearPending();

    HR_Trigger_Counter_ClearInterrupt(HR_Trigger_Counter_INTR_MASK_CC_MATCH);

}

int main(void)

{

    CyGlobalIntEnable;  // Enable global interrupts.

  

    /* Initialization */

    HR_Sample_Clock_Start();

    HR_Update_Swap_Int_StartEx(HR_Update_Swap_Int_EXISR);

    Comm_UART_Start();

    Comm_UART_UartPutString("Starting\r\n");

  

    /* Start sampling*/

    HR_Trigger_Counter_WriteCompare(20000);//hrCountVal[hrCountIdx++]);

    HR_Trigger_Counter_Start();

  

    while(1);

}

===============

moto

0 Likes
lock attach
Attachments are accessible only for community members.
MotooTanaka
Level 9
Level 9
Distributor - Marubun (Japan)
First comment on blog Beta tester First comment on KBA

Hi,

After posting previous response, I felt having reload, which is not working uneasy.

So I modified your project like below

Schematic

000-schematic.JPG

Since you are using TCPWM as a timer, let's use "period" for the control

so that when period hits, TC is asserted and reload is automatically done

001-Timer_config_1.JPG

002-Timer_config_2.JPG

Then I set the initial period to 20000, instead of 65535.

And I modified your ISR as

======================

CY_ISR(HR_Update_Swap_Int_EXISR)

{

    period = hrCountVal[hrCountIdx] ;

//    HR_Trigger_Counter_WritePeriod(period) ;

    HR_Trigger_Counter_WritePeriodBuf(period) ;

    hrCountIdx = (hrCountIdx + 1) % HR_COUNTER_IDX_NUM ;

  

    LED_Write(!LED_Read()) ;

    HR_Update_Swap_Int_ClearPending();

    HR_Trigger_Counter_ClearInterrupt(HR_Trigger_Counter_INTR_MASK_TC) ;

}

======================

I tried both

    HR_Trigger_Counter_WritePeriod(period) ;

and

    HR_Trigger_Counter_WritePeriodBuf(period) ;

for my human sense I did not notice difference,

but may be WritePeriodBuf() can set more exact timing.

And let main report the change of the period

======================

int main(void)

{

    CyGlobalIntEnable;  // Enable global interrupts.

  

    Comm_UART_Start();

    sprintf(str, "Starting (%s %s)\r\n",__DATE__, __TIME__);

    print(str) ;

    /* Initialization */

    HR_Sample_Clock_Start();

    HR_Update_Swap_Int_StartEx(HR_Update_Swap_Int_EXISR);

    /* Start sampling*/

    HR_Trigger_Counter_WritePeriod(period);//hrCountVal[hrCountIdx++]);

    HR_Trigger_Counter_Start();

  

    while(1) {

        if (period != prev_period) {

            sprintf(str, "period %d\r\n", period) ;

            print(str) ;

            prev_period = period ;

        }

    }

}

======================

Then Tera Term log was

003-TeraTerm-Log.JPG

moto

0 Likes
lock attach
Attachments are accessible only for community members.
Ekta_N
Moderator
Moderator
Moderator
750 replies posted First like given 250 solutions authored

Hello

The pulse takes 2 to 3 seconds interval to arrive in the initial project because although the compare buffer values are being continuously changed, the period value remains a constant 65535 (i.e., reload does not happen) as shown in the figure below:

pastedImage_0.png

The interrupt will be generated once the counter value equals the compare value but this will happen only once during a period. This is because even after the interrupt is generated the counter will keep on incrementing upto the maximum value and reload only after that. Thus the interrupt interval will be around 65535/20000 = 3.27 sec

In order to generate pulse within 1 or less than 1 sec (depending upon the hrCountVal), we need to change the 'period' value also along with the compare value.

In order to do this we need to use the API: HR_Trigger_Counter_WritePeriod(hrCountVal[hrCountIdx++]); in the sampling part of the code

pastedImage_5.png

Also set the initial period, compare value and compare buffer value as 20000 as shown in the figure below.

pastedImage_4.png

I have attached the modified project below.

Regards

Ekta

0 Likes

Hello,

Thanks for the replies (also to Tanaka).

The thing about the counter not stopping makes sense (also answers why the period is roughly 3 secs).

However, I don't understand why the reload input is not working. I might be wrong about the cc output being a pulse.

Anyone knows about this issue?

0 Likes
MotooTanaka
Level 9
Level 9
Distributor - Marubun (Japan)
First comment on blog Beta tester First comment on KBA

Hi,

I tried to measure what was happening

with slightly modified schematic.

000-schematic-190730.JPG

I probed LED(P1[1]) pin and HR_Out_Pin (P0[2])

The pulse at CC (HR_Out_Pin) was

cc_pulse.jpg

pulse width was about 136ns (= 7.353MHz),

where the clock to the counter is 24MHz divided by 1200 = 20KHz?

So this pulse will be very difficult to be caught by the counter.

Meantime, I measured the delay from the pulse to the LED(ISR assignment)

pulse2intr.jpg

The delay was about 5+ us.

So resetting counter from ISR may be slow.

If we compare it with 20kHz (= 50us), it may be ignored.

But I'd rather let the hardware reset (or reload) the counter.

So I prefer to use counter period with which at TC the reload will take place automatically by the hardware

instead of using compare which will cause some delay before we can do something to reset the counter.

moto

0 Likes