cancel
Showing results for 
Search instead for 
Did you mean: 

PSoC 5, 3 & 1 MCU

CaDu_3933941
New Contributor II

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
MotooTanaka
Esteemed Contributor

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
New Contributor II

Have a look into this thread.

Bob

0 Likes
MotooTanaka
Esteemed Contributor

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