Two Capture Components

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Two Capture Components

Jump to solution
1,406 Views
alexit
Contributor I


I am working a project with QD4 and need to use two capture components for interrupts (both sharing TPM1.) The first capture is for a frequency signal 30 to 2000Hz, while the second is about half this speed (15-1000 Hz). I have configured both capture components to the same 65.384ms maximum. When I test with each capture independently they function correctly, both together give me erratic capture results. My ISR code is the same for both capture:

{

CAPx_GetCaptureValue(&time);

pin = CAPx_GetPinValue();

if (pin)

{

cap_x_high = time;

}

else

{

cap_x_low = time;

}

CAPx_Reset();

}

The signals are asynchronous, the erratic capture seems to occur when the interrupts occur close together. All the calcs are done outside of the ISR, with interrupts are disabled i.e.:

Cpu_DisableInt();

[do math]

Cpu_EnableInt();

I have also tried using an OverflowISR {overflow_counts++;} and NOT performing the Reset() for the timers, similar to:

cap_x_ = time - lasttime + (overflow_counts * TPM1MOD) ;

This doesn't work even when only one Capture is used. Where have I gone wrong?

0 Kudos
1 Solution
1,141 Views
Petr_H
NXP Employee
NXP Employee

Hi,

Great, I'm glad that you have resolved it.

Regarding your question: 'Should the value of TPMCNT always be zero after the reset?':

No, because the counter is only one and shared for all channels. The reset methods just remembers the current state of the counter and it's substracted from the capture value. You can check it in the generated capture driver code.

Regarding the Init_ADC example - unfortunately, I don't have any example for that . However, the settings should be quite straightforward, here is a screenshot of example what should work (but haven't tried it on hardware):

init_ADC_QD4.png

Best regards

Petr Hradsky

Processor Expert Support Team

View solution in original post

0 Kudos
13 Replies
1,141 Views
Petr_H
NXP Employee
NXP Employee

Yes, I think that it should work. You need to access the counter register directly (TPMCNT) because there are no methods for this in capture.

You should also expect that there might appear some issues at limit values with overflowing the counter while you read it.

Best regards

Petr Hradsky

Processor Expert Support Team

0 Kudos
1,141 Views
alexit
Contributor I

Petr,

I have tested accessing the TPMCNT register but there appears to be an overflow even though I am using the CAPx_Reset() in my ISR:

{

CAPx_GetCaptureValue(&time);

pin = CAPx_GetPinValue();

if (pin)

{

cap_x_high = time;

}

else

{

cap_x_low = time;

}

CAPx_Reset();

}

Should the value of TPMCNT always be zero after the reset?

Also, can you provide an example of your 2nd suggestion using Init_ADC for continuous sampling and reading the registers (is one register per channel or are they ADCRH(x) and ADCRL(x)?)

Thanks,

D

0 Kudos
1,141 Views
alexit
Contributor I

Not sure how proper, but using several boolean flags I have sequenced the computation with the incoming frequencies to avoid sequential interrupts. So far so good. Thanks!

0 Kudos
1,142 Views
Petr_H
NXP Employee
NXP Employee

Hi,

Great, I'm glad that you have resolved it.

Regarding your question: 'Should the value of TPMCNT always be zero after the reset?':

No, because the counter is only one and shared for all channels. The reset methods just remembers the current state of the counter and it's substracted from the capture value. You can check it in the generated capture driver code.

Regarding the Init_ADC example - unfortunately, I don't have any example for that . However, the settings should be quite straightforward, here is a screenshot of example what should work (but haven't tried it on hardware):

init_ADC_QD4.png

Best regards

Petr Hradsky

Processor Expert Support Team

0 Kudos
1,141 Views
alexit
Contributor I

Petr,

Thank you again for all your help!

Last question, can I also use the TempSensor with init_ADC? This option does not appear in the input pins list.

Regards,

D

0 Kudos
1,141 Views
Petr_H
NXP Employee
NXP Employee

You are welcome.

That's correct, the Pins group contains only physical pins allocation. To measure temprreature sensor, just select "Temperature sensor" at "Initial channel select" property. There do not have to be any pins configured for this.

Best regards

Petr Hradsky

Processor Expert Support Team

0 Kudos
1,141 Views
alexit
Contributor I

Petr,

Thank you, I tried to upload some more information but the post was not accepted. I am in process to synchronize the math function with the high-speed signal. It works mostly ok, now I need to ADD computation cycles when the frequency is very slow. Can I access the TPM1 counter as it is referenced in the Capture directly

(i.e. put a math cycle between the capture events such as if (cap_x_low >= 32768 && tpm1 >= 16383) {perform math}?

Thanks,

D

0 Kudos
1,141 Views
Petr_H
NXP Employee
NXP Employee

Hi,

the 2000Hz seems to quite a lot, there may be some issues related to interrupt coming earlier than the previous was serviced.

I recommend to put some output bit toggling at the beginning and end of ISR and see it on scope. Such problem might be quite difficult to investigate.

Is the appearance of the error related to the signal frequency?

What Processor Expert product and version are you using?

best regards

Petr Hradsky

Processor Expert Support Team

1,141 Views
alexit
Contributor I

Thanks for your suggestion, I have tried this and become more confused by the measurements. It appears as you suggest, there is an issue with the timing as one ISR conflicts with the other ISR, if I added the Overflow ISR this gets even worse (three ISR now conflict as the signals are not synchronized in any fashion)

And to make matters worse the ADC routine I have implemented during the math portion (when ISR are disabled) takes too long, so multiple ISR gets stacked. I am thinking my ADC is too slow, and must find a way this becomes 10x faster (or happens in the background)

Are these issues with conflicting ISR typical with the HCS08 processor? Do I need a more capable device for several different frequencies to happen simutaneously?

0 Kudos
1,141 Views
Petr_H
NXP Employee
NXP Employee

Well, I would have to know more about your application. Do you need to capture every single edge or measuring time after time is OK? Do you need to sample at ADC at exact period or as fast as the MCU can? Or should the ADC be somehow triggered?

Best regards

Petr Hradsky

Processor Expert Support Team

0 Kudos
1,141 Views
alexit
Contributor I

Petr,

I am using this for a motor control application with two independent feedback systems. The ADC channel and the higher frequency capture should be read most often, actual response for these signal are <4ms. The slower capture signal could safely ignore edges, as long as this was checked at some interval (every 100ms would be fine.)

Originally I was polling the higher frequency signal input to detect state change and the slower capture created the timing for triggering the ADC and making the calculations after every X edges were received. The polling became problematic as the math is processor-intensive and I'd lose changes in the frequency that are important to the next calculation cycle. Thus adding a second capture to ensure fewer edges are lost.

In the last interation, I wanted to use the timer overflow to pace the ADC polling. So I would CaptureFast and CaptureSlow until the shared timer overflowed, at that point a flag would set so I'd exit the ISR and temporarily disable interrupts while reading ADC and making the calc. This is where I saw the erratic behavior in the two capture events, it appears I only get good timer data from the capture events when I reset each in the ISR (so I never get the overflow.) I tried adding a Free Running Counter, but it looks like this plus the two captures all on the shared TPM1 (all interrupts) does something else unexpected.

From your suggestion above I have been checking timing for each portion of my code, CaptureFast ISR = 20us, CaptureSlow ISR = 28us, ADC read = 562us, calculation loop 500-900us. It feels like I am close to making this work, is it possible to disable the CaptureSlow interrutp seperately?

Thanks,

D

0 Kudos
1,141 Views
alexit
Contributor I

Probably a simple question, but what "time" is actually captured? The time the ISR was entered or the time of the actual event?

Capture Errors.jpg

This is probably the easiest way to look at what I suspect is the problem, every x edges I am still getting a late ISR I suspect is caused by the ADC or math performed. Does the time stamp correspond to the actual edge timing (left red arrow) or the time the ISR was serviced (right red arrow)?

Thanks,

D

0 Kudos
1,141 Views
Petr_H
NXP Employee
NXP Employee

Hi,

From your description, it seems that your application is reaching the timing limits...

I suggest to measure the time of processing code for the values itself (without any capture or ADC), if it's short enough to get between the lowest intervals that can occur. If not, you would need to optimize it or change the micro-controller to something more powerful.

If it's OK, the possible directions of improvement could be the following :

1. Try to increase optimization level of the compiler.

2. Use Init_ADC component instead of ADC, configure it and select "Continuous  conversion" mode. This means that ADC performs continuously and you can just grab results from the ADC result register (ADCRH, ADCRL). This would allow to avoid some overhead in ADC functions

3. Disable interrupts in capture components and read both of  them it in periodic manner using method GetCaptureValue. For example in some periodic timer interrupt or elsewhere. This period would have to be lower than the lowest period of the signal.

4. Use Init_TPM component, add there two channels and set them for capture and then write you own code directly handling the TPM registers to avoid overhead in 'Capture' component code.

Best regards

Petr Hradsky

Processor Expert Support Team