- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
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.
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
Solved! Go to Solution.
- Labels:
-
PSoC 4 MCU
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
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.
Oops, I mis spelled assign as assing, forgive me for that m(_ _)m
I used CY8CKIT-042, and the schematic was
Pin_Switch configuration(s)
Note: I used both edges for interrupt to detect push and release.
Pins
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
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.
Oops, I mis spelled assign as assing, forgive me for that m(_ _)m
I used CY8CKIT-042, and the schematic was
Pin_Switch configuration(s)
Note: I used both edges for interrupt to detect push and release.
Pins
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
@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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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