PSoC 4 Timer Counter question

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

cross mob
DaKo_463136
Level 5
Level 5
10 likes received 10 likes given 5 likes given

Hello,

I would like to ask for help with Timer Counter setup for the following situation.

I need to measure a duty cycle of a signal (or just measure for how long was a signal low in the past 30 s). The minimum pulse width is 10 us and the signal is logic high by default and logic low when I need to measure it. There is more than one pulse for 30 s period. (Actually I need to process two input signals using the same principle concurrently.)

My initial thoughts were to let the signal trigger (by a falling edge) a start of the timer and stop it with the rising edge. Do this 30 times (store in SW in a circular buffer) and then create an average for the these 30 samples. The timer could be clocked with 1 MHz clock, for example.

Do you have any suggestions or ideas how to setup the Timer Counter component? I lost myself in the component datasheet. Or would do this differently?

Thank you,

David

0 Likes
1 Solution
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,

Following is my trial sample.

To make the calculation easier, I chose 10MHz for PWM, which generates the test signal,

but the actual accuracy was 9.6MHz +/- 2%, which affects the count, but I hope this is enough for POC.

schematic

002-schematic.JPG

UART and PWM are for testing

main.c

use measure_sec in main() to specify how many seconds to meausre.

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

#include "project.h"

#include "stdio.h"

uint32_t count_value = 0 ;

char str[128] ; /* print buffer */

void print(char *str)

{

    UART_UartPutString(str) ;

}

CY_ISR(counter_overflow_isr)

{

    counter_int_ClearPending() ;

    count_value += Counter_ReadPeriod() ;

}

void init_hardware(void)

{

    CyGlobalIntEnable; /* Enable global interrupts. */

    UART_Start() ;

    Counter_Init() ;

    PWM_Start() ;

    counter_int_StartEx(counter_overflow_isr) ;

}

void splash(void)

{

    sprintf(str, "Timer Counter Test (%s %s)\n", __DATE__, __TIME__) ;

    print(str) ;

}

uint32_t measure_low(int wait_sec)

{

    uint32_t delay ;

  

    delay = wait_sec * 1000 ; /* count clock is 1MHz */

    count_value = 0 ;

    counter_reset_Write(1) ;

    CyDelayUs(10) ;

    counter_reset_Write(0) ;

    Counter_WriteCounter(0) ;

    Counter_Start() ;

    CyDelay(delay) ; /* wait 30sec */

      

    Counter_Stop() ;

    count_value += Counter_ReadCounter() ;

    return( count_value ) ;

}

int main(void)

{

    uint32_t period, compare ;

    int measure_sec = 30 ;

    int div = 2 ;

  

    init_hardware() ;

  

    splash() ;

    for(;;)

    {

        period = PWM_ReadPeriod() ;

        compare = period / div ;

        PWM_WriteCompare(compare) ;

        sprintf(str, "PWM %d/%d @ 10MHz, measuring for %d sec\n", compare, period, measure_sec) ;

        print(str) ;

        sprintf(str, "Count of low is %d\n", measure_low(measure_sec)) ;

        print(str) ;

        div *= 2 ;

        if ((period / div) == 0) {

            div = 2 ;

        }

    }

}

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

measuring each 1 second

000-TeraTerm-1sec.JPG

Measuring each 30 seconds

001-TeraTerm-30sec.JPG

moto

View solution in original post

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,

Following is my trial sample.

To make the calculation easier, I chose 10MHz for PWM, which generates the test signal,

but the actual accuracy was 9.6MHz +/- 2%, which affects the count, but I hope this is enough for POC.

schematic

002-schematic.JPG

UART and PWM are for testing

main.c

use measure_sec in main() to specify how many seconds to meausre.

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

#include "project.h"

#include "stdio.h"

uint32_t count_value = 0 ;

char str[128] ; /* print buffer */

void print(char *str)

{

    UART_UartPutString(str) ;

}

CY_ISR(counter_overflow_isr)

{

    counter_int_ClearPending() ;

    count_value += Counter_ReadPeriod() ;

}

void init_hardware(void)

{

    CyGlobalIntEnable; /* Enable global interrupts. */

    UART_Start() ;

    Counter_Init() ;

    PWM_Start() ;

    counter_int_StartEx(counter_overflow_isr) ;

}

void splash(void)

{

    sprintf(str, "Timer Counter Test (%s %s)\n", __DATE__, __TIME__) ;

    print(str) ;

}

uint32_t measure_low(int wait_sec)

{

    uint32_t delay ;

  

    delay = wait_sec * 1000 ; /* count clock is 1MHz */

    count_value = 0 ;

    counter_reset_Write(1) ;

    CyDelayUs(10) ;

    counter_reset_Write(0) ;

    Counter_WriteCounter(0) ;

    Counter_Start() ;

    CyDelay(delay) ; /* wait 30sec */

      

    Counter_Stop() ;

    count_value += Counter_ReadCounter() ;

    return( count_value ) ;

}

int main(void)

{

    uint32_t period, compare ;

    int measure_sec = 30 ;

    int div = 2 ;

  

    init_hardware() ;

  

    splash() ;

    for(;;)

    {

        period = PWM_ReadPeriod() ;

        compare = period / div ;

        PWM_WriteCompare(compare) ;

        sprintf(str, "PWM %d/%d @ 10MHz, measuring for %d sec\n", compare, period, measure_sec) ;

        print(str) ;

        sprintf(str, "Count of low is %d\n", measure_low(measure_sec)) ;

        print(str) ;

        div *= 2 ;

        if ((period / div) == 0) {

            div = 2 ;

        }

    }

}

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

measuring each 1 second

000-TeraTerm-1sec.JPG

Measuring each 30 seconds

001-TeraTerm-30sec.JPG

moto

Thank you very much for your answer. I am still working on other parts of the design, so I haven't tried it out.

Here is my evaluation so far:

1) Your solution - use a Counter and a Frequency divider.

2) Use a Timer and a hardware pin to enable it. One disadvantage is that it counts only down, but the difference between two values can be easily subtracted.

3) TimerCounter would be a great component, BUT it is only 16 bit, which is too low for me (need at least 32 bits). I haven't used a microcontroller with a 32-bit PWM module, yet.

4) Counter alone can be only used for counting the edges, not the period.

I will try both 1 and 2 and decide later.

David

0 Likes
DaKo_463136
Level 5
Level 5
10 likes received 10 likes given 5 likes given

Just in case anyone stumbles upon this thread.

I just ruled out case 2 (described in my previous post), because I am only able to use 1 UDB 32-bit timer on CY8C4245AXI-483. (And I need to measure 2 signals simultaneously.) I find it kind of surprising - seems like there is no 32-bit HW timer in this PSoC. I thought it is a top of the 4200 line.

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

Hi,

If you need a couple of 32-bit timer(s) you could

(1) Use 4200L line

(2) Use 16bit counter and use its overflow interrupt to let the software count the upper 16bit

IMHO, (1) will be easier, but (2) will be more economical.

moto

Thank you for your replies.

I will need to switch to another device anyway. When trying to use CY8C4245AZI or CY8C4247AZI, I run out of Datapath cells.

My schematics for two channels sensing is this:

pastedImage_0.png

A the Resource meter says:

pastedImage_1.png

David

0 Likes