Maker Pro
Maker Pro

Software question: Capturing a servo PPM using a PIC24FJ64GA002...

F

frenchy

Howdy,
What input capture mode is best for capturing a servo PPM using a
PIC24FJ64GA002? I need to capture every edge (ICM2:ICM0 = 001), but
then the time between two captures isn't necessarily always the pulse
I am looking for....it might be the 18ms "dead time" between pulses.
I wish I could set it to capture the falling, then rising edges and
interrupt on the latter (my polarity is reversed if I use an inverting
common emitter buffer for interfacing). But according to the below
choices, if I want to detect both rising AND falling, it has no
intelligence as to whether the interrupt was caused by rising or
falling. Using a hardware peripheral like this, I didnt think I had
to implement all kinds of software checking to see what I ended up
with (to keep the ISR short)..

any comments would be helpful.
respectfully,
frenchy

bit 15-14 Unimplemented: Read as '0'

bit 13 ICSIDL: Input Capture x Module Stop in Idle Control bit
1 = Input capture module will halt in CPU Idle mode
0 = Input capture module will continue to operate in CPU Idle mode

bit 12-8 Unimplemented: Read as '0'

bit 7 ICTMR: Input Capture x Timer Select bit
1 = TMR2 contents are captured on capture event
0 = TMR3 contents are captured on capture event

bit 6-5 ICI1:ICI0: Select Number of Captures per Interrupt bits
11 = Interrupt on every fourth capture event
10 = Interrupt on every third capture event
01 = Interrupt on every second capture event
00 = Interrupt on every capture event

bit 4 ICOV: Input Capture x Overflow Status Flag bit (read-only)
1 = Input capture overflow occurred
0 = No input capture overflow occurred

bit 3 ICBNE: Input Capture x Buffer Empty Status bit (read-only)
1 = Input capture buffer is not empty, at least one more capture value
can be read
0 = Input capture buffer is empty

bit 2-0 ICM2:ICM0: Input Capture x Mode Select bits(1)
111 = Input capture functions as interrupt pin only when device is in
Sleep or Idle mode (rising edge
detect only, all other control bits are not applicable)
110 = Unused (module disabled)
101 = Capture mode, every 16th rising edge
100 = Capture mode, every 4th rising edge
011 = Capture mode, every rising edge
010 = Capture mode, every falling edge
001 = Capture mode, every edge (rising and falling) - ICI<1:0> bits do
not control interrupt generation
for this mode
000 = Input capture module turned off

thx,
frenchy
 
J

Jan Panteltje


Keep shadow register for port.
Interrupt on change service routine:
Compare to shadow, what bit changed?
is it 1? start counter for this bit, update shadow, reti
is it 0? stop counter for this bit,
do something with counter value, reti

'start counter' can even be as simple a setting a flag, and having main
update a register every x us as long as that flag is set.

It can even be done without interrups with 100% polling.

Use your imagination.
 
S

Spehro Pefhany

Howdy,
What input capture mode is best for capturing a servo PPM using a
PIC24FJ64GA002? I need to capture every edge (ICM2:ICM0 = 001), but
then the time between two captures isn't necessarily always the pulse
I am looking for....it might be the 18ms "dead time" between pulses.
I wish I could set it to capture the falling, then rising edges and
interrupt on the latter (my polarity is reversed if I use an inverting
common emitter buffer for interfacing). But according to the below
choices, if I want to detect both rising AND falling, it has no
intelligence as to whether the interrupt was caused by rising or
falling. Using a hardware peripheral like this, I didnt think I had
to implement all kinds of software checking to see what I ended up
with (to keep the ISR short)..

If you can guarantee that the time between edges is a minimum of the
maximum ISR service time including latency you could just toggle the
edge capture mode between 'rising' and 'falling' within your ISR. If
you can't.. you'll have difficulty capturing the information anyway,
unless I'm forgetting some features that MCU has..
Best regards,
Spehro Pefhany
 
J

JosephKK

If you can guarantee that the time between edges is a minimum of the
maximum ISR service time including latency you could just toggle the
edge capture mode between 'rising' and 'falling' within your ISR. If
you can't.. you'll have difficulty capturing the information anyway,
unless I'm forgetting some features that MCU has..
Best regards,
Spehro Pefhany

I can't remember a uC that can trigger on the edge of an I/O pin that
could not capture the value of that I/O pin in the ISR.
 
S

Spehro Pefhany

I can't remember a uC that can trigger on the edge of an I/O pin that
could not capture the value of that I/O pin in the ISR.

The problem is to grab the value of a free-running counter/timer at
the precise moment of pin state change. While that's built into
peripheral hardware in many micros, the smaller ones only have a
single register to store the timer value. If you don't grab the value
and put it somewhere before the next edge comes along, the data is
lost. If there's multiple levels of buffering (whether by FIFO, DMA or
otherwise) you can do things such as accurately measuring the width of
a very narrow pulse provided it doesn't occcur so often as to
overwhelm the ISR service routine. RC servo pulses are neither narrow
nor frequent so it's not really a problem for reasonable clock rates.

If you have an int that will trigger on state change (either edge) and
are counting on being able to read the pin in the ISR, you'd better be
able to guarantee that the pin state doesn't change in the time it
takes to trigger the interrupt, complete any higher priority ISRs,
store the context, and execute the ISR to the point of reading the
pin.



Best regards,
Spehro Pefhany
 
J

JosephKK

The problem is to grab the value of a free-running counter/timer at
the precise moment of pin state change. While that's built into
peripheral hardware in many micros, the smaller ones only have a
single register to store the timer value. If you don't grab the value
and put it somewhere before the next edge comes along, the data is
lost. If there's multiple levels of buffering (whether by FIFO, DMA or
otherwise) you can do things such as accurately measuring the width of
a very narrow pulse provided it doesn't occcur so often as to
overwhelm the ISR service routine. RC servo pulses are neither narrow
nor frequent so it's not really a problem for reasonable clock rates.

If you have an int that will trigger on state change (either edge) and
are counting on being able to read the pin in the ISR, you'd better be
able to guarantee that the pin state doesn't change in the time it
takes to trigger the interrupt, complete any higher priority ISRs,
store the context, and execute the ISR to the point of reading the
pin.



Best regards,
Spehro Pefhany

I do not see any problems with your contribution. Proper ISRs are
very fast. If the micro cannot handle the load it is the wrong micro.
Whether or not you stay in the same family is a design decision.
 
Top