- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I want to measure the width of each pulse from an external signal. For this I set up a timer to run continuously,trigger at the rising edge and capture at the falling edge. There is an ISR attached to the interrupt terminal of the timer and is called Channel_1_ISR as can be seen below.
The ISR runs once since the led state is only toggled once but not after that. What am I missing?
CY_ISR(Channel_1_ISR_Handler){
Channel_1_Count=Channel_1_Timer_ReadCapture();
onboard_led_Write(~onboard_led_Read());
Channel_1_ISR_ClearPending();
}
int main(void)
{
CyGlobalIntEnable;
onboard_led_Write(~onboard_led_Read());
Channel_1_Timer_Start();
Channel_1_Timer_EnableTrigger();
Channel_1_ISR_Enable();
Channel_1_ISR_StartEx(Channel_1_ISR_Handler);
for(;;){}
}
- Labels:
-
PSoC 5LP
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You need to use Volatile for interrupt variables
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Good catch but that doesn't explain why the led is only toggled once because I know there is a constant 2ms pulse being fed to the timer. When I put print statements in the for loop then those work indicating that the ISR runs only once initially and never runs after that. My only guess is that something is disabling the ISR but I am unsure of what.
I just added in the volatile but as expected it doesn't solve the problem here. Thanks for pointing that out though.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I believe that when using a trigger you have to reset Timer after isr also, else only one interrupt will fire. Please post your project for review. File->Create workspace bundle-> minimal
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I attached the bundle in the comment below.
Many thanks
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You could use Timer_ReadStatus() API to clear any of the interrupt bits. The capture freezes the current counter statre into the FIFO, so to measure the time between pulses, easiest is to reset the counter to zero. Since it is a down counter you need to subtract the capture value from the period value.
A tip for later measures: When you are interested in the pulse width, just connect the enable input to the signal.
Bob
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I have changed the code in the ISR to the following and am writing 100000 into the counter as the initial value. I am still getting the wrong results though for the pulse width. As I vary the pulse width from 1 to 2ms there is close to no difference in the value of the counter.
Channel_1_Count=Channel_1_Timer_ReadCounter();
onboard_led_Write(~onboard_led_Read());
Channel_1_ISR_ClearPending();
Channel_1_Timer_ClearFIFO();
Channel_1_Timer_ReadStatusRegister();
Channel_1_Timer_WriteCounter(100000);
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I cannot comment a code snippet, please post your actual project.
Bob
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I downloaded your code but as I move throttle from 1ms to 2ms there is no difference in the counter value- it is always at 99971. At least there is consistency now. Interestingly, the frequency of the blinking led matches that of the input signal indicating that the pulse width is being detected correctly but for some reason the stored value is incorrect.
Close- Im trying to read throttle,yaw,pitch and roll from an RC transmitter. I was planning on doing this with pin change interrupts which is what I found on a DIY flight controller online for an arduino. The flight controller has a 250Hz refresh rate using an Arduino which is impressive for an Arduino however I wanted to write a flight controller with a faster refresh rate and psoc UDBs I thought would allow me to get more out of the cpu by delegating control of sending esc pulses and reading receiver inputs to the UDB components. Having the ISR though defeats the purpose so I would like to try to save receiver inputs without an ISR in the first place. I could do this easily by writing verilog code for an FPGA but Id rather have just one controller on board rather than an MCU and an FPGA.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Replace the line containing
Channel_1_Count = Channel_1_Timer_ReadCounter();
with
Channel_1_Count = Channel_1_Timer_ReadCapture();
Sorry, deleted the wrong line
Bob
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
It still does not work unfortunately- the value I see when I print to screen oscillates around 6200 despite changing input pulse from 1 to 2ms. I double checked with an arduino to make sure that the signal can be detected correctly-therefore there is no problem with the outputs of the receiver.
Once in a while there seems to be a "glitch" and the value printed is ~2400 but apart from that it is almost always ~6200.
I have attached the bundle below.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Here are the files showing the outputs- the names are self explanatory but I printed the output by putting the print statement in the ISR itself and in main for 1ms and 2ms pulse input. The results are way off and I can't seem to figure out what's going wrong. Perhaps cypress' UDBs cant handle this frequency however 1000 Hz is hardly what I'd call high frequency. I will try the pin change ISR technique to see if that works- it should since it works flawlessly on a 16MHz arduino.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You did not use my attached project, I changed some more items in hardware and in your interrupt handler.
Bob
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
My apologies! It's 4:15am where I am so I'm not as alert as I can be.
Your program's output is far more consistent but it doesnt change with change in input. Attached is the output file below. Furthermore- the led seems to be blinking at around 2Hz despite the fact that input is 1000Hz.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Did you apply the correction I suggested?
Bob
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I did-changing readCounter to readCapture- however I dont see how this would help as it just changes the value by a constant hence if the value doesnt change with the pulse then this change will not work. I could be misunderstanding something though.
Attached is the bundle.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Did you scope your input signal? Can it be that the signal is inverted thus the low-time is between 1 and 2ms?
Bob
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Here are two projects... one is more software oriented... the other is a more HW oriented solution.
I added a bunch of commands to the serial program to help.
The key 't': puts out a 1234us pulse (to be measured)
The key 'y' puts out a 12ms pulse (which causes overflow)
I will write about exactly how they both work with screen shots later in the week on iotexpert.com
Notice that I changed the unit of measure to uS so that the calculations were easy
Alan
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Well... I wrote a long article about this issue here: https://iotexpert.com/2017/05/17/psoc-5-timer-circuit-debug/