- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello I need to measure a signal's period to calculate heartbeat.
In order to achieve that, I'm trying to capture the time when the signal crosses the average of the signal so I can compare it with the next time it crosses the average and so on.
In Arduino I could use the function "millis" for that. For PSoC, I've read I'd need to install "millis.h" and "millis.c" but I haven't found those files.
Next, I read I can use a timer on continuous mode, here's where I get lost.
I understand I need to connect a 1kHz clock to the timer's clock input so the timer count changes up/down every 1ms. Then I get lost.
should I just use something like "uint32 currentCount = Timer_ReadCounter();"?
I need it to run freely and store in a variable the time in ms in order to compare. How can I achieve that?
Thanks!!
Solved! Go to Solution.
- Tags:
- psoc_4
- timer counter
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
>This is the code I'm trying but I don't get any value from contador_ms on my UART terminal.
There are some points you need to be aware of.
Let's talk with your code.
===================
#include "project.h"
#include <stdio.h>
char uartline[250]; //caracteres para enviar por UART
float contador_ms=0; // (A)
int main(void){
CyGlobalIntEnable;
Timer_Start();
UART_Start();
UART_PutString("Comunicacion UART establecida correctamente");
UART_PutCRLF();
contador_ms=Timer_ReadCapture(); // (B)
sprintf(uartline,"El tiempo es %f",contador_ms); // (C)
UART_PutString(uartline); //Se imprime el contenido que llene en uartline
UART_PutCRLF(); //Se limpia uart
// (D)
}
===================
(A) Since the value type returned by the counter is an integer, you should use int or uint for the type of conador_ms.
(B) Timer_ReadCapture() returns the "Captured" value, to make this value valid, you need to configure the timer "Capture" mode.
And after the Capture Event, you will get some reasonable value.
For the time being, if you want to test reading something from the Timer, may be you can use Timer_ReadCounter()
(C) If you want to handle "%f", you need some additional setups in your project.
Please refer to a KBA (Knowledge Base Article) KBA231059
Printing floating-point values in PSoC Creator - KBA231059
Or my old meme
printf and float rhapsody (aka, yet another printf and floating topic)
(D) Since you are in the wild "Embedded" world, you should not end main().
In the embedded programming without an OS, main() should have a style of
int main(void)
{
/* initialization */
/* first or only 1 time execution process */
/* infinite loop */
for (;;) {
}
}
So the summary of this response, I would ask you to try below to see if it works or not
(1) Change "float" to "int" or "uint16"
(2) Change "%f" to "%d"
(3) Add following line at the blank place of (D)
for (;;) {
}
So it will look like
===================
#include "project.h"
#include <stdio.h>
char uartline[250]; //caracteres para enviar por UART
int contador_ms=0; // (A)
int main(void){
CyGlobalIntEnable;
Timer_Start();
UART_Start();
UART_PutString("Comunicacion UART establecida correctamente");
UART_PutCRLF();
contador_ms=Timer_ReadCapture(); // (B)
sprintf(uartline,"El tiempo es %d",contador_ms); // (C)
UART_PutString(uartline); //Se imprime el contenido que llene en uartline
UART_PutCRLF(); //Se limpia uart
// (D)
for (;;) {
}
}
===================
moto
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
If all you need is ms order timing, I would recommend to use "SysTick".
As it is already included in the Cortex-M and using it will not consume additional hardware resource.
(IMHO, and also it is easier to use)
So I made a sample project using CY8CKIT-044 (CY8C4247AZI-M485).
As I don't have heartbeat sensor right now, I used the switch on the board.
Every time the switch is pushed, ms count from the previous push will be printed to the serial output.
And LED on the board toggles.
Tera Term log
schematic
Note: To use "SysTick" none of the component below is necessary,
but to make testing easier I added them.
Pins
main.c
============================
#include "project.h"
#include "stdio.h"
#define STR_LEN 64
char str[STR_LEN+1] ;
void print(char *str)
{
UART_UartPutString(str) ; /* PSoC 4 */
// UART_PutString(str) ; /* PSoC 5 */
}
void cls(void)
{
print("\033c") ; /* reset */
CyDelay(20) ;
print("\033[2J") ; /* clear screen */
CyDelay(20) ;
}
void splash(char *prog_name)
{
cls() ;
if (prog_name && *prog_name) {
print(prog_name) ;
}
print(" (") ;
print(__DATE__) ;
print(" ") ;
print(__TIME__) ;
print(")\n") ;
}
volatile uint32_t sw_tick_count = 0 ;
volatile uint32_t sw_interval = 0 ;
volatile int sw_flag = 0 ;
CY_ISR(SysTick_ISR)
{
sw_tick_count++ ;
}
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) ;
}
CY_ISR(sw_isr)
{
sw_interval = sw_tick_count ;
sw_tick_count = 0 ;
sw_flag = 1 ;
SW_ClearInterrupt() ;
}
void init_hardware(void)
{
CyGlobalIntEnable; /* Enable global interrupts. */
UART_Start() ;
sw_push_int_ClearPending() ;
sw_push_int_StartEx(sw_isr) ;
}
int main(void)
{
int sys_tick_slot = 0 ;
init_hardware() ;
splash("Interval Time Test using SysTick") ;
sys_tick_slot = find_empty_slot() ;
if (sys_tick_slot < 0) {
while(1) { } /* halting here */
} else {
CySysTickStart() ;
CySysTickSetCallback(sys_tick_slot, SysTick_ISR) ;
}
CySysTickStart();
for(;;)
{
if (sw_flag) {
snprintf(str, STR_LEN, "%d ms\n\r", sw_interval) ;
print(str) ;
LED_Write(!LED_Read()) ;
sw_flag = 0 ;
}
}
}
============================
moto
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks for your answer!!
Unfortunately for me, I don't understand much of the code you posted.
Could you help me with my failed attempt?
I'm trying to set up a timer, with a 1kHz clock it will count each 1ms without needing any triggers to start and it will run continuously.
Then when I need to capture the time an event occurs on my signal of interest, I'd just call some macro of my timer to store how many ms has it counted so far.
This is the code I'm trying but I don't get any value from contador_ms on my UART terminal.
#include "project.h"
#include <stdio.h>
char uartline[250]; //caracteres para enviar por UART
float contador_ms=0;
int main(void){
CyGlobalIntEnable;
Timer_Start();
UART_Start();
UART_PutString("Comunicacion UART establecida correctamente");
UART_PutCRLF();
contador_ms=Timer_ReadCapture();
sprintf(uartline,"El tiempo es %f",contador_ms);
UART_PutString(uartline); //Se imprime el contenido que llene en uartline
UART_PutCRLF(); //Se limpia uart
}
Thanks!!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I do a similar thing to you for measuring the frequency of a sinusoidal signal - I'm measuring the time between zero crossings and calculating frequency from that. I use a Timer set up as follows to do this:
This is then how I do it:
1. I have an interrupt routine that gets triggered each time I detect a zero crossing. This grabs the current count in my timer each time it is called
2. Start my timer in readiness to do a measurement
3. Wait for zero crossing to trigger my ISR. In that ISR, I do this: TimeStart = Counter_ReadCounter(); This stores the count in my timer when the first zero-crossing occures
4. Wait for the next zero crossing. I then do: TimeStop = Counter_ReadCounter();
5. I can then calculate the period by doing period = TimeStop - TimerStart;
6. Stop my timer and get ready for next time I need to do a measurement
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
>This is the code I'm trying but I don't get any value from contador_ms on my UART terminal.
There are some points you need to be aware of.
Let's talk with your code.
===================
#include "project.h"
#include <stdio.h>
char uartline[250]; //caracteres para enviar por UART
float contador_ms=0; // (A)
int main(void){
CyGlobalIntEnable;
Timer_Start();
UART_Start();
UART_PutString("Comunicacion UART establecida correctamente");
UART_PutCRLF();
contador_ms=Timer_ReadCapture(); // (B)
sprintf(uartline,"El tiempo es %f",contador_ms); // (C)
UART_PutString(uartline); //Se imprime el contenido que llene en uartline
UART_PutCRLF(); //Se limpia uart
// (D)
}
===================
(A) Since the value type returned by the counter is an integer, you should use int or uint for the type of conador_ms.
(B) Timer_ReadCapture() returns the "Captured" value, to make this value valid, you need to configure the timer "Capture" mode.
And after the Capture Event, you will get some reasonable value.
For the time being, if you want to test reading something from the Timer, may be you can use Timer_ReadCounter()
(C) If you want to handle "%f", you need some additional setups in your project.
Please refer to a KBA (Knowledge Base Article) KBA231059
Printing floating-point values in PSoC Creator - KBA231059
Or my old meme
printf and float rhapsody (aka, yet another printf and floating topic)
(D) Since you are in the wild "Embedded" world, you should not end main().
In the embedded programming without an OS, main() should have a style of
int main(void)
{
/* initialization */
/* first or only 1 time execution process */
/* infinite loop */
for (;;) {
}
}
So the summary of this response, I would ask you to try below to see if it works or not
(1) Change "float" to "int" or "uint16"
(2) Change "%f" to "%d"
(3) Add following line at the blank place of (D)
for (;;) {
}
So it will look like
===================
#include "project.h"
#include <stdio.h>
char uartline[250]; //caracteres para enviar por UART
int contador_ms=0; // (A)
int main(void){
CyGlobalIntEnable;
Timer_Start();
UART_Start();
UART_PutString("Comunicacion UART establecida correctamente");
UART_PutCRLF();
contador_ms=Timer_ReadCapture(); // (B)
sprintf(uartline,"El tiempo es %d",contador_ms); // (C)
UART_PutString(uartline); //Se imprime el contenido que llene en uartline
UART_PutCRLF(); //Se limpia uart
// (D)
for (;;) {
}
}
===================
moto
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
After posting my previous response,
I tried using Timer/Counter (TCPWM) with CY8CKIT-044.
Again, I used the SW on the board as the trigger.
The serial output looks like below.
When I don't push the switch more than 2.5sec, "." are printed.
And when I push the switch, time from the previous push is printed.
schematic
Note: I use the signal from the SW for capture and reload.
Counter Config
Note: The switch on the board is low-active, so I set Mode of reload and capture as "Falling edge".
If you connect these pins to a high-active module, please set them to "Rising edge"
I also enabled Interrupt for "On compare/capture count"
I set the Period 2500, as you configured so, but may be it could be set longer.
pins
main.c
=======================
#include "project.h"
#include "stdio.h"
#define STR_LEN 64
char str[STR_LEN+1] ;
void print(char *str) ;
void cls(void) ;
void splash(char *prog_name) ;
volatile int capture_flag = 0 ;
volatile uint16_t count ;
CY_ISR(counter_isr)
{
uint32_t interrupt_source ;
interrupt_source = Counter_GetInterruptSource() ;
if (interrupt_source & Counter_INTR_MASK_TC) { /* timer over flow */
capture_flag = -1 ; /* counter overflow, not a valid count */
}
if (interrupt_source & Counter_INTR_MASK_CC_MATCH) { /* capture event! */
count = Counter_ReadCapture() ;
capture_flag = 1 ;
}
Counter_ClearInterrupt(interrupt_source) ;
}
void init_hardware(void)
{
CyGlobalIntEnable; /* Enable global interrupts. */
UART_Start() ;
isr_1_ClearPending() ;
Counter_ClearInterrupt(Counter_INTR_MASK_TC|Counter_INTR_MASK_CC_MATCH) ;
isr_1_StartEx(counter_isr) ;
Counter_Start() ;
}
int main(void)
{
init_hardware() ;
splash("Interval Time Test using TCPWM") ;
for(;;)
{
if (capture_flag) {
if (capture_flag > 0) { /* valid capture count */
snprintf(str, STR_LEN, "%d ms\n\r", count) ;
print(str) ;
} else { /* capture time overflow */
print(".") ;
}
capture_flag = 0 ;
}
}
}
void print(char *str)
{
UART_UartPutString(str) ; /* PSoC 4 */
// UART_PutString(str) ; /* PSoC 5 */
}
void cls(void)
{
print("\033c") ; /* reset */
CyDelay(20) ;
print("\033[2J") ; /* clear screen */
CyDelay(20) ;
}
void splash(char *prog_name)
{
cls() ;
if (prog_name && *prog_name) {
print(prog_name) ;
}
print(" (") ;
print(__DATE__) ;
print(" ") ;
print(__TIME__) ;
print(")\n") ;
}
=======================
moto