First version of my PPM library.
Dependents: PPM_Test QuadCopter Quadcopter_mk2
Have a look at PPM_Test to see how this library is used.
Import programPPM_Test
Test program for my PPM library.
Diff: Ppm.cpp
- Revision:
- 2:b67f18c84c05
- Child:
- 3:d13b9e50312f
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Ppm.cpp Wed Mar 04 18:49:31 2015 +0000 @@ -0,0 +1,103 @@ +#include "Ppm.h" + +//Ppm reader by Joe Roberts, based on work by John Wolter +//This program takes the Ppm Signal (Pulse Position Modulation) from your RC transmitter and outputs the data between the min/max outputs passed into the constructor +//See +Ppm::Ppm(PinName pin, float minimumOutput, float maximumOutput, int minimumPulseTime, int maximumPulseTime, int numberOfChannels, int throttleChannel) +{ + //Assign local variables passed into constructor + _ppmPin = new InterruptIn(pin); + _minimumOutput = minimumOutput; + _maximumOutput = maximumOutput; + _minimumPulseTime = minimumPulseTime; + _maximumPulseTime = maximumPulseTime; + _numberOfChannels = numberOfChannels; + _throttleChannel = throttleChannel; + + //Set other variables + _currentChannel = 0; + _timeElapsed = 0; + _minFrameTime = 6000; + _shortTime = 800; + + //Initialise arrays + for(int i = 0; i < _numberOfChannels; i++) + { + _times[i] = 0; + _completeTimes[i] = 0; + } + + //Assign interrupt + _ppmPin->mode (PullUp); + _ppmPin->rise (this, &Ppm::SignalRise); + + //Start timer + _timer.start(); +} + +//Here is where all the work decoding the Ppm signal takes place +void Ppm::SignalRise() +{ + //Get the time taken since the last interrupt + _timeElapsed = _timer.read_us(); + + //If time is less than _shortTime then the channel timing is too short - ignore + if (_timeElapsed < _shortTime) return; + + //Disable the interrupt + _ppmPin->rise(NULL); + + //Reset the timer + _timer.reset(); + + //Check for a new frame signal, if before start of new frame then its a glitch - start a new frame + if ((_timeElapsed > _minFrameTime) && (_currentChannel != 0)) _currentChannel = 0; + + //Check for a new frame signal, if it is the start of a new frame then start new frame + if ((_timeElapsed > _minFrameTime ) && (_currentChannel == 0)) + { + //Assign interrupt + _ppmPin->rise (this, &Ppm::SignalRise); + return; + } + + //Save the time to the times array + _times[_currentChannel] = _timeElapsed; + _currentChannel++; + + //Check for a complete frame + if (_currentChannel == _numberOfChannels) + { + //Set channel iterator to 0 + _currentChannel = 0; + //Copy times array to complete times array + memcpy(_completeTimes, _times, sizeof(_times)); + } + + //Assign interrupt + _ppmPin->rise(this, &Ppm::SignalRise); + return; +} + +//Place mapped channel data into the passed in array +void Ppm::GetChannelData(float * channelData) +{ + //Iterate over the channel times array + for(int i = 0; i < _numberOfChannels; i++) + { + //Check the transmitter is still connected by checking the thottle + if((i == _throttleChannel - 1) && (_completeTimes[i] < _minimumPulseTime)) channelData[i] = -1; + else + { + //Map the channel times to value between the channel min and channel max + channelData[i] = Map(_completeTimes[i] ,_minimumPulseTime, _maximumPulseTime, _minimumOutput, _maximumOutput); + } + } + + return; +} + +float Ppm::Map(float input, float inputMin, float inputMax, float outputMin, float outputMax) +{ + return (input - inputMin) * (outputMax - outputMin) / (inputMax - inputMin) + outputMin; +} \ No newline at end of file