PSoC 101: Lesson 9 Timer Example

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.
Michael_K
Level 3
Level 3
25 replies posted 10 likes given 50 sign-ins

Good morning everyone,

I wanted to double-assign a few buttons for a project and wanted a different function or ISR to be executed when pressed for longer.

I found this example, but it doesn't work.
https://www.youtube.com/watch?v=_eGdJ93vUms&list=PLIOkqhZiy83F8KPvHejA4ujvAfwJYpAtP&index=10

 

I have set everything in the timer settings as in the video.

Michael_K_0-1666683016136.png

The interrupt is executed, but the counter always stays at 0, no matter how long I press the button. When I debug it, the counter has an undefined value once and then it also remains 0 the next time.

Michael_K_1-1666683324880.png

Michael_K_2-1666683345555.png

Do you know what the problem could be? I have the same problem with my self-made board with a PSoC 4100.

 

Best Regards

Michael 

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,

Your problem seems to have all reload, start, stop, capture pins connected to the SW_1.

So as far as you keep the switch pushed, the Timer won't be able to count up nor

generate another interrupt.

000-original.JPG

Although if we think very carefully, we could implement what you want with using a single Timer hardware,

to provide more versatile short-push and long-push, I decided to use "SysTick" which comes free with Cortex-M.

 

The following sample of mine, decide switch push shorter than 1 second (1000ms) as "Button Pushed"

and with switch push longer than 1 second,  reports the number of seconds the switch has been kept pushed.

 

In the following TeraTerm log,

I pushed short once, pushed for 3 seconds, pushed short twice, pushed long for seconds.

001-TeraTerm_log.JPG

Oops, I mis spelled assign as assing, forgive me for that m(_ _)m

I used CY8CKIT-042, and the schematic was

002-schematic.JPG

Pin_Switch configuration(s)

004_PinSwitch_1.JPG

005-PinSwitch_2.JPG

Note: I used both edges for interrupt to detect push and release.

Pins

003-Pins.JPG

main.c

I'm sorry, a little bit long 😜


#include <project.h>
#include <stdio.h>

#define MAX_SW2_DURATION_MS 10000
#define SW2_SHORT_THRESHOLD 1000

volatile long sw2_duration  = -1 ;
volatile int  sw2_short_flag = 0 ;
volatile int  sw2_long_flag  = 0 ;
volatile int  sw2_held       = 0 ;
volatile long sw2_sec_count  = 0 ;

/* print related utilities */
#define STR_LEN 64
char str[STR_LEN+1] ;

void print(char *str)
{
    UART_UartPutString(str) ;    
}

void cls(void)
{
    print("\033c") ; /* reset */
    CyDelay(100) ;
    print("\033[2J") ; /* clear screen */
    CyDelay(100) ;
}

void splash(char *title)
{
    cls() ;
    if (title && *title) {
        print(title) ;
        print(" ") ;
    }
    snprintf(str, STR_LEN, "(%s %s)\n\r", __DATE__, __TIME__) ;
    print(str) ;
}

/* SysTick related functions */
volatile uint32_t tick_count = 0 ;

CY_ISR(tick_callback)
{
    tick_count++ ;
    
    if (sw2_duration >= 0) {
        sw2_duration++ ;
        if (sw2_duration >= SW2_SHORT_THRESHOLD) {
            sw2_long_flag = 1 ;
            sw2_held      = 1 ;
            sw2_duration  = 0 ;
        }
    }
}

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 start_sys_tick_timer(void)
{
    int sys_tick_slot = 0 ;

    sys_tick_slot = find_empty_slot() ;
    if (sys_tick_slot < 0) {
        print("Sorry No empty SysTick Slot available\n\r") ;
        while(1) { } /* halting here */
    } else {
        CySysTickStart() ;
        CySysTickSetCallback(sys_tick_slot, tick_callback) ;
    }
}

CY_ISR(sw2_isr)
{
    Pin_Switch_ClearInterrupt() ;
    if (Pin_Switch_Read()) { /* SW2=High -> released */
        if (sw2_held == 0) {
            sw2_short_flag = 1 ;
        }
        sw2_sec_count = 0 ;
        sw2_held      = 0 ;
        sw2_duration  = -1 ;
    } else { /* SW2=Low -> pushed */
        sw2_duration = 0 ;
    }
}

void init_hardware(void)
{
    /* Enable global interrupts. */
	CyGlobalIntEnable; 
    
    start_sys_tick_timer() ;
    
    sw2_int_ClearPending() ;
    sw2_int_StartEx(sw2_isr) ;
    
    UART_Start() ;
    splash("button double assing test") ;
}

int main(void)
{

    
    init_hardware() ;
    
    for(;;)
    {
        if (sw2_short_flag) {
            sw2_short_flag = 0 ;
            print("Button Pushed!\n\r") ;
        }
        if (sw2_long_flag) {
            sw2_long_flag = 0 ;
            sw2_sec_count++   ;
            snprintf(str, STR_LEN, "%ld\n\r", sw2_sec_count) ;
            print(str) ;
        }
    }
}

/* [] END OF FILE */

In the main() you can call different function(s) for sw2_short_flag and sw2_long_flag.

 

Meantime, as you know there could be many approaches to do what you wanted,

so this is only one of such samples.

 

moto

View solution in original post

0 Likes
4 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,

Your problem seems to have all reload, start, stop, capture pins connected to the SW_1.

So as far as you keep the switch pushed, the Timer won't be able to count up nor

generate another interrupt.

000-original.JPG

Although if we think very carefully, we could implement what you want with using a single Timer hardware,

to provide more versatile short-push and long-push, I decided to use "SysTick" which comes free with Cortex-M.

 

The following sample of mine, decide switch push shorter than 1 second (1000ms) as "Button Pushed"

and with switch push longer than 1 second,  reports the number of seconds the switch has been kept pushed.

 

In the following TeraTerm log,

I pushed short once, pushed for 3 seconds, pushed short twice, pushed long for seconds.

001-TeraTerm_log.JPG

Oops, I mis spelled assign as assing, forgive me for that m(_ _)m

I used CY8CKIT-042, and the schematic was

002-schematic.JPG

Pin_Switch configuration(s)

004_PinSwitch_1.JPG

005-PinSwitch_2.JPG

Note: I used both edges for interrupt to detect push and release.

Pins

003-Pins.JPG

main.c

I'm sorry, a little bit long 😜


#include <project.h>
#include <stdio.h>

#define MAX_SW2_DURATION_MS 10000
#define SW2_SHORT_THRESHOLD 1000

volatile long sw2_duration  = -1 ;
volatile int  sw2_short_flag = 0 ;
volatile int  sw2_long_flag  = 0 ;
volatile int  sw2_held       = 0 ;
volatile long sw2_sec_count  = 0 ;

/* print related utilities */
#define STR_LEN 64
char str[STR_LEN+1] ;

void print(char *str)
{
    UART_UartPutString(str) ;    
}

void cls(void)
{
    print("\033c") ; /* reset */
    CyDelay(100) ;
    print("\033[2J") ; /* clear screen */
    CyDelay(100) ;
}

void splash(char *title)
{
    cls() ;
    if (title && *title) {
        print(title) ;
        print(" ") ;
    }
    snprintf(str, STR_LEN, "(%s %s)\n\r", __DATE__, __TIME__) ;
    print(str) ;
}

/* SysTick related functions */
volatile uint32_t tick_count = 0 ;

CY_ISR(tick_callback)
{
    tick_count++ ;
    
    if (sw2_duration >= 0) {
        sw2_duration++ ;
        if (sw2_duration >= SW2_SHORT_THRESHOLD) {
            sw2_long_flag = 1 ;
            sw2_held      = 1 ;
            sw2_duration  = 0 ;
        }
    }
}

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 start_sys_tick_timer(void)
{
    int sys_tick_slot = 0 ;

    sys_tick_slot = find_empty_slot() ;
    if (sys_tick_slot < 0) {
        print("Sorry No empty SysTick Slot available\n\r") ;
        while(1) { } /* halting here */
    } else {
        CySysTickStart() ;
        CySysTickSetCallback(sys_tick_slot, tick_callback) ;
    }
}

CY_ISR(sw2_isr)
{
    Pin_Switch_ClearInterrupt() ;
    if (Pin_Switch_Read()) { /* SW2=High -> released */
        if (sw2_held == 0) {
            sw2_short_flag = 1 ;
        }
        sw2_sec_count = 0 ;
        sw2_held      = 0 ;
        sw2_duration  = -1 ;
    } else { /* SW2=Low -> pushed */
        sw2_duration = 0 ;
    }
}

void init_hardware(void)
{
    /* Enable global interrupts. */
	CyGlobalIntEnable; 
    
    start_sys_tick_timer() ;
    
    sw2_int_ClearPending() ;
    sw2_int_StartEx(sw2_isr) ;
    
    UART_Start() ;
    splash("button double assing test") ;
}

int main(void)
{

    
    init_hardware() ;
    
    for(;;)
    {
        if (sw2_short_flag) {
            sw2_short_flag = 0 ;
            print("Button Pushed!\n\r") ;
        }
        if (sw2_long_flag) {
            sw2_long_flag = 0 ;
            sw2_sec_count++   ;
            snprintf(str, STR_LEN, "%ld\n\r", sw2_sec_count) ;
            print(str) ;
        }
    }
}

/* [] END OF FILE */

In the main() you can call different function(s) for sw2_short_flag and sw2_long_flag.

 

Meantime, as you know there could be many approaches to do what you wanted,

so this is only one of such samples.

 

moto

0 Likes
lock attach
Attachments are accessible only for community members.
Arpit_S
Moderator
Moderator
Moderator
50 likes received 250 replies posted 100 solutions authored

Hi @Michael_K 

 

I ran your project in Kit-042 and it is working fine. Please find screenshot attached for more details. I held the P0.7 for 
1. Less than 1 Seconds

2. Around 6 seconds

3. Around 9 Seconds

 

It is working fine, for Case 1 the brightness of LED was maximum and for case 3 the brightness of LED was dim, which is the expected output. For you I believe the issue could be because of the mechanical button. Sometimes, Mechanical switches and relays tend to make and break connections for a finite time before settling down to a stable state. Within this settling time, the digital circuit can see multiple transitions as the switch contacts bounce between make-or-break conditions.

 

I'd suggest you to please use the Debouncer component. You can find it in PSoC Components in PSoC Creator.

Thanks!
kind regards

Arpit Srivastav

0 Likes
Michael_K
Level 3
Level 3
25 replies posted 10 likes given 50 sign-ins

@MotooTanaka I connected the timerblock like this because that's how they showed it in the video. I haven't tried your solution yet, but I'll try it this week.
I will definitely report back to you. Then I can also close the thread.

 

@Arpit_S 
After I created a completely empty project again and created everything one-to-one manually, it suddenly worked. I don't know what I did wrong earlier. 

With you, my project apparently worked right away. I can't explain it either.

 

Thanks for the help and best regards

Michael K.

Michael_K
Level 3
Level 3
25 replies posted 10 likes given 50 sign-ins

Hello again,

@MotooTanaka I tried your solution and it works very well. I will change my project to the SysTick solution. This way I save myself a timer/counter block.
I have only two short questions:
Is it not possible to replace sw2_duration in the SysTick callback with the tick_count and reset tick_count after SW2_SHORT_TRESHOLD is reached?
And why does sw2_duration have the value -1 in the ISR?

 

Best Regards

Michael