- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I followed this thread: https://community.cypress.com/servlet/JiveServlet/download/134688-28018/Pulse%20Width%20and%20Period... and use this example on PSoC 5 (using CYKIT-059). I checked that PWM ~1kHZ and removed from code lcd display and add UARt TX component to see output. When capturing I get strange values like:
pulse:9000
pulse:870
pulse:4000
pulse:238830
pulse:4000
pulse:1000
pulse:1000
pulse:1000
pulse:0
pulse:1000
pulse:1000
pulse:1000
pulse:1000
pulse:16000
pulse:1000
pulse:1000
pulse:1010
pulse:1000
pulse:8000
pulse:990
any ideas how to check that? I also plan to monitor 5 PWm input signals is there enough resources on this dev board? Thanks.
BR,
marek
Solved! Go to Solution.
- Labels:
-
PSoC 5LP
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
marek,
I've modified the original program intended for the 050 eval board with LCD for your 059-KIT and the USB-UART.
Here is a summary of the modifications:
- I added 4 additional stimulus sources
- (see the schematic snippet below). The stimulus outputs are on P3.0, P3.1, P3.2 and P3.3. The original test stim is on P0.7.
- I deleted the LCD code references and added the UART calls to the USB_UART.
- I converted the ISR calls to cyapicallbacks. I believe this is a 'safer' way to implement component level ISRs.
Question:
When you were performing your original measurements, were you externally connecting the test stim output (P0.7) to the pulse monitor input (P0.5)? I get similar 'floating' reads if I don't connect P0.5 to a stimulus source. Otherwise, when I connect the 5 stimulus sources to P0.5 (one at a time) I get a reasonably value period and duty cycle.
Note:
- If the output frequency is too close to the sampling frequency (100KHz), the SW can't keep up reliably. As I get closer to the sampling frequency, the period is not as accurate. Eventually as the measure frequency is much nearer the sampling frequency, the SW appears to lockup (spending too much time in the ISRs) until I open up the input or switch to another slower stimulus.
- If the output frequency is too low, the wrap-around effect appears to become more significant and the period is not correct and/or the duty cycle reads greater than 100% which is definitely wrong.
Attached is my modified code if you want to check it out.
If you need to support frequency/period and duty-cycle measurements with more accuracy and reliability, you should set up HW counters with capture inputs. This allows the Counter HW to save the count value on the capture edge. Using the SW ISRs as being used in the project, is good if the inputs are relatively slow (not too slow) and you can support all the inputs you need with enough CPU speed.
Using the capture counters allow for more accurate results. This is because the counter count is loaded into a FIFO storage at the edge of capture. This lowers CPU usage and since there are four FIFO'd capture counts, the time criticality is not as bad. Using the ISRs means that the CPU tries to read the counter value as quickly as possible but the count might advance before the CPU can read it in the ISR.
Len
"Engineering is an Art. The Art of Compromise."
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
marek,
I just downloaded the project and will get back to you if I can reproduce your results.
Is this your application design?
I noticed you are using a 16bit counter with a 100KHz clock. This means the count value wraps back to 0 every 65536/100000 = 0.65536 seconds. I see there is counter rollover compensation. Therefore this shouldn't be an issue if your frequency is not too slow.
"I also plan to monitor 5 PWm input signals is there enough resources on this dev board?"
Using an ISR for each PWM input you could support an infinite number of inputs. You're only limited by the CPU processing frequency and RAM resources.
Len
"Engineering is an Art. The Art of Compromise."
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi Len,
I've pushed modified project here: Pulse Width Period Dutry Cycle.zip - Google Drive
it's original project where there is 1kHz pwm generator and for capturing I'm getting this strange results. I'm not sure yet if I need to monitor them in parallel or not but thanks for hint.
For monitoring values I connected USB->serial converter (TX ping is P1.7) and GND and get this values. Also duty cycle is 0 which is not good. Thanks.
Marek
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
FYI, in the following topic, I tried something similar.
But I'm afraid that my approach won't allow you to measure 5 PWMs.
moto
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks. I think original approach should work just there is some issue why it's not working always. Anyway thanks for sharing.
marek
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
OK, I tried with your strategy.
To take care of roll over I added another interrupt for TC
As I want to have ISRs in my source file I modified main.c as below
=======================
#include <project.h>
#include <stdio.h>
#include <stdlib.h>
#include <cytypes.h>
volatile uint16 PulseHighTime = 0; // pulsetime capture
volatile uint16 PulsePeriodStart = 0; // period time capture start
volatile uint16 PulsePeriodEnd = 0; // period time capture end
volatile uint8 flgPerdstart = 0; // Flag indicating + edge of pulse in has occured
volatile uint8 flgPerdend = 0; // Flag indicating + edge of next pulse has occured, signifying end of pepriod
char dispbuff[8]; // LCD display buffer 8 bytes long
uint8 lenstrg; // result of string length
uint8 i = 0; // loop index
float dutycycle = 0.0; // Variable to hold duty cycle computation
float pulseperd = 0.0; // Pulse period in mS
uint16 perdcalc = 0; // Intermediate value to aid in period measurement
float dutycalc = 0; // Intermediate value to aid in duty cycle measurement
volatile uint32_t tc_count = 0 ;
volatile uint32_t duty_count = 0 ;
volatile uint32_t duty_tc = 0 ;
uint32_t duty_cycle = 0 ;
volatile uint32_t period_count = 0 ;
volatile uint32_t period_tc = 0 ;
uint32_t period_cycle = 0 ;
volatile int measuring = 0 ;
#define STR_LEN 128
char str[STR_LEN+1] ; /* print buffer */
CY_ISR(counter_tc_isr)
{
Counter_ReadStatusRegister() ;
tc_count++ ;
}
CY_ISR(rising_isr)
{
PeriodISR_ClearPending() ;
if (measuring) { /* end measure */
period_count = Counter_ReadCounter() ;
period_tc = tc_count ;
measuring = 0 ;
Counter_Stop() ;
Counter_WriteCounter(0) ;
} else { /* start measure */
measuring = 1 ;
tc_count = 0 ;
Counter_Enable() ;
}
}
CY_ISR(falling_isr)
{
PulsehiISR_ClearPending() ;
if (measuring) {
duty_count = Counter_ReadCounter() ;
duty_tc = tc_count ;
}
}
int main()
{
int prev_measuring = 0 ;
uint16_t period ;
UART_Start() ;
PeriodISR_StartEx(rising_isr); // Start period time ISR
PulsehiISR_StartEx(falling_isr); // Start high pulse time ISR
isr_tc_StartEx(counter_tc_isr) ; // tc counter ISR
Counter_Init(); // Init measurement counter, but not start
CyGlobalIntEnable; // Uncomment this line to enable global interrupts
UART_PutString("Period, High, Duty\n") ;
for(;;) { // Infinite for-loop
if ((prev_measuring == 1)&&(measuring == 0)) { // measuring done
period = Counter_ReadPeriod() ;
period_cycle = (period - period_count) + period_tc * period ;
duty_cycle = (period - duty_count) - duty_tc * period ;
snprintf(str, STR_LEN, "Cycle = %d ", period_cycle) ;
UART_PutString(str) ;
snprintf(str, STR_LEN, "High = %d ", duty_cycle) ;
UART_PutString(str) ;
snprintf(str, STR_LEN, "Duty = %d.%02 %\n",
100 * duty_cycle / period_cycle,
(10000 * duty_cycle / period_cycle) % 100
) ;
UART_PutString(str) ;
}
prev_measuring = measuring ;
} // end of infinity for-loop
i='F'; // for debugging only
} // end of main
=======================
Then when I ran with Clock_1 = 1kHz, I got around 21.0%, although expected 25.0%
Then I changed Clock_1 to 1MHz, the duty is now 24.0% (getting close to 25.0%)
Then I tried Clock_1 = 12MHz, but duty accuracy did not get improved
So I think that either the ramp slope of the signal or the overhead of isr()s makes the accuracy not as good.
The sample I posted in the earlier response had accuracy of .01 % but required much more resource(s).
Attached is your project with my modification.
moto
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
marek,
Make sure you connect P0.7 (test stimulus output) to the input P0.5 (PWMxIN) externally. The results you posted might be a floating P0.5. One way to confirm this is to configure PWMxIN as an input with pull-up or pull-down. If PWMxIN is left unconnected, then the output will always be constant.
Len
"Engineering is an Art. The Art of Compromise."
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
OK this works then but when PWM is not at input then program report random values. I think maybe code should be extended that if IRQ is not happening then disable capturing or is there other way how to detect if signal is present on pin? Thanks.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
marek,
I've modified the original program intended for the 050 eval board with LCD for your 059-KIT and the USB-UART.
Here is a summary of the modifications:
- I added 4 additional stimulus sources
- (see the schematic snippet below). The stimulus outputs are on P3.0, P3.1, P3.2 and P3.3. The original test stim is on P0.7.
- I deleted the LCD code references and added the UART calls to the USB_UART.
- I converted the ISR calls to cyapicallbacks. I believe this is a 'safer' way to implement component level ISRs.
Question:
When you were performing your original measurements, were you externally connecting the test stim output (P0.7) to the pulse monitor input (P0.5)? I get similar 'floating' reads if I don't connect P0.5 to a stimulus source. Otherwise, when I connect the 5 stimulus sources to P0.5 (one at a time) I get a reasonably value period and duty cycle.
Note:
- If the output frequency is too close to the sampling frequency (100KHz), the SW can't keep up reliably. As I get closer to the sampling frequency, the period is not as accurate. Eventually as the measure frequency is much nearer the sampling frequency, the SW appears to lockup (spending too much time in the ISRs) until I open up the input or switch to another slower stimulus.
- If the output frequency is too low, the wrap-around effect appears to become more significant and the period is not correct and/or the duty cycle reads greater than 100% which is definitely wrong.
Attached is my modified code if you want to check it out.
If you need to support frequency/period and duty-cycle measurements with more accuracy and reliability, you should set up HW counters with capture inputs. This allows the Counter HW to save the count value on the capture edge. Using the SW ISRs as being used in the project, is good if the inputs are relatively slow (not too slow) and you can support all the inputs you need with enough CPU speed.
Using the capture counters allow for more accurate results. This is because the counter count is loaded into a FIFO storage at the edge of capture. This lowers CPU usage and since there are four FIFO'd capture counts, the time criticality is not as bad. Using the ISRs means that the CPU tries to read the counter value as quickly as possible but the count might advance before the CPU can read it in the ISR.
Len
"Engineering is an Art. The Art of Compromise."
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
thanks for update. Hmm I didn't have anything connected on P0.5 (PWM input). I think test generator from P0.7 would be used for that purpose? But I have no clue how to connect those 2 pins. But when put input signal from external PWM to P0.5 then it works . Thanks a lot.
marek
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
marek,
A floating P0.5 input. That would explain the results.
Since you are using the CY8CKIT-059, see the diagram below. (Note: In this case, GND is already internally connected on the Kit)
I'm glad you got it working.
Len
"Engineering is an Art. The Art of Compromise."