View previous topic :: View next topic |
Author |
Message |
40inD
Joined: 30 Jul 2007 Posts: 112 Location: Moscow, Russia
|
Is it possible to measure pulse width and period by one CCP? |
Posted: Wed Mar 02, 2016 4:12 am |
|
|
Is it possible to measure pulse width AND period by only one CCP? Maybe with using timers? |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9226 Location: Greensville,Ontario
|
|
Posted: Wed Mar 02, 2016 6:06 am |
|
|
Yes, you should read the Microchip application notes about how to do it as well Search for the apnote about 'measuring pulse width'. CCS may have an example in their extensive folder of example.
What method you choose will be based upon the peripherals available in your PIC.
Jay |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19513
|
|
Posted: Wed Mar 02, 2016 9:08 am |
|
|
A CCP, always uses a timer, when measuring pulse widths....
Big critical question is 'how fast'.
Yes it is possible, the problem is that there has to be some 'user intervention', such as changing the edge to be sensed in the interrupt. This takes time, so you can't do this for a really short pulse, or fast repetition rate.
It's basically simple, on the first capture, you toggle the edge to be sensed, and record the first value. On the second you toggle the edge again, and record the second value.
The example posted by Pcm_programmer at the end of this thread:
<http://www.ccsinfo.com/forum/viewtopic.php?t=45616&highlight=pulse+width+one+ccp>
Shows this being done. |
|
|
40inD
Joined: 30 Jul 2007 Posts: 112 Location: Moscow, Russia
|
|
Posted: Thu Mar 03, 2016 12:36 am |
|
|
It's understood, I have read that post, and measuring pulse width is no problem. But i don't understand, how to calculate period (or frequency) if it can change?
Need to measure 5-10 ms pulse @ 5-50 Hz.
I use 18f25k22 @ 20MHz , only CCP2 free. T1 used, ССP1 used as PWM. But I also have EXT_INT1 and EXT_INT 2 free.
If I feed signal simultaneously into CCP and ext_int, and ext_int will count period with help of some free timer? |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Thu Mar 03, 2016 3:39 am |
|
|
What accuracy/resolution are you wanting?
Mike |
|
|
40inD
Joined: 30 Jul 2007 Posts: 112 Location: Moscow, Russia
|
|
Posted: Thu Mar 03, 2016 3:51 am |
|
|
Let's say 0.1 - 0.2 ms
I think it must look something like this:
Code: |
#INT_EXT1
void EXT1_isr(void)
{
period=get_timer0();
set_timer0(0);
}
#INT_CCP2 // from PCM programmer code
void CCP2_isr(void)
{
static int16 rising_edge;
// If current interrupt is for rising edge.
if(capture_rising_edge)
{
setup_ccp1(CCP_CAPTURE_FE);
capture_rising_edge = FALSE;
rising_edge = CCP_2;
}
else
{
setup_ccp1(CCP_CAPTURE_RE);
capture_rising_edge = TRUE;
ccp_delta = CCP_2 - rising_edge;
got_pulse_width = TRUE;
}
if(got_pulse_width)
{
pulse_width_ms = ccp_delta / (125); // adjust divider
got_pulse_width = FALSE;
}
}
|
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19513
|
|
Posted: Thu Mar 03, 2016 9:31 am |
|
|
Don't do the maths in the interrupt. Look at PCM_programmer's code. He just takes the readings in the interrupts, and this is what you should do.
When it flags 'got_pulse_width', record one of the two readings into a 'temporary' variable. The _next_ time a pulse width is signalled, the time between the reading this time, and the one stored, is the period of the signal. |
|
|
40inD
Joined: 30 Jul 2007 Posts: 112 Location: Moscow, Russia
|
|
Posted: Fri Mar 04, 2016 12:14 am |
|
|
Ok, thanks.
What do you think about
Code: |
#INT_EXT1
void EXT1_isr(void)
{
period=get_timer0();
set_timer0(0);
}
|
? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19513
|
|
Posted: Fri Mar 04, 2016 2:22 am |
|
|
Look at PCM_programmer's code.....
You are no longer measuring the pulse width.
Just amend it as:
Code: |
int1 capture_rising_edge;
int1 got_pulse_width;
int16 ccp_delta;
int16 period_delta;
#int_ccp1
void ccp1_isr(void)
{
static int16 t1_rising_edge;
static int16 old_t1;
static int1 first=TRUE;
// If current interrupt is for rising edge.
if(capture_rising_edge)
{
setup_ccp1(CCP_CAPTURE_FE);
capture_rising_edge = FALSE;
t1_rising_edge = CCP_1;
period_delta=old_t1-t1_rising_edge;
old_t1=t1_rising_edge;
}
else
{
setup_ccp1(CCP_CAPTURE_RE);
capture_rising_edge = TRUE;
ccp_delta = CCP_1 - t1_rising_edge;
if (first)
first=FALSE;
else
got_pulse_width = TRUE;
}
}
|
Then when 'got_pulse_width' goes true, there are now _two_ values
recorded. ccp_delta for the pulse width, and period_delta for the
period.
Use exactly the same code as he shows (modified to suit your clock
rate - the '125' needs to change, and if you want pulse times more accurately than 'mSec', you probably don't actually want this), but save a
local copy of period_delta as well as ccp_delta. Then do the
same maths on this to get the pulse period. |
|
|
|