Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

PSoC™ 5, 3 & 1 Forum Discussions

Anonymous
Not applicable

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(;;){}

   

}

0 Likes
22 Replies
rola_264706
Level 8
Level 8
50 likes received 25 likes received 10 likes received

You need to use Volatile for interrupt variables 

0 Likes
Anonymous
Not applicable

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.

0 Likes
odissey1
Level 9
Level 9
First comment on KBA 1000 replies posted 750 replies posted

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

0 Likes
Anonymous
Not applicable

I attached the bundle in the comment below.

   

Many thanks

0 Likes
Anonymous
Not applicable

Thanks-clearing the timer's FIFO makes the led blink rapidly however the value of the capture is completely different each time I print it despite having an input signal with a steady 2ms pulse length.

   

I have attached the bundle.

0 Likes
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

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

0 Likes
Anonymous
Not applicable

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);

0 Likes
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

I cannot comment a code snippet, please post your actual project.

   

 

   

Bob

0 Likes
Anonymous
Not applicable

Sorry, should have done that earlier.

0 Likes
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

I changed your code to measure the pulse width. Reading a servo position from an RC?

   

 

   

Bob

0 Likes
Anonymous
Not applicable

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.

0 Likes
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

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

0 Likes
Anonymous
Not applicable

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.

0 Likes
Anonymous
Not applicable

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.

0 Likes
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

You did not use my attached project, I changed some more items in hardware and in your interrupt handler.

   

 

   

Bob

0 Likes
Anonymous
Not applicable

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.

0 Likes
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

Did you apply the correction I suggested?

   

 

   

Bob

0 Likes
Anonymous
Not applicable

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.

0 Likes
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

Did you scope your input signal? Can it be that the signal is inverted thus the low-time is between 1 and 2ms?

   

 

   

Bob

0 Likes
Anonymous
Not applicable

It is not. I checked that. 

   

If you are familiar with Arduino you can look at the following code which successfully collects receiver input. It is not my own but it works. Its doing the same thing as what I'm doing but using a different technique.

0 Likes
AlanH_86
Employee
Employee
100 replies posted 50 replies posted 25 solutions authored

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

0 Likes
AlanH_86
Employee
Employee
100 replies posted 50 replies posted 25 solutions authored

Well... I wrote a long article about this issue here: https://iotexpert.com/2017/05/17/psoc-5-timer-circuit-debug/

0 Likes