To dim LED

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

cross mob
UlMo_4589691
Level 1
Level 1
First like given

Hello,

now I have a touch sensor and a LED. The touch sensor enables the LED. Now I want to preset the brightness of the LED. How can I do this?

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 was my mistake, before setting period PWM_Start() or PWM_Init() must have been called.

Note: PWM_Init() is called at the first time PWM_Start() is called

003-pwm_start.JPG

And in the PWM_Init(), period is overwritten to the value set in the GUI.

So I should have written

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

PWM_Start() ;

PWM_Stop() ; /* before changing the period, PWM must be stopped */

PWM_WritePeriod(PWM_PERIOD) ;

PWM_WriteCompare(led_level) ;

PWM_Start() ;

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

To test if PWM_WritePeriod() really works,

I made following test program.

schematic

001-schematic.JPG

pins

002-pins.JPG

main.c

Note: To handle UART interactions I cheated by using my tty_utility

tty_utils a utility sample for CLI type program

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

#include "project.h"

#include "stdio.h"

#include "tty_utils.h"

#define PWM_PERIOD 1000 /* 65535 (0xFFFF) was too much for this purpose */

#define LED_OFF       0

#define LED_DIM      10 /* could be anywhere from 1 to 1000 */

uint16_t led_period = PWM_PERIOD ;

uint16_t led_level = LED_DIM ; /* set default to ON */

void config_pwm(uint16_t period, uint16_t compare) ;

typedef void (*func_ptr_type)(char *str) ;

void do_help(char *str) ;

void do_period(char *str) ;

void do_compare(char *str) ;

void do_pwm(char *str) ;

void do_status(char *str) ;

typedef struct _cmd_func_st {

    char *cmd ;

    func_ptr_type func ;

    char *description ;

} cmd_func_type ;

cmd_func_type cmd_list[] = {

    { "help",    do_help,    "Print Help Message" },

    { "period",  do_period,  "Set PWM Period value, period 1000" },

    { "compare", do_compare, "Set PWM Compare value, compare 10" },

    { "pwm",     do_pwm,     "Set PWM Config period and compare, pwm 1000 10" },

    { "status",  do_status,  "Show current setting" },

    { 0, 0, 0 }

} ;

void do_help(char *str)

{

    (void) str ;

    int i = 0 ;

   

    print("=== command ===\n\r") ;

    for (i = 0 ; cmd_list.cmd ; i++ ) {

        snprintf(str, STR_BUF_LEN, "%10s : ", cmd_list.cmd) ;

        print(str) ;

        print(cmd_list.description) ;

        print("\n\r") ;

    }

}

void do_period(char *str)

{

    sscanf(str, "%*s %hd", &led_period) ;

    config_pwm(led_period, led_level) ;

}

void do_compare(char *str)

{

    sscanf(str, "%*s %hd", &led_level) ;

    config_pwm(led_period, led_level) ;

}

void do_pwm(char *str)

{

    sscanf(str, "%*s %hd %hd", &led_period, &led_level) ;

    config_pwm(led_period, led_level) ;   

}

void do_status(char *str)

{

    uint16_t period, compare ;

    period = PWM_ReadPeriod() ;

    compare = PWM_ReadCompare() ;

    print("=== PWM Status ===\n\r") ;

    snprintf(str, STR_BUF_LEN, "Period: %hd\r\n", period) ;

    print(str) ;

    snprintf(str, STR_BUF_LEN, "Compare: %hd\r\n", compare) ;

    print(str) ;

}

void init_hardware(void)

{

    CyGlobalIntEnable; /* Enable global interrupts. */

    CapSense_1_Start() ;

   

    UART_Start() ;

    tty_init() ;

    splash("CapSense and LED PWM Test") ;

   

    PWM_Start() ;

}

void config_pwm(uint16_t period, uint16_t compare)

{

    PWM_Stop() ;

    PWM_WritePeriod(period) ;

    PWM_WriteCompare(compare) ;

    PWM_Start() ;

}

func_ptr_type get_func(char *cmd)

{

    int i ;

    for (i = 0 ; cmd_list.cmd ; i++ ) {

        if (strcmp(cmd, cmd_list.cmd) == 0) {

            break ;

        }

    }

    return( cmd_list.func ) ;

}

void do_command(char *str)

{

    char command[STR_BUF_LEN+1] ;

    func_ptr_type func ;

    sscanf(str, "%s", command) ;

    func = get_func(command) ;

    if (func) {

        func(str) ;

    } else {

        do_help(str) ;

    }

}

int main(void)

{  

    init_hardware() ;

   

    config_pwm(led_period, led_level) ;

    prompt() ;

   

    for(;;) {

        if (get_line()) {

            do_command(str) ;

            prompt() ;

        }

        if (!CapSense_1_IsBusy()) {

            CapSense_1_ProcessAllWidgets() ;

           

            if (CapSense_1_IsSensorActive(CapSense_1_BUTTON0_WDGT_ID, CapSense_1_BUTTON0_SNS0_ID)) {

                if (led_level == LED_OFF) {

                    led_level = LED_DIM ;

                } else {

                    led_level = LED_OFF ;

                }

                PWM_WriteCompare(led_level) ;

                CyDelay(500) ; /* cheap debouncing */

            }      

           

            CapSense_1_ScanAllWidgets() ;   

        }

    }

}

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

Tera Term log

001-tera_term_log.JPG

When the program started, as Period = 1000, Compare = 10 and the PWM Clock = 2MHz

About 2KHz pulse(s) are generated

TEK0000.jpg

When I entered "pwm 2000 1000" to the prompt (>)

Now frequency is 2KHz and as compre value is 1000 the duty is 50%

TEK0001.jpg

When I entered "pwm 3000 1000"

The frequency was about 668Hz and duty is about 30%

TEK0002.jpg

When I entered "pwm 1500 1000", frequency was about 1.336 kHz

and duty is about 67%.

TEK0003.jpg

So the bad news is that I had a bug in my previous program,

and the good news is PWM_WritePeriod() does its work 😉

moto

View solution in original post

0 Likes
10 Replies
BragadeeshV
Moderator
Moderator
Moderator
First question asked 1000 replies posted 750 replies posted

Hi UlMo_4589691​,

If you wish to adjust the brightness of the LED (fixed brightness), you can increase/ decrease the current flowing through the LED. This can be done by varying the resistor connected in series to the LED. Increasing the resistance will dim the LED.

If you wish to dynamically control the brightness of the LED, you can connect it to a PWM block and change the duty cycle of the PWM to increase/ decrease brightness. If ON time is increased , brightness increases.

Regards,

Bragadeesh 

Regards,
Bragadeesh

Many of the PSoC devicws have a PrISM component which is specialized for dimming LEDs dynamically.

Have a look into the datasheet.

Bob

0 Likes

No there is no such PrlSM on my PSoC 4000 Kit

0 Likes

Hi Bragadeesh,

I want to use the second option and have made the code below. There a touch button shall switch on the LED and its brightness I want to set up PWM.

Before I have tested: With no PWM and not connect the LED to the PWM (no "HW connection"), the touch button switches the LED on to full brightness.

Now programming the device the Leds flashes shortly and the touch is not working anymore. Do you know, what is wrong?

pastedImage_0.png

#include "project.h"

//leds

#define LED_ON                        (0u) //Für Oledanschluss OFF=0u --> on=1u

#define LED_OFF                        (1u)

int main(void)

{

    CyGlobalIntEnable; /* Enable global interrupts. Immer notwendig */

    CapSense_1_Start();

   

    PWM_Start();

    PWM_SetMode(PWM_MODE_PWM_DT);

    PWM_SetPWMDeadTime(255);

   

    //How can I controll

   

    for(;;)

    {

    //CHECK IF CAPSENSE IS NOT BUSY -- Touch funktioniert dann besser

    if(!CapSense_1_IsBusy())

        {

        CapSense_1_ScanAllWidgets();

        CapSense_1_ProcessAllWidgets();

        ledGreen_Write(CapSense_1_IsWidgetActive(CapSense_1_BUTTON0_WDGT_ID) ? LED_ON : LED_OFF );

        }

    }

}

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,

I tried with CY8CKIT-044.

My Program starts with LED off,

when you touch the button,

(1) LED lights with 1/4 brightness

(2) LED lights with full brightness

(3) LED turns off

(1) ...

schematic

001-schematic.JPG

main.c

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

#include "project.h"

#define PWM_PERIOD 1000

#define LED_OFF  0

#define LED_1_4  250

#define LED_HALF 500

#define LED_3_4  750

#define LED_FULL 1000

int main(void)

{

    int led_level = LED_OFF ;

  

    CyGlobalIntEnable; /* Enable global interrupts. */

    CapSense_1_Start() ;

    PWM_WritePeriod(PWM_PERIOD) ;

    PWM_WriteCompare(led_level) ;

    PWM_Start() ;

    for(;;)

    {

        if (!CapSense_1_IsBusy()) {

            CapSense_1_ProcessAllWidgets() ;

          

            if (CapSense_1_IsSensorActive(CapSense_1_BUTTON0_WDGT_ID, CapSense_1_BUTTON0_SNS0_ID)) {

                switch(led_level) {

                case LED_OFF:  led_level = LED_1_4  ; break ;

                case LED_1_4:  led_level = LED_FULL ; break ;

                case LED_FULL: led_level = LED_OFF  ; break ;

                default:      led_level = LED_OFF  ; break ;

                }

                // PWM_Stop() ;

                PWM_WriteCompare(led_level) ;

                // PWM_Enable() ;

                CyDelay(500) ; /* cheap debouncing */

            }        

            CapSense_1_ScanAllWidgets() ;  

        }

    }

}

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

moto

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,

Although I'm afraid that this may be somewhat supererogatory,

I modified my program to only ON <-> OFF function.

Meantime as I played with my CY8CKIT-044, about 10~100 for compare out of 1000  period cycle seemed to be "dim".

This number may vary in each system(s).

main.c

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

#include "project.h"

#define PWM_PERIOD 1000 /* 65535 (0xFFFF) was too much for this purpose */

#define LED_OFF       0

#define LED_DIM      10 /* could be anywhere from 1 to 1000 */

int main(void)

{

    int led_level = LED_OFF ;

   

    CyGlobalIntEnable; /* Enable global interrupts. */

    CapSense_1_Start() ;

    PWM_WritePeriod(PWM_PERIOD) ;

    PWM_WriteCompare(led_level) ;

    PWM_Start() ;

    for(;;) {

         if (!CapSense_1_IsBusy()) {

            CapSense_1_ProcessAllWidgets() ;

           

            if (CapSense_1_IsSensorActive(CapSense_1_BUTTON0_WDGT_ID, CapSense_1_BUTTON0_SNS0_ID)) {

                if (led_level == LED_OFF) {

                    led_level = LED_DIM ;

                } else {

                    led_level = LED_OFF ;

                }

                PWM_WriteCompare(led_level) ;

                CyDelay(500) ; /* cheap debouncing */

            }      

           

            CapSense_1_ScanAllWidgets() ;   

        }

    }

}

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

moto

Hi

your answer is very helpfull. I think that LED_DIM -input for PWM_WriteCompare) shall be between 0 and 65535 for getting 0 to 100 %.

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

Hi,

There are some more things to consider.

(1) The "period" of the counter defines the frequency. (frequency = 1/period)

(2) As a 16bit counter, the TCPWM can count 0 to 65535 (= 65536 cycles)

(3) If you count up to 65535 with 2MHz clock, it takes 32.768ms => 30.5175 Hz

(4) The "compare" value could be 0 to the period+1, although we can assign up to 65535 anyway.

    But 0 to period+1 will be mapped to 0% to 100%

(5) In my sample, I set the period to "1000", so meaningful compare value is 0 to 1001.

   (Oops, I notice that I should have set it to 999, so that 0 to 1000 was meaningful, but it's a detail)

(6) On the other hand, to avoid seeing the LED flickering,

    usually, we'd like to make the frequency more than 50 or 60Hz,

    so that about "10000" or less will be good for the period.

(7) And I chose 1000.  (So compare value should be 0 to 1001, which is 0% to 100%)

moto

0 Likes

Hi,

now I have measured the output frequency by the help of an oscilloscope. Changing the PWM_PERIOD or even cancel (//PWM_WritePeriod(PWM_PERIOD)  has no impact on the final frequency of 61 Hz.

To work with PWM_PERIOD, do I have change the settings direct in the ''Configure PWM"?

Please find below a screenshot of the ''Configure PWM" and my main.

pastedImage_12.png

#include "project.h"

//#define PWM_PERIOD 1 //16 bit clock/period = frequency

#define LED_OFF 0          //16 bit for writeCompare   

#define LED_1_4  64*256

#define LED_HALF 128*256

#define LED_3_4  192*256

#define LED_FULL (256*256)-1

int main(void){

    int led_level = LED_OFF ;

    CyGlobalIntEnable; /* Enable global interrupts. */

    CapSense_1_Start() ;

    //PWM_WritePeriod(PWM_PERIOD) ;   ---------has no impact on frequency

    PWM_Start() ;

    PWM_WriteCompare(led_level) ;

    for(;;) {

        if ( ! CapSense_1_IsBusy()) {

            CapSense_1_ProcessAllWidgets() ;

           

            if (CapSense_1_IsSensorActive(CapSense_1_BUTTON0_WDGT_ID, CapSense_1_BUTTON0_SNS0_ID)) {

                switch(led_level) {

                    case LED_OFF:  led_level = LED_1_4  ; break ;

                    case LED_1_4:  led_level = LED_HALF ; break ;

                    case LED_HALF:  led_level = LED_3_4 ; break ;

                    case LED_3_4:  led_level = LED_FULL ; break ;

                    case LED_FULL: led_level = LED_OFF  ; break ;

                default:      led_level = LED_OFF  ; break ;

                }

                PWM_WriteCompare(led_level) ;

             

                CyDelay(500) ; /* cheap debouncing */

            }       

            CapSense_1_ScanAllWidgets() ; 

        }

    }

}

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 was my mistake, before setting period PWM_Start() or PWM_Init() must have been called.

Note: PWM_Init() is called at the first time PWM_Start() is called

003-pwm_start.JPG

And in the PWM_Init(), period is overwritten to the value set in the GUI.

So I should have written

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

PWM_Start() ;

PWM_Stop() ; /* before changing the period, PWM must be stopped */

PWM_WritePeriod(PWM_PERIOD) ;

PWM_WriteCompare(led_level) ;

PWM_Start() ;

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

To test if PWM_WritePeriod() really works,

I made following test program.

schematic

001-schematic.JPG

pins

002-pins.JPG

main.c

Note: To handle UART interactions I cheated by using my tty_utility

tty_utils a utility sample for CLI type program

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

#include "project.h"

#include "stdio.h"

#include "tty_utils.h"

#define PWM_PERIOD 1000 /* 65535 (0xFFFF) was too much for this purpose */

#define LED_OFF       0

#define LED_DIM      10 /* could be anywhere from 1 to 1000 */

uint16_t led_period = PWM_PERIOD ;

uint16_t led_level = LED_DIM ; /* set default to ON */

void config_pwm(uint16_t period, uint16_t compare) ;

typedef void (*func_ptr_type)(char *str) ;

void do_help(char *str) ;

void do_period(char *str) ;

void do_compare(char *str) ;

void do_pwm(char *str) ;

void do_status(char *str) ;

typedef struct _cmd_func_st {

    char *cmd ;

    func_ptr_type func ;

    char *description ;

} cmd_func_type ;

cmd_func_type cmd_list[] = {

    { "help",    do_help,    "Print Help Message" },

    { "period",  do_period,  "Set PWM Period value, period 1000" },

    { "compare", do_compare, "Set PWM Compare value, compare 10" },

    { "pwm",     do_pwm,     "Set PWM Config period and compare, pwm 1000 10" },

    { "status",  do_status,  "Show current setting" },

    { 0, 0, 0 }

} ;

void do_help(char *str)

{

    (void) str ;

    int i = 0 ;

   

    print("=== command ===\n\r") ;

    for (i = 0 ; cmd_list.cmd ; i++ ) {

        snprintf(str, STR_BUF_LEN, "%10s : ", cmd_list.cmd) ;

        print(str) ;

        print(cmd_list.description) ;

        print("\n\r") ;

    }

}

void do_period(char *str)

{

    sscanf(str, "%*s %hd", &led_period) ;

    config_pwm(led_period, led_level) ;

}

void do_compare(char *str)

{

    sscanf(str, "%*s %hd", &led_level) ;

    config_pwm(led_period, led_level) ;

}

void do_pwm(char *str)

{

    sscanf(str, "%*s %hd %hd", &led_period, &led_level) ;

    config_pwm(led_period, led_level) ;   

}

void do_status(char *str)

{

    uint16_t period, compare ;

    period = PWM_ReadPeriod() ;

    compare = PWM_ReadCompare() ;

    print("=== PWM Status ===\n\r") ;

    snprintf(str, STR_BUF_LEN, "Period: %hd\r\n", period) ;

    print(str) ;

    snprintf(str, STR_BUF_LEN, "Compare: %hd\r\n", compare) ;

    print(str) ;

}

void init_hardware(void)

{

    CyGlobalIntEnable; /* Enable global interrupts. */

    CapSense_1_Start() ;

   

    UART_Start() ;

    tty_init() ;

    splash("CapSense and LED PWM Test") ;

   

    PWM_Start() ;

}

void config_pwm(uint16_t period, uint16_t compare)

{

    PWM_Stop() ;

    PWM_WritePeriod(period) ;

    PWM_WriteCompare(compare) ;

    PWM_Start() ;

}

func_ptr_type get_func(char *cmd)

{

    int i ;

    for (i = 0 ; cmd_list.cmd ; i++ ) {

        if (strcmp(cmd, cmd_list.cmd) == 0) {

            break ;

        }

    }

    return( cmd_list.func ) ;

}

void do_command(char *str)

{

    char command[STR_BUF_LEN+1] ;

    func_ptr_type func ;

    sscanf(str, "%s", command) ;

    func = get_func(command) ;

    if (func) {

        func(str) ;

    } else {

        do_help(str) ;

    }

}

int main(void)

{  

    init_hardware() ;

   

    config_pwm(led_period, led_level) ;

    prompt() ;

   

    for(;;) {

        if (get_line()) {

            do_command(str) ;

            prompt() ;

        }

        if (!CapSense_1_IsBusy()) {

            CapSense_1_ProcessAllWidgets() ;

           

            if (CapSense_1_IsSensorActive(CapSense_1_BUTTON0_WDGT_ID, CapSense_1_BUTTON0_SNS0_ID)) {

                if (led_level == LED_OFF) {

                    led_level = LED_DIM ;

                } else {

                    led_level = LED_OFF ;

                }

                PWM_WriteCompare(led_level) ;

                CyDelay(500) ; /* cheap debouncing */

            }      

           

            CapSense_1_ScanAllWidgets() ;   

        }

    }

}

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

Tera Term log

001-tera_term_log.JPG

When the program started, as Period = 1000, Compare = 10 and the PWM Clock = 2MHz

About 2KHz pulse(s) are generated

TEK0000.jpg

When I entered "pwm 2000 1000" to the prompt (>)

Now frequency is 2KHz and as compre value is 1000 the duty is 50%

TEK0001.jpg

When I entered "pwm 3000 1000"

The frequency was about 668Hz and duty is about 30%

TEK0002.jpg

When I entered "pwm 1500 1000", frequency was about 1.336 kHz

and duty is about 67%.

TEK0003.jpg

So the bad news is that I had a bug in my previous program,

and the good news is PWM_WritePeriod() does its work 😉

moto

0 Likes