PSoC 5LP Duty Cycle

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

cross mob
CaDu_3933941
Level 4
Level 4
50 replies posted 25 replies posted 10 replies posted

Hi all,

For my current project, I require to be able to read the pulse width of a PWM signal and store it in a variable using a PSoC 5LP. I would appreciate the help if anyone offered me any method on how to do this efficiently.

Thanks

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,

It took me a few days to implement this with CY8CKIT-059.

There may (must) be better strategies, but this is the way I made it.

At first I was trying to implement a state machine which advances state in each edge of the input signal,

after all, I could not make it work well. (May be I'll try it again someday)

Then I changed my strategy to use a couple of counters,

one for counting "High" level and the other for "Low" level.

With Rising Edge of the input signal,

High Level counter gets reset and start counting,

Low Level counter gets "capture" signal

With Falling Edge of the input signal

High Level counter gets "capture" signal

Low Level counter gets reset and start counting.

The schematic seems as

001-schematic.JPG

companion schematics

Test PWM signal Generator

002-PWM_GEN.JPG

UART as usual

003-UART.JPG

Pin Assignment

004-pin_assignment.JPG

main.c

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

/**

* Duty Cycle Count Test

*/

#include "project.h"

#include "stdio.h"

volatile uint16_t h_count = 0 ;

volatile uint16_t l_count = 0 ;

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

void print(char *str)

{

    UART_PutString(str) ;

}

void splash(void)

{

    sprintf(str, "Duty Cycle Count Test (%s %s)\n", __DATE__, __TIME__) ;

    print(str) ;

}

CY_ISR(isr_H_callback)

{

    h_count = H_Counter_ReadCapture() ;

    isr_H_ClearPending() ;

    H_Counter_Enable() ;

}

CY_ISR(isr_L_callback)

{

    l_count = L_Counter_ReadCapture() ;

    isr_L_ClearPending() ;

    L_Counter_Enable() ;

}

void config_pwm(uint16_t period, uint16_t compare)

{

    PWM_Stop() ;

    PWM_WriteCounter(0) ;

    PWM_WritePeriod(period) ;

    PWM_WriteCompare(compare) ;

    PWM_Start() ;   

}

void init_hardware(void)

{

    Control_Reg_Write(1) ;

    CyDelayUs(10) ;

    Control_Reg_Write(0) ;

   

    UART_Start() ;

    H_Counter_Start() ;

    L_Counter_Start() ;

   

    H_Counter_Enable() ;

    L_Counter_Enable() ;

   

    isr_H_ClearPending() ;

    isr_L_ClearPending() ;

   

    isr_H_StartEx(isr_H_callback) ;

    isr_L_StartEx(isr_L_callback) ;

   

    CyGlobalIntEnable; /* Enable global interrupts. */   

}

void print_duty(uint16_t period, uint16_t compare)

{

    uint16_t LW, HW ;

    float duty ;

    LW = l_count ;

    HW = h_count ;

    sprintf(str, "PWM %d/%d ", compare, period) ;

    print(str) ;

    sprintf(str, "Duty = %d:%d ", HW, LW) ;

    print(str) ;

    duty = (float)HW / (float)(HW + LW) ;

    sprintf(str, "%d.%02d %%\n", (int)(100 * duty), (int)(10000 * duty) % 100) ;

    print(str) ;

}

int main(void)

{

    uint16_t period = 10000 ;

    uint16_t compare = 5000 ;

   

    init_hardware() ;   

    splash() ;

    config_pwm(period, compare) ;

    CyDelay(1000) ;

       

    for(;;)

    {

        print_duty(period, compare) ;

       

        compare += 100 ;

        if (compare > period) {

            compare = 0 ;

        }

       

        config_pwm(period, compare) ;

        CyDelay(1000) ;

    }

}

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

Tera Term Log

000-TeraTerm-log.JPG

I'm glad that it's Friday!

moto

View solution in original post

2 Replies
BoMa_4329931
Level 3
Level 3
First like received

Have a look into this thread.

Bob

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,

It took me a few days to implement this with CY8CKIT-059.

There may (must) be better strategies, but this is the way I made it.

At first I was trying to implement a state machine which advances state in each edge of the input signal,

after all, I could not make it work well. (May be I'll try it again someday)

Then I changed my strategy to use a couple of counters,

one for counting "High" level and the other for "Low" level.

With Rising Edge of the input signal,

High Level counter gets reset and start counting,

Low Level counter gets "capture" signal

With Falling Edge of the input signal

High Level counter gets "capture" signal

Low Level counter gets reset and start counting.

The schematic seems as

001-schematic.JPG

companion schematics

Test PWM signal Generator

002-PWM_GEN.JPG

UART as usual

003-UART.JPG

Pin Assignment

004-pin_assignment.JPG

main.c

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

/**

* Duty Cycle Count Test

*/

#include "project.h"

#include "stdio.h"

volatile uint16_t h_count = 0 ;

volatile uint16_t l_count = 0 ;

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

void print(char *str)

{

    UART_PutString(str) ;

}

void splash(void)

{

    sprintf(str, "Duty Cycle Count Test (%s %s)\n", __DATE__, __TIME__) ;

    print(str) ;

}

CY_ISR(isr_H_callback)

{

    h_count = H_Counter_ReadCapture() ;

    isr_H_ClearPending() ;

    H_Counter_Enable() ;

}

CY_ISR(isr_L_callback)

{

    l_count = L_Counter_ReadCapture() ;

    isr_L_ClearPending() ;

    L_Counter_Enable() ;

}

void config_pwm(uint16_t period, uint16_t compare)

{

    PWM_Stop() ;

    PWM_WriteCounter(0) ;

    PWM_WritePeriod(period) ;

    PWM_WriteCompare(compare) ;

    PWM_Start() ;   

}

void init_hardware(void)

{

    Control_Reg_Write(1) ;

    CyDelayUs(10) ;

    Control_Reg_Write(0) ;

   

    UART_Start() ;

    H_Counter_Start() ;

    L_Counter_Start() ;

   

    H_Counter_Enable() ;

    L_Counter_Enable() ;

   

    isr_H_ClearPending() ;

    isr_L_ClearPending() ;

   

    isr_H_StartEx(isr_H_callback) ;

    isr_L_StartEx(isr_L_callback) ;

   

    CyGlobalIntEnable; /* Enable global interrupts. */   

}

void print_duty(uint16_t period, uint16_t compare)

{

    uint16_t LW, HW ;

    float duty ;

    LW = l_count ;

    HW = h_count ;

    sprintf(str, "PWM %d/%d ", compare, period) ;

    print(str) ;

    sprintf(str, "Duty = %d:%d ", HW, LW) ;

    print(str) ;

    duty = (float)HW / (float)(HW + LW) ;

    sprintf(str, "%d.%02d %%\n", (int)(100 * duty), (int)(10000 * duty) % 100) ;

    print(str) ;

}

int main(void)

{

    uint16_t period = 10000 ;

    uint16_t compare = 5000 ;

   

    init_hardware() ;   

    splash() ;

    config_pwm(period, compare) ;

    CyDelay(1000) ;

       

    for(;;)

    {

        print_duty(period, compare) ;

       

        compare += 100 ;

        if (compare > period) {

            compare = 0 ;

        }

       

        config_pwm(period, compare) ;

        CyDelay(1000) ;

    }

}

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

Tera Term Log

000-TeraTerm-log.JPG

I'm glad that it's Friday!

moto