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@2:b67f18c84c05, 2015-03-04 (annotated)
- Committer:
- joe4465
- Date:
- Wed Mar 04 18:49:31 2015 +0000
- Revision:
- 2:b67f18c84c05
- Child:
- 3:d13b9e50312f
Modified library so that the InterruptIn pin is passed into constructor instead of the InterruptIn object
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
joe4465 | 2:b67f18c84c05 | 1 | #include "Ppm.h" |
joe4465 | 2:b67f18c84c05 | 2 | |
joe4465 | 2:b67f18c84c05 | 3 | //Ppm reader by Joe Roberts, based on work by John Wolter |
joe4465 | 2:b67f18c84c05 | 4 | //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 |
joe4465 | 2:b67f18c84c05 | 5 | //See |
joe4465 | 2:b67f18c84c05 | 6 | Ppm::Ppm(PinName pin, float minimumOutput, float maximumOutput, int minimumPulseTime, int maximumPulseTime, int numberOfChannels, int throttleChannel) |
joe4465 | 2:b67f18c84c05 | 7 | { |
joe4465 | 2:b67f18c84c05 | 8 | //Assign local variables passed into constructor |
joe4465 | 2:b67f18c84c05 | 9 | _ppmPin = new InterruptIn(pin); |
joe4465 | 2:b67f18c84c05 | 10 | _minimumOutput = minimumOutput; |
joe4465 | 2:b67f18c84c05 | 11 | _maximumOutput = maximumOutput; |
joe4465 | 2:b67f18c84c05 | 12 | _minimumPulseTime = minimumPulseTime; |
joe4465 | 2:b67f18c84c05 | 13 | _maximumPulseTime = maximumPulseTime; |
joe4465 | 2:b67f18c84c05 | 14 | _numberOfChannels = numberOfChannels; |
joe4465 | 2:b67f18c84c05 | 15 | _throttleChannel = throttleChannel; |
joe4465 | 2:b67f18c84c05 | 16 | |
joe4465 | 2:b67f18c84c05 | 17 | //Set other variables |
joe4465 | 2:b67f18c84c05 | 18 | _currentChannel = 0; |
joe4465 | 2:b67f18c84c05 | 19 | _timeElapsed = 0; |
joe4465 | 2:b67f18c84c05 | 20 | _minFrameTime = 6000; |
joe4465 | 2:b67f18c84c05 | 21 | _shortTime = 800; |
joe4465 | 2:b67f18c84c05 | 22 | |
joe4465 | 2:b67f18c84c05 | 23 | //Initialise arrays |
joe4465 | 2:b67f18c84c05 | 24 | for(int i = 0; i < _numberOfChannels; i++) |
joe4465 | 2:b67f18c84c05 | 25 | { |
joe4465 | 2:b67f18c84c05 | 26 | _times[i] = 0; |
joe4465 | 2:b67f18c84c05 | 27 | _completeTimes[i] = 0; |
joe4465 | 2:b67f18c84c05 | 28 | } |
joe4465 | 2:b67f18c84c05 | 29 | |
joe4465 | 2:b67f18c84c05 | 30 | //Assign interrupt |
joe4465 | 2:b67f18c84c05 | 31 | _ppmPin->mode (PullUp); |
joe4465 | 2:b67f18c84c05 | 32 | _ppmPin->rise (this, &Ppm::SignalRise); |
joe4465 | 2:b67f18c84c05 | 33 | |
joe4465 | 2:b67f18c84c05 | 34 | //Start timer |
joe4465 | 2:b67f18c84c05 | 35 | _timer.start(); |
joe4465 | 2:b67f18c84c05 | 36 | } |
joe4465 | 2:b67f18c84c05 | 37 | |
joe4465 | 2:b67f18c84c05 | 38 | //Here is where all the work decoding the Ppm signal takes place |
joe4465 | 2:b67f18c84c05 | 39 | void Ppm::SignalRise() |
joe4465 | 2:b67f18c84c05 | 40 | { |
joe4465 | 2:b67f18c84c05 | 41 | //Get the time taken since the last interrupt |
joe4465 | 2:b67f18c84c05 | 42 | _timeElapsed = _timer.read_us(); |
joe4465 | 2:b67f18c84c05 | 43 | |
joe4465 | 2:b67f18c84c05 | 44 | //If time is less than _shortTime then the channel timing is too short - ignore |
joe4465 | 2:b67f18c84c05 | 45 | if (_timeElapsed < _shortTime) return; |
joe4465 | 2:b67f18c84c05 | 46 | |
joe4465 | 2:b67f18c84c05 | 47 | //Disable the interrupt |
joe4465 | 2:b67f18c84c05 | 48 | _ppmPin->rise(NULL); |
joe4465 | 2:b67f18c84c05 | 49 | |
joe4465 | 2:b67f18c84c05 | 50 | //Reset the timer |
joe4465 | 2:b67f18c84c05 | 51 | _timer.reset(); |
joe4465 | 2:b67f18c84c05 | 52 | |
joe4465 | 2:b67f18c84c05 | 53 | //Check for a new frame signal, if before start of new frame then its a glitch - start a new frame |
joe4465 | 2:b67f18c84c05 | 54 | if ((_timeElapsed > _minFrameTime) && (_currentChannel != 0)) _currentChannel = 0; |
joe4465 | 2:b67f18c84c05 | 55 | |
joe4465 | 2:b67f18c84c05 | 56 | //Check for a new frame signal, if it is the start of a new frame then start new frame |
joe4465 | 2:b67f18c84c05 | 57 | if ((_timeElapsed > _minFrameTime ) && (_currentChannel == 0)) |
joe4465 | 2:b67f18c84c05 | 58 | { |
joe4465 | 2:b67f18c84c05 | 59 | //Assign interrupt |
joe4465 | 2:b67f18c84c05 | 60 | _ppmPin->rise (this, &Ppm::SignalRise); |
joe4465 | 2:b67f18c84c05 | 61 | return; |
joe4465 | 2:b67f18c84c05 | 62 | } |
joe4465 | 2:b67f18c84c05 | 63 | |
joe4465 | 2:b67f18c84c05 | 64 | //Save the time to the times array |
joe4465 | 2:b67f18c84c05 | 65 | _times[_currentChannel] = _timeElapsed; |
joe4465 | 2:b67f18c84c05 | 66 | _currentChannel++; |
joe4465 | 2:b67f18c84c05 | 67 | |
joe4465 | 2:b67f18c84c05 | 68 | //Check for a complete frame |
joe4465 | 2:b67f18c84c05 | 69 | if (_currentChannel == _numberOfChannels) |
joe4465 | 2:b67f18c84c05 | 70 | { |
joe4465 | 2:b67f18c84c05 | 71 | //Set channel iterator to 0 |
joe4465 | 2:b67f18c84c05 | 72 | _currentChannel = 0; |
joe4465 | 2:b67f18c84c05 | 73 | //Copy times array to complete times array |
joe4465 | 2:b67f18c84c05 | 74 | memcpy(_completeTimes, _times, sizeof(_times)); |
joe4465 | 2:b67f18c84c05 | 75 | } |
joe4465 | 2:b67f18c84c05 | 76 | |
joe4465 | 2:b67f18c84c05 | 77 | //Assign interrupt |
joe4465 | 2:b67f18c84c05 | 78 | _ppmPin->rise(this, &Ppm::SignalRise); |
joe4465 | 2:b67f18c84c05 | 79 | return; |
joe4465 | 2:b67f18c84c05 | 80 | } |
joe4465 | 2:b67f18c84c05 | 81 | |
joe4465 | 2:b67f18c84c05 | 82 | //Place mapped channel data into the passed in array |
joe4465 | 2:b67f18c84c05 | 83 | void Ppm::GetChannelData(float * channelData) |
joe4465 | 2:b67f18c84c05 | 84 | { |
joe4465 | 2:b67f18c84c05 | 85 | //Iterate over the channel times array |
joe4465 | 2:b67f18c84c05 | 86 | for(int i = 0; i < _numberOfChannels; i++) |
joe4465 | 2:b67f18c84c05 | 87 | { |
joe4465 | 2:b67f18c84c05 | 88 | //Check the transmitter is still connected by checking the thottle |
joe4465 | 2:b67f18c84c05 | 89 | if((i == _throttleChannel - 1) && (_completeTimes[i] < _minimumPulseTime)) channelData[i] = -1; |
joe4465 | 2:b67f18c84c05 | 90 | else |
joe4465 | 2:b67f18c84c05 | 91 | { |
joe4465 | 2:b67f18c84c05 | 92 | //Map the channel times to value between the channel min and channel max |
joe4465 | 2:b67f18c84c05 | 93 | channelData[i] = Map(_completeTimes[i] ,_minimumPulseTime, _maximumPulseTime, _minimumOutput, _maximumOutput); |
joe4465 | 2:b67f18c84c05 | 94 | } |
joe4465 | 2:b67f18c84c05 | 95 | } |
joe4465 | 2:b67f18c84c05 | 96 | |
joe4465 | 2:b67f18c84c05 | 97 | return; |
joe4465 | 2:b67f18c84c05 | 98 | } |
joe4465 | 2:b67f18c84c05 | 99 | |
joe4465 | 2:b67f18c84c05 | 100 | float Ppm::Map(float input, float inputMin, float inputMax, float outputMin, float outputMax) |
joe4465 | 2:b67f18c84c05 | 101 | { |
joe4465 | 2:b67f18c84c05 | 102 | return (input - inputMin) * (outputMax - outputMin) / (inputMax - inputMin) + outputMin; |
joe4465 | 2:b67f18c84c05 | 103 | } |