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

Howdy, What input capture mode is best for capturing a servo PPM using a PIC24FJ64GA002? I need to capture every edge (ICM2:ICM0 =3D 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 =910=92

bit 13 ICSIDL: Input Capture x Module Stop in Idle Control bit

1 =3D Input capture module will halt in CPU Idle mode 0 =3D Input capture module will continue to operate in CPU Idle mode

bit 12-8 Unimplemented: Read as =910=92

bit 7 ICTMR: Input Capture x Timer Select bit

1 =3D TMR2 contents are captured on capture event 0 =3D TMR3 contents are captured on capture event

bit 6-5 ICI1:ICI0: Select Number of Captures per Interrupt bits

11 =3D Interrupt on every fourth capture event 10 =3D Interrupt on every third capture event 01 =3D Interrupt on every second capture event 00 =3D Interrupt on every capture event

bit 4 ICOV: Input Capture x Overflow Status Flag bit (read-only)

1 =3D Input capture overflow occurred 0 =3D No input capture overflow occurred

bit 3 ICBNE: Input Capture x Buffer Empty Status bit (read-only)

1 =3D Input capture buffer is not empty, at least one more capture value can be read 0 =3D Input capture buffer is empty

bit 2-0 ICM2:ICM0: Input Capture x Mode Select bits(1)

111 =3D 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 =3D Unused (module disabled) 101 =3D Capture mode, every 16th rising edge 100 =3D Capture mode, every 4th rising edge 011 =3D Capture mode, every rising edge 010 =3D Capture mode, every falling edge 001 =3D Capture mode, every edge (rising and falling) =96 ICI bits do not control interrupt generation for this mode 000 =3D Input capture module turned off

thx, frenchy

Reply to
frenchy
Loading thread data ...

I'm not familar with the PIC24 chips so I'll limit my comments to general notes only. It seems as though you are getting lost in details and losing sight of general principals anyway. You don't need a lot of specialised peripherals to do this in a fairly straightforward manner, just a timer and a reasonably simple ISR. The first requirement is a free running timer. The speed of the timer is not critical provided that it does not wrap around within the maximum pulse length, say 2.5ms (it's supposed to be

2ms but some manufacturers have apparently started to take liberties there). However since you're using a 16 bit machine that shouldn't be a problem.

At the other end of the scale you need it to be fast enough to give sufficent resolution. The receiver is designed with servos in mind that typically have a resolution of around 7 bits, so an equivalent resolution in your device would imply a minimum timer frequency of around 100kHz. Obviously, faster would give you better resolution.

Set your input to interrupt on change. In your ISR the first thing to do is check the state of the pin - you need both rising and falling edges of the pulse.

If it is high you have found the rising edge of the pulse. Stash the timer value in a variable somewhere, eg riseTime, and return from interrupt.

If it is low then you have the falling edge. Copy the timer into another variable fallTime. Subtract fallTime from riseTime to give the pulse duration. If the timer was at a fairly high count at riseTime it is possible that the timer has overflowed during the pulse but don't worry about it - if that is the case then the subtraction will underflow and the duration will still be correct. Store the duration into another variable where it can be accessed by the surrounding program and return from interrupt.

Bear in mind that the value recorded using the method described here is the pulse duration, including the initial 1ms that is simply there to denote the presence of the pulse. This is may need some further conversion into a logical value to go from 0 to whatever maximum value you want, or a signed value centred on 1.5ms. However, what is appropriate depends on your circumstances and preferences so I'll leave it to you to decide what to do with the value obtained.

--
Andrew Smallshaw
andrews@sdf.lonestar.org
Reply to
Andrew Smallshaw

Subtract riseTime from fallTime...

--
Andrew Smallshaw
andrews@sdf.lonestar.org
Reply to
Andrew Smallshaw

Andrew, Thank you very much. Like you said in your response, I was caught up in the whole concept of using the "input capture" peripheral and I was blinded to the much simpler solution of using a free-running timer and just looking at the timer values every-time the internal comparator switched state. I already had 2 comparators sitting there and didnt even realize it!! This solved my software problem (timing and interrupts) and also my hardware problem (undetermined voltage levels due to battery sag). It worked great. Thank you.

respect, frenchy

Reply to
frenchy

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.