LED Not Blinking

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.
BladeCJ
Level 1
Level 1
First question asked Welcome!

I am trying to use an interrupt to make an LED blink different colors, at different speeds. The target slow frequency is 3 Hz, fast 15 Hz. I am clearing both my SW and timer interrupts, so I am not sure what is going wrong.

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,

Yet another sample, using PWM for blinking LEDs.

CY8CKIT-044:

schematic

020-schematic.JPG

Pins

021-Pins.JPG

CY8CKIT-042

Schematic

030-schematic.JPG

Pins

031-Pins.JPG

main.c (same for 042 and 044)
Note: I tried to make it less than 50 lines.

 

#include "project.h"

#define INTERVAL_3HZ    3 // value does not have much meaning here
#define INTERVAL_15HZ  15 // value does not have much meaning here

#define COLOR_RED     0x6 // B:1, G:1, R:0
#define COLOR_GREEN   0x5 // B:1, G:0, R:1

volatile int interval_mode   = INTERVAL_3HZ ;

CY_ISR(sw_isr)
{
    uint16_t period ;

    switch(interval_mode) {
    default:
    case INTERVAL_3HZ:
        period  =  799 ;
        led_color_Write(COLOR_RED) ;
        interval_mode = INTERVAL_15HZ ;
        break ;
    case INTERVAL_15HZ:
        period  = 3999 ;
        led_color_Write(COLOR_GREEN) ;
        interval_mode = INTERVAL_3HZ ;
        break ;
    }
    PWM_Stop() ;
    PWM_WritePeriod(period) ;
    PWM_WriteCompare(period/2) ; // about 50% duty
    PWM_WriteCounter(0) ;        // activate the values set
    PWM_Start() ;

    SW_ClearInterrupt() ;
}

int main(void)
{
    CyGlobalIntEnable; /* Enable global interrupts. */

    isr_1_ClearPending() ;
    isr_1_StartEx(sw_isr) ;
    
    PWM_Start() ;

    for(;;) {
    }
}

 

moto

 

View solution in original post

8 Replies
MiNe_85951
Level 7
Level 7
Distributor - TED (Japan)
50 likes received 500 replies posted 50 solutions authored

Hi  ,

 

I use the ISR_StartEx() API rather than ISR_Start(), but first of all, please tell us about the following two points.

 

- Interrupt priority

   Are GPIO(SW) interrupts set higher priority than TIMER interrupts?

 

- Configuring GPIO(SW) interrupts

  Are GPIO interrupts set for Both edge?

 

Also, I think it would be better to change the interrupt enable timing in the main function as shown below.

 

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

LED_Timer_Start(); //Starts timer

TIMER_ISR_Start(); //Starts timer interrupt

SW_ISR_Start(); //Starts switch interrupts

SW_flag = 0; //Sets flag to 0, so does not go into interrupt until slide switch is used

R_LED_Write(1); // Defaults LED to off

G_LED_Write(1);

B_LED_Write(1);

CyGlobalIntEnable; /* Enable global interrupts. */

 

You say that the LED does not blinking, but what state will it be in?

 

Regards,

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,

IMHO, for slow interval like 3Hz, 15Hz, I prefer to use "SysTick" timer, which comes with cortex-m free.

So I tried this with CY8CKIT-044, hopefully it won't be hard to port it to other PSoC 4 devices (fingers crossed).

Schematic

001-schematic.JPG

Pins

002-pins.JPG

main.c

#include "project.h"

#define LED_ON 0u
#define LED_OFF 1u

#define INTERVAL_3HZ  167 // (1000 / 3) / 2
#define INTERVAL_15HZ  33  // (1000 / 15) / 2

uint32_t     interval   = INTERVAL_3HZ ;
volatile int blink_flag = 0 ;

// SysTick related functions
volatile uint32_t tick_count = 0 ;

CY_ISR(tick_callback)
{
    tick_count++ ;
    if (tick_count > interval) {
        tick_count = 0 ;
        blink_flag = 1 ;
    }
}

int find_empty_slot(void)
{
    int result = -1 ;
    uint32_t i ;
    for (i = 0 ; i < CY_SYS_SYST_NUM_OF_CALLBACKS ; i++ ) {
        if (CySysTickGetCallback(i) == NULL) {
            result = i ;
            break ;
        }
    }
    return(result) ;
}

void init_sys_tick(void)
{
    int sys_tick_slot = 0 ;

    sys_tick_slot = find_empty_slot() ;
    if (sys_tick_slot < 0) {
        R_LED_Write(LED_ON) ;
        while(1) { } /* halting here */
    } else {
        CySysTickStart() ;
        CySysTickSetCallback(sys_tick_slot, tick_callback) ;
    }
    
}
// SW interrupt related functions
volatile int sw_flag = 0 ;

CY_ISR(sw_isr)
{
    SW_ClearInterrupt() ;
    isr_1_ClearPending() ; // may be not necessary
    sw_flag = 1 ;
}

void blink_led(void)
{
 //   R_LED_Write(!R_LED_Read()) ;
    G_LED_Write(!G_LED_Read()) ;
//    B_LED_Write(!B_LED_Read()) ;
}

int main(void)
{
    CyGlobalIntEnable; /* Enable global interrupts. */

    isr_1_ClearPending() ;
    isr_1_StartEx(sw_isr) ;
    
    init_sys_tick() ;

    for(;;) {
        if (sw_flag) { 
            sw_flag = 0 ;
            if (interval == INTERVAL_3HZ) {
                interval = INTERVAL_15HZ ;
            } else {
                interval = INTERVAL_3HZ ;
            }
        }
        if (blink_flag) {
            blink_flag = 0 ;
            blink_led() ;
        }
    }
}

 

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,

As usual, I was overheasty and forgot about the color change.

Here is the version with color change, at first green blink (3Hz), with sw pushed blue blink (15Hz) vice versa.

Schematic and Pins are same with the previous post.

main.c

 

#include "project.h"

#define LED_ON 0u
#define LED_OFF 1u

#define INTERVAL_3HZ  167 // (1000 / 3) / 2
#define INTERVAL_15HZ  33  // (1000 / 15) / 2

#define COLOR_RED   0x01
#define COLOR_GREEN 0x02
#define COLOR_BLUE  0x04

uint8_t      led_color  = COLOR_GREEN ;
uint32_t     interval   = INTERVAL_3HZ ;
volatile int blink_flag = 0 ;

// SysTick related functions
volatile uint32_t tick_count = 0 ;

CY_ISR(tick_callback)
{
    tick_count++ ;
    if (tick_count > interval) {
        tick_count = 0 ;
        blink_flag = 1 ;
    }
}

int find_empty_slot(void)
{
    int result = -1 ;
    uint32_t i ;
    for (i = 0 ; i < CY_SYS_SYST_NUM_OF_CALLBACKS ; i++ ) {
        if (CySysTickGetCallback(i) == NULL) {
            result = i ;
            break ;
        }
    }
    return(result) ;
}

void init_sys_tick(void)
{
    int sys_tick_slot = 0 ;

    sys_tick_slot = find_empty_slot() ;
    if (sys_tick_slot < 0) {
        R_LED_Write(LED_ON) ;
        while(1) { } /* halting here */
    } else {
        CySysTickStart() ;
        CySysTickSetCallback(sys_tick_slot, tick_callback) ;
    }
    
}
// SW interrupt related functions
volatile int sw_flag = 0 ;

CY_ISR(sw_isr)
{
    SW_ClearInterrupt() ;
    isr_1_ClearPending() ; // may be not necessary
    sw_flag = 1 ;
}

// LED control functions

void set_color(uint8_t color)
{
    R_LED_Write(LED_OFF) ;
    G_LED_Write(LED_OFF) ;
    B_LED_Write(LED_OFF) ;
    
    led_color = color ;
}

void blink_led(void)
{
    if (led_color & COLOR_RED) {
        R_LED_Write(!R_LED_Read()) ;
    }
    if (led_color & COLOR_GREEN) {
        G_LED_Write(!G_LED_Read()) ;
    }
    if (led_color & COLOR_BLUE) {
        B_LED_Write(!B_LED_Read()) ;
    }
}

int main(void)
{
    CyGlobalIntEnable; /* Enable global interrupts. */

    isr_1_ClearPending() ;
    isr_1_StartEx(sw_isr) ;
    
    init_sys_tick() ;

    for(;;) {
        if (sw_flag) { 
            sw_flag = 0 ;
            if (interval == INTERVAL_3HZ) {
                interval = INTERVAL_15HZ ;
                set_color( COLOR_BLUE ) ;
            } else {
                interval = INTERVAL_3HZ ;
                set_color( COLOR_GREEN) ;
            }
        }
        if (blink_flag) {
            blink_flag = 0 ;
            blink_led() ;
        }
    }
}

 

Note: you can change the color at "set_color()" call.
You can "or" colors like "set_color( COLOR_GREEN | COLOR_RED )", too.

moto

0 Likes
lock attach
Attachments are accessible only for community members.
MiNe_85951
Level 7
Level 7
Distributor - TED (Japan)
50 likes received 500 replies posted 50 solutions authored

I confirmed the operation using CY8CKIT-042.

The source code is mostly yours.

 

I think Mr. Tanaka is right.

 

In your project:

GPIO changes, SW interrupt flag set.

An interrupt is generated by the timer,

・SW interrupt flag clear

・Change the period of the timer

・Turn on the LED according to the specified GPIO

The next timer interrupt will also occur, but

・Turn on the LED with the same color without GPIO change

 

It is setting the LED to turn on, but there is no condition to turn it off.

I think it is necessary to read the LED state using a timer interrupt and invert it.

 

The conditions have been changed so that Archive01 only lights up without blinking, and Archive02 blinks.

For this configuration, I felt that the GPIO interrupt was not necessary since the GPIO state could be read using only the timer interrupt.

 

Regards,

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 feel that we should have isr for both the Switch and the Timer,

as polling switch in the timer isr may  cause slow response.

So I tried the following with CY8CKIT-042

Schematic

010-schematic_042.JPG

Pins

011-pins.JPG

main.c

#include "project.h"

#define COLOR_RED   0x04
#define COLOR_GREEN 0x02
#define COLOR_BLUE  0x01

#define LED_ON        0u
#define LED_OFF       1u

#define MODE_3HZ       0
#define MODE_15HZ      1
#define TIMER_3HZ   2000
#define TIMER_15HZ   400

volatile uint8_t led_color = COLOR_GREEN ;
volatile int mode          = MODE_3HZ ;

CY_ISR(timer_isr)
{
    Timer_ClearInterrupt(Timer_INTR_MASK_TC) ;
    if (led_color & COLOR_RED) {
        R_LED_Write(!R_LED_Read()) ;
    }
    if (led_color & COLOR_GREEN) {
        G_LED_Write(!G_LED_Read()) ;
    }
    if (led_color & COLOR_BLUE) {
        B_LED_Write(!B_LED_Read()) ;
    }
}

CY_ISR(sw2_isr)
{
    SW2_ClearInterrupt() ;
    Timer_Stop() ;
    R_LED_Write(LED_OFF) ;
    G_LED_Write(LED_OFF) ;
    B_LED_Write(LED_OFF) ;
    if (mode == MODE_3HZ) {
        mode = MODE_15HZ ;
        led_color = COLOR_BLUE ;
        Timer_WritePeriod(TIMER_15HZ) ;
    } else {
        mode = MODE_3HZ ;
        Timer_WritePeriod(TIMER_3HZ) ;
        led_color = COLOR_GREEN ;
    }   
    Timer_WriteCounter(0) ;
    Timer_Enable() ;
}

int main(void)
{
    CyGlobalIntEnable; /* Enable global interrupts. */

    SW2_ClearInterrupt() ;
    int_sw2_StartEx(sw2_isr) ;
    
    Timer_ClearInterrupt(Timer_INTR_MASK_TC) ;
    int_timer_StartEx(timer_isr) ;
    Timer_Start() ;

    for(;;) {
    }
}

moto

MiNe_85951
Level 7
Level 7
Distributor - TED (Japan)
50 likes received 500 replies posted 50 solutions authored

Hello moto,

 

I just thought that if it was 3Hz and 15Hz in this original configuration, I might not understand it in the sense of human switch operation.

 

In the original, even if there is a switch interrupt, in the end, the switch interrupt is judged by the next timer interrupt.

 

I just pointed out the problems of the original project, I also think this configuration you are proposing is good.

However, if we wanted to achieve this LED blinking, we thought it would be undesirable for the timer to perform frequent interrupt processing just by blinking the LED.

Therefore, I believe it is best configured without timer interrupts and with one GPIO interrupt, one PWM, and Smart IO (or DMUX + LUT of UDB).

 

When a SW interrupt occurs, read the GPIO and change PWM speed settings.

PWM connection can be switched by hardware using LUT of Smart IO.

MiNe_85951_0-1707411491766.png

MiNe_85951_3-1707411612897.png

Unfortunately, I can't try it because I don't have a 3-color LED and a PSoC4S series(mounted Smart IO) environment at hand.

 

Regards,

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

Dear Mine-san,

I just pointed out the problems of the original project,
> I also think this configuration you are proposing is good.

Yes, I agree. Usually it's the best approach for supporting within a limited time and maximum result.

But sometimes for the customer who is not familiar and/or comfortable with embedded programming or PSoC programming, providing a working sample may be a time saving and helps to keep the customer confidence toward the device. Seeing the main.c posted in the original question, I felt that the person is not very familiar with PSoC programming. May be, because I just like to program, though 😜

> However, if we wanted to achieve this LED blinking, we thought it would be undesirable for the timer to perform frequent interrupt processing just by blinking the LED.

I agree.

If we must blink the LED, using PWM seems to be the easiest or using the "SysTick" seems to be the cheapest. So at first I suggested to use SysTick. Meantime, for the easiest implementation, using a PWM would be nice, yes, you can guess, I was planning to write another sample using a PWM.

And also controlling the color, SmartIO seemed to be nice, and Bang! you've already posted the strategy!

Best Regards,
9-Feb-2024
Motoo Tanaka

P.S. Later, if I can afford time, I might post a sample using PWM (and without SmartIO...)

 

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,

Yet another sample, using PWM for blinking LEDs.

CY8CKIT-044:

schematic

020-schematic.JPG

Pins

021-Pins.JPG

CY8CKIT-042

Schematic

030-schematic.JPG

Pins

031-Pins.JPG

main.c (same for 042 and 044)
Note: I tried to make it less than 50 lines.

 

#include "project.h"

#define INTERVAL_3HZ    3 // value does not have much meaning here
#define INTERVAL_15HZ  15 // value does not have much meaning here

#define COLOR_RED     0x6 // B:1, G:1, R:0
#define COLOR_GREEN   0x5 // B:1, G:0, R:1

volatile int interval_mode   = INTERVAL_3HZ ;

CY_ISR(sw_isr)
{
    uint16_t period ;

    switch(interval_mode) {
    default:
    case INTERVAL_3HZ:
        period  =  799 ;
        led_color_Write(COLOR_RED) ;
        interval_mode = INTERVAL_15HZ ;
        break ;
    case INTERVAL_15HZ:
        period  = 3999 ;
        led_color_Write(COLOR_GREEN) ;
        interval_mode = INTERVAL_3HZ ;
        break ;
    }
    PWM_Stop() ;
    PWM_WritePeriod(period) ;
    PWM_WriteCompare(period/2) ; // about 50% duty
    PWM_WriteCounter(0) ;        // activate the values set
    PWM_Start() ;

    SW_ClearInterrupt() ;
}

int main(void)
{
    CyGlobalIntEnable; /* Enable global interrupts. */

    isr_1_ClearPending() ;
    isr_1_StartEx(sw_isr) ;
    
    PWM_Start() ;

    for(;;) {
    }
}

 

moto