Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: PPM_Test QuadCopter Quadcopter_mk2
PPM.cpp@0:083ed8cea5ff, 2014-08-26 (annotated)
- Committer:
- joe4465
- Date:
- Tue Aug 26 15:54:34 2014 +0000
- Revision:
- 0:083ed8cea5ff
- Child:
- 1:fb0ab71eb0ea
First version of my PPM library.
Who changed what in which revision?
| User | Revision | Line number | New contents of line |
|---|---|---|---|
| joe4465 | 0:083ed8cea5ff | 1 | #include "PPM.h" |
| joe4465 | 0:083ed8cea5ff | 2 | |
| joe4465 | 0:083ed8cea5ff | 3 | //PPM reader by Joe Roberts, based on work by John Wolter |
| joe4465 | 0:083ed8cea5ff | 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 | 0:083ed8cea5ff | 5 | //See |
| joe4465 | 0:083ed8cea5ff | 6 | PPM::PPM(InterruptIn *ppmPin, float minimumOutput, float maximumOutput, int minimumPulseTime, int maximumPulseTime, int numberOfChannels, int throttleChannel) |
| joe4465 | 0:083ed8cea5ff | 7 | { |
| joe4465 | 0:083ed8cea5ff | 8 | //Assign local variables passed into constructor |
| joe4465 | 0:083ed8cea5ff | 9 | _ppmPin = ppmPin; |
| joe4465 | 0:083ed8cea5ff | 10 | _minimumOutput = minimumOutput; |
| joe4465 | 0:083ed8cea5ff | 11 | _maximumOutput = maximumOutput; |
| joe4465 | 0:083ed8cea5ff | 12 | _minimumPulseTime = minimumPulseTime; |
| joe4465 | 0:083ed8cea5ff | 13 | _maximumPulseTime = maximumPulseTime; |
| joe4465 | 0:083ed8cea5ff | 14 | _numberOfChannels = numberOfChannels; |
| joe4465 | 0:083ed8cea5ff | 15 | _throttleChannel = throttleChannel; |
| joe4465 | 0:083ed8cea5ff | 16 | |
| joe4465 | 0:083ed8cea5ff | 17 | //Set other variables |
| joe4465 | 0:083ed8cea5ff | 18 | _currentChannel = 0; |
| joe4465 | 0:083ed8cea5ff | 19 | _timeElapsed = 0; |
| joe4465 | 0:083ed8cea5ff | 20 | _minFrameTime = 6000; |
| joe4465 | 0:083ed8cea5ff | 21 | _shortTime = 800; |
| joe4465 | 0:083ed8cea5ff | 22 | |
| joe4465 | 0:083ed8cea5ff | 23 | //Initialise arrays |
| joe4465 | 0:083ed8cea5ff | 24 | for(int i = 0; i < _numberOfChannels; i++) |
| joe4465 | 0:083ed8cea5ff | 25 | { |
| joe4465 | 0:083ed8cea5ff | 26 | _times[i] = 0; |
| joe4465 | 0:083ed8cea5ff | 27 | _completeTimes[i] = 0; |
| joe4465 | 0:083ed8cea5ff | 28 | } |
| joe4465 | 0:083ed8cea5ff | 29 | |
| joe4465 | 0:083ed8cea5ff | 30 | //Assign interrupt |
| joe4465 | 0:083ed8cea5ff | 31 | _ppmPin->mode (PullUp); |
| joe4465 | 0:083ed8cea5ff | 32 | _ppmPin->rise (this, &PPM::SignalRise); |
| joe4465 | 0:083ed8cea5ff | 33 | |
| joe4465 | 0:083ed8cea5ff | 34 | //Start timer |
| joe4465 | 0:083ed8cea5ff | 35 | _timer.start(); |
| joe4465 | 0:083ed8cea5ff | 36 | } |
| joe4465 | 0:083ed8cea5ff | 37 | |
| joe4465 | 0:083ed8cea5ff | 38 | //Here is where all the work decoding the PPM signal takes place |
| joe4465 | 0:083ed8cea5ff | 39 | void PPM::SignalRise() |
| joe4465 | 0:083ed8cea5ff | 40 | { |
| joe4465 | 0:083ed8cea5ff | 41 | //Get the time taken since the last interrupt |
| joe4465 | 0:083ed8cea5ff | 42 | _timeElapsed = _timer.read_us(); |
| joe4465 | 0:083ed8cea5ff | 43 | |
| joe4465 | 0:083ed8cea5ff | 44 | //If time is less than _shortTime then the channel timing is too short - ignore |
| joe4465 | 0:083ed8cea5ff | 45 | if (_timeElapsed < _shortTime) return; |
| joe4465 | 0:083ed8cea5ff | 46 | |
| joe4465 | 0:083ed8cea5ff | 47 | //Disable the interrupt |
| joe4465 | 0:083ed8cea5ff | 48 | _ppmPin->rise(NULL); |
| joe4465 | 0:083ed8cea5ff | 49 | |
| joe4465 | 0:083ed8cea5ff | 50 | //Reset the timer |
| joe4465 | 0:083ed8cea5ff | 51 | _timer.reset(); |
| joe4465 | 0:083ed8cea5ff | 52 | |
| joe4465 | 0:083ed8cea5ff | 53 | //Check for a new frame signal, if before start of new frame then its a glitch - start a new frame |
| joe4465 | 0:083ed8cea5ff | 54 | if ((_timeElapsed > _minFrameTime) && (_currentChannel != 0)) _currentChannel = 0; |
| joe4465 | 0:083ed8cea5ff | 55 | |
| joe4465 | 0:083ed8cea5ff | 56 | //Check for a new frame signal, if it is the start of a new frame then start new frame |
| joe4465 | 0:083ed8cea5ff | 57 | if ((_timeElapsed > _minFrameTime ) && (_currentChannel == 0)) |
| joe4465 | 0:083ed8cea5ff | 58 | { |
| joe4465 | 0:083ed8cea5ff | 59 | //Assign interrupt |
| joe4465 | 0:083ed8cea5ff | 60 | _ppmPin->rise (this, &PPM::SignalRise); |
| joe4465 | 0:083ed8cea5ff | 61 | return; |
| joe4465 | 0:083ed8cea5ff | 62 | } |
| joe4465 | 0:083ed8cea5ff | 63 | |
| joe4465 | 0:083ed8cea5ff | 64 | //Save the time to the times array |
| joe4465 | 0:083ed8cea5ff | 65 | _times[_currentChannel] = _timeElapsed; |
| joe4465 | 0:083ed8cea5ff | 66 | _currentChannel++; |
| joe4465 | 0:083ed8cea5ff | 67 | |
| joe4465 | 0:083ed8cea5ff | 68 | //Check for a complete frame |
| joe4465 | 0:083ed8cea5ff | 69 | if (_currentChannel == _numberOfChannels) |
| joe4465 | 0:083ed8cea5ff | 70 | { |
| joe4465 | 0:083ed8cea5ff | 71 | //Set channel iterator to 0 |
| joe4465 | 0:083ed8cea5ff | 72 | _currentChannel = 0; |
| joe4465 | 0:083ed8cea5ff | 73 | //Copy times array to complete times array |
| joe4465 | 0:083ed8cea5ff | 74 | memcpy(_completeTimes, _times, sizeof(_times)); |
| joe4465 | 0:083ed8cea5ff | 75 | } |
| joe4465 | 0:083ed8cea5ff | 76 | |
| joe4465 | 0:083ed8cea5ff | 77 | //Assign interrupt |
| joe4465 | 0:083ed8cea5ff | 78 | _ppmPin->rise(this, &PPM::SignalRise); |
| joe4465 | 0:083ed8cea5ff | 79 | return; |
| joe4465 | 0:083ed8cea5ff | 80 | } |
| joe4465 | 0:083ed8cea5ff | 81 | |
| joe4465 | 0:083ed8cea5ff | 82 | //Place mapped channel data into the passed in array |
| joe4465 | 0:083ed8cea5ff | 83 | void PPM::GetChannelData(float * channelData) |
| joe4465 | 0:083ed8cea5ff | 84 | { |
| joe4465 | 0:083ed8cea5ff | 85 | //Iterate over the channel times array |
| joe4465 | 0:083ed8cea5ff | 86 | for(int i = 0; i < _numberOfChannels; i++) |
| joe4465 | 0:083ed8cea5ff | 87 | { |
| joe4465 | 0:083ed8cea5ff | 88 | //Check the transmitter is still connected by checking the thottle |
| joe4465 | 0:083ed8cea5ff | 89 | if((i == _throttleChannel - 1) && (_completeTimes[i] < _minimumPulseTime)) channelData[i] = -1; |
| joe4465 | 0:083ed8cea5ff | 90 | else |
| joe4465 | 0:083ed8cea5ff | 91 | { |
| joe4465 | 0:083ed8cea5ff | 92 | //Map the channel times to value between the channel min and channel max |
| joe4465 | 0:083ed8cea5ff | 93 | channelData[i] = (_completeTimes[i] - _minimumPulseTime) * (_maximumOutput - _minimumOutput) / (_maximumPulseTime - _minimumPulseTime) + _minimumOutput; |
| joe4465 | 0:083ed8cea5ff | 94 | } |
| joe4465 | 0:083ed8cea5ff | 95 | } |
| joe4465 | 0:083ed8cea5ff | 96 | |
| joe4465 | 0:083ed8cea5ff | 97 | return; |
| joe4465 | 0:083ed8cea5ff | 98 | } |