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.

Ppm.cpp

Committer:
joe4465
Date:
2015-04-01
Revision:
3:d13b9e50312f
Parent:
2:b67f18c84c05

File content as of revision 3:d13b9e50312f:

#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, int minimumOutput, int 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(double* 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; 
}

double Ppm::Map(double input, double inputMin, double inputMax, double outputMin, double outputMax)
{
    return (input - inputMin) * (outputMax - outputMin) / (inputMax - inputMin) + outputMin;
}