A simple API/Software interface to the LPC17xx PWM peripheral to provide control to up to six RC type servo controllers.

Committer:
AjK
Date:
Thu May 19 22:48:17 2011 +0000
Revision:
3:1232505e7206
Parent:
2:d6a018232650
1.3 See ChangeLog.h

Who changed what in which revision?

UserRevisionLine numberNew contents of line
AjK 2:d6a018232650 1 /*
AjK 2:d6a018232650 2 Copyright (c) 2011 Andy Kirkham
AjK 2:d6a018232650 3
AjK 2:d6a018232650 4 Permission is hereby granted, free of charge, to any person obtaining a copy
AjK 2:d6a018232650 5 of this software and associated documentation files (the "Software"), to deal
AjK 2:d6a018232650 6 in the Software without restriction, including without limitation the rights
AjK 2:d6a018232650 7 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
AjK 2:d6a018232650 8 copies of the Software, and to permit persons to whom the Software is
AjK 2:d6a018232650 9 furnished to do so, subject to the following conditions:
AjK 2:d6a018232650 10
AjK 2:d6a018232650 11 The above copyright notice and this permission notice shall be included in
AjK 2:d6a018232650 12 all copies or substantial portions of the Software.
AjK 2:d6a018232650 13
AjK 2:d6a018232650 14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
AjK 2:d6a018232650 15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
AjK 2:d6a018232650 16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AjK 2:d6a018232650 17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
AjK 2:d6a018232650 18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
AjK 2:d6a018232650 19 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
AjK 2:d6a018232650 20 THE SOFTWARE.
AjK 2:d6a018232650 21 */
AjK 2:d6a018232650 22
AjK 2:d6a018232650 23 #ifndef AJK_SIMPLERCSERVOS_H
AjK 2:d6a018232650 24 #define AJK_SIMPLERCSERVOS_H
AjK 2:d6a018232650 25
AjK 2:d6a018232650 26 #include "LPC17xx.h"
AjK 2:d6a018232650 27 #include "SimpleRCmbed.h"
AjK 2:d6a018232650 28
AjK 2:d6a018232650 29 namespace AjK {
AjK 2:d6a018232650 30
AjK 2:d6a018232650 31 class SimpleRCservos {
AjK 2:d6a018232650 32
AjK 2:d6a018232650 33 public:
AjK 2:d6a018232650 34 enum Servo { NoServo0, Servo1, Servo2, Servo3, Servo4, Servo5, Servo6, NumOfServos };
AjK 2:d6a018232650 35
AjK 2:d6a018232650 36 protected:
AjK 2:d6a018232650 37 PinName _pinName;
AjK 2:d6a018232650 38
AjK 2:d6a018232650 39 uint32_t _duty;
AjK 2:d6a018232650 40
AjK 2:d6a018232650 41 uint32_t _mid[NumOfServos];
AjK 2:d6a018232650 42
AjK 2:d6a018232650 43 double _limitMax[NumOfServos];
AjK 2:d6a018232650 44
AjK 2:d6a018232650 45 double _limitMin[NumOfServos];
AjK 2:d6a018232650 46
AjK 2:d6a018232650 47 uint32_t _msMin[NumOfServos];
AjK 2:d6a018232650 48
AjK 2:d6a018232650 49 uint32_t _msMax[NumOfServos];
AjK 2:d6a018232650 50
AjK 2:d6a018232650 51 void init(uint32_t duty);
AjK 2:d6a018232650 52
AjK 2:d6a018232650 53 void setRangeMin(Servo ch, uint32_t u) { _msMin[ch] = u * 24; }
AjK 2:d6a018232650 54
AjK 2:d6a018232650 55 void setRangeMax(Servo ch, uint32_t u) { _msMax[ch] = (u * 24) - _msMin[ch]; }
AjK 2:d6a018232650 56
AjK 2:d6a018232650 57 void setMRx(Servo ch, uint32_t value);
AjK 2:d6a018232650 58
AjK 2:d6a018232650 59 double limit(Servo ch, double degrees);
AjK 2:d6a018232650 60
AjK 2:d6a018232650 61 public:
AjK 2:d6a018232650 62
AjK 2:d6a018232650 63 /** Constructor
AjK 2:d6a018232650 64 */
AjK 2:d6a018232650 65 SimpleRCservos() { init(480000UL); setDuty(); }
AjK 2:d6a018232650 66
AjK 2:d6a018232650 67 /** setDuty
AjK 2:d6a018232650 68 *
AjK 2:d6a018232650 69 * Set's the duty, or period, of the PWM pulses.
AjK 2:d6a018232650 70 * The default is 20ms and the parameter passed in is the
AjK 2:d6a018232650 71 * number of "clock ticks" that represents the period.
AjK 2:d6a018232650 72 * 480000 gives rise to 20ms by default. It's rare that
AjK 2:d6a018232650 73 * you would alter this value. Remember, with the PWM
AjK 2:d6a018232650 74 * peripheral there is only a single, common, period for
AjK 2:d6a018232650 75 * all six PWM outputs.
AjK 2:d6a018232650 76 *
AjK 2:d6a018232650 77 * @param duty The number of "clock ticks" for the duty cycle.
AjK 2:d6a018232650 78 */
AjK 2:d6a018232650 79 void setDuty(uint32_t duty = 480000);
AjK 2:d6a018232650 80
AjK 2:d6a018232650 81 /** enable1
AjK 2:d6a018232650 82 *
AjK 2:d6a018232650 83 * Enable PWM channel 1.
AjK 2:d6a018232650 84 *
AjK 2:d6a018232650 85 * @param PinName p26(P2_0) or LED1(P1_18)
AjK 2:d6a018232650 86 */
AjK 2:d6a018232650 87 void enable1(PinName pin = p26);
AjK 2:d6a018232650 88
AjK 2:d6a018232650 89 /** enable2
AjK 2:d6a018232650 90 *
AjK 2:d6a018232650 91 * Enable PWM channel 2.
AjK 2:d6a018232650 92 *
AjK 2:d6a018232650 93 * @param PinName p25(P2_1) or LED2(P1_20)
AjK 2:d6a018232650 94 */
AjK 2:d6a018232650 95 void enable2(PinName pin = p25);
AjK 2:d6a018232650 96
AjK 2:d6a018232650 97 /** enable3
AjK 2:d6a018232650 98 *
AjK 2:d6a018232650 99 * Enable PWM channel 3.
AjK 2:d6a018232650 100 *
AjK 2:d6a018232650 101 * @param PinName p24(P2_2) or LED3(P1_21)
AjK 2:d6a018232650 102 */
AjK 2:d6a018232650 103 void enable3(PinName pin = p24);
AjK 2:d6a018232650 104
AjK 2:d6a018232650 105 /** enable4
AjK 2:d6a018232650 106 *
AjK 2:d6a018232650 107 * Enable PWM channel 4.
AjK 2:d6a018232650 108 *
AjK 2:d6a018232650 109 * @param PinName p23(P2_3) or LED4(P1_23)
AjK 2:d6a018232650 110 */
AjK 2:d6a018232650 111 void enable4(PinName pin = p23);
AjK 2:d6a018232650 112
AjK 2:d6a018232650 113 /** enable5
AjK 2:d6a018232650 114 *
AjK 2:d6a018232650 115 * Enable PWM channel 5.
AjK 2:d6a018232650 116 *
AjK 2:d6a018232650 117 * @param PinName p22(P2_4) or P1_24
AjK 2:d6a018232650 118 */
AjK 2:d6a018232650 119 void enable5(PinName pin = p22);
AjK 2:d6a018232650 120
AjK 2:d6a018232650 121 /** enable6
AjK 2:d6a018232650 122 *
AjK 2:d6a018232650 123 * Enable PWM channel 6.
AjK 2:d6a018232650 124 *
AjK 2:d6a018232650 125 * @param PinName p21(P2_5) or P1_26
AjK 2:d6a018232650 126 */
AjK 2:d6a018232650 127 void enable6(PinName pin = p21);
AjK 2:d6a018232650 128
AjK 2:d6a018232650 129 /** enable
AjK 2:d6a018232650 130 *
AjK 2:d6a018232650 131 * Enable the specified channel. The default pin on port 2 is assumed.
AjK 2:d6a018232650 132 *
AjK 2:d6a018232650 133 * @param Servo The channel to enable, Servo1 to Servo6
AjK 2:d6a018232650 134 */
AjK 2:d6a018232650 135 void enable(Servo ch);
AjK 2:d6a018232650 136
AjK 2:d6a018232650 137 /** setLimitMin
AjK 2:d6a018232650 138 *
AjK 2:d6a018232650 139 * Set the minimum logical limit for the specified channel.
AjK 2:d6a018232650 140 *
AjK 2:d6a018232650 141 * @param Servo channel
AjK 2:d6a018232650 142 * @param double The lower logical limit.
AjK 2:d6a018232650 143 */
AjK 2:d6a018232650 144 void setLimitMin(Servo ch, double d) { _limitMin[ch] = d; }
AjK 2:d6a018232650 145
AjK 2:d6a018232650 146 /** getLimitMin
AjK 2:d6a018232650 147 *
AjK 2:d6a018232650 148 * Get the minimum logical limit for the specified channel.
AjK 2:d6a018232650 149 *
AjK 2:d6a018232650 150 * @param Servo channel
AjK 2:d6a018232650 151 * @return double The lower logical limit.
AjK 2:d6a018232650 152 */
AjK 2:d6a018232650 153 double getlimitMin(Servo ch) { return _limitMin[ch]; }
AjK 2:d6a018232650 154
AjK 2:d6a018232650 155 /** setLimitMax
AjK 2:d6a018232650 156 *
AjK 2:d6a018232650 157 * Set the maximum logical limit for the specified channel.
AjK 2:d6a018232650 158 *
AjK 2:d6a018232650 159 * @param Servo channel
AjK 2:d6a018232650 160 * @param double The upper logical limit.
AjK 2:d6a018232650 161 */
AjK 2:d6a018232650 162 void setLimitMax(Servo ch, double d) { _limitMax[ch] = d; }
AjK 2:d6a018232650 163
AjK 2:d6a018232650 164 /** getLimitMax
AjK 2:d6a018232650 165 *
AjK 2:d6a018232650 166 * Get the maximum logical limit for the specified channel.
AjK 2:d6a018232650 167 *
AjK 2:d6a018232650 168 * @param Servo channel
AjK 2:d6a018232650 169 * @return double The upper logical limit.
AjK 2:d6a018232650 170 */
AjK 2:d6a018232650 171 double getLimitMax(Servo ch) { return _limitMax[ch]; }
AjK 2:d6a018232650 172
AjK 2:d6a018232650 173 /** setLimits
AjK 2:d6a018232650 174 *
AjK 2:d6a018232650 175 * Set the logical upper and lower limits for channel.
AjK 2:d6a018232650 176 *
AjK 2:d6a018232650 177 * @param Servo channel
AjK 2:d6a018232650 178 * @param double The minimum logical limit
AjK 2:d6a018232650 179 * @param double The maximum logical limit
AjK 2:d6a018232650 180 */
AjK 2:d6a018232650 181 void setLimits(Servo ch, double min, double max) {
AjK 2:d6a018232650 182 _limitMin[ch] = min;
AjK 2:d6a018232650 183 _limitMax[ch] = max;
AjK 2:d6a018232650 184 }
AjK 2:d6a018232650 185
AjK 2:d6a018232650 186 /** getRangeMin
AjK 2:d6a018232650 187 *
AjK 2:d6a018232650 188 * Set the minimum physical limit for the specified channel.
AjK 2:d6a018232650 189 *
AjK 2:d6a018232650 190 * @param Servo channel
AjK 2:d6a018232650 191 * @param double The lower phyiscal limit in microseconds
AjK 2:d6a018232650 192 */
AjK 2:d6a018232650 193 uint32_t getRangeMin(Servo ch, uint32_t u) { return _msMin[ch] / 24; }
AjK 2:d6a018232650 194
AjK 2:d6a018232650 195 /** getRangeMax
AjK 2:d6a018232650 196 *
AjK 2:d6a018232650 197 * Set the maximum physical limit for the specified channel.
AjK 2:d6a018232650 198 *
AjK 2:d6a018232650 199 * @param Servo channel
AjK 2:d6a018232650 200 * @param uint32 The upper phyiscal limit in microseconds
AjK 2:d6a018232650 201 */
AjK 2:d6a018232650 202 uint32_t getRangeMax(Servo ch, uint32_t u) { return (_msMax[ch] / 24) + _msMin[ch]; }
AjK 2:d6a018232650 203
AjK 2:d6a018232650 204 /** setRange
AjK 2:d6a018232650 205 *
AjK 2:d6a018232650 206 * Set the minimum and maximum physical limits for the specified channel.
AjK 2:d6a018232650 207 *
AjK 2:d6a018232650 208 * @param Servo channel
AjK 2:d6a018232650 209 * @param uint32 The lower phyiscal limit in microseconds
AjK 2:d6a018232650 210 * @param uint32 The upper phyiscal limit in microseconds
AjK 2:d6a018232650 211 */
AjK 2:d6a018232650 212 void setRange(Servo ch, uint32_t min, uint32_t max) {
AjK 2:d6a018232650 213 setRangeMin(ch, min);
AjK 2:d6a018232650 214 setRangeMax(ch, max);
AjK 2:d6a018232650 215 }
AjK 2:d6a018232650 216
AjK 2:d6a018232650 217 /** position
AjK 2:d6a018232650 218 *
AjK 2:d6a018232650 219 * Set the desired position of the servo.
AjK 2:d6a018232650 220 * This value should be between the lower and upper logical limits.
AjK 2:d6a018232650 221 *
AjK 2:d6a018232650 222 * Under normal circumstances this fuction returns the same position is
AjK 2:d6a018232650 223 * was supplied. However, if the supplied position is outside the logical
AjK 2:d6a018232650 224 * system limits we return the value we actually went to. This is almost
AjK 2:d6a018232650 225 * always the value of the logical limit that is set for that direction.
AjK 2:d6a018232650 226 *
AjK 2:d6a018232650 227 * @param Servo channel
AjK 2:d6a018232650 228 * @param double the logical position to move to.
AjK 2:d6a018232650 229 * @return double The actual calculated position moved to.
AjK 2:d6a018232650 230 */
AjK 2:d6a018232650 231 double position(Servo ch, double degrees);
AjK 2:d6a018232650 232
AjK 2:d6a018232650 233 /** neutral
AjK 2:d6a018232650 234 *
AjK 2:d6a018232650 235 * Tell the servo to move to it's neutral position (1.5ms pulse width)
AjK 2:d6a018232650 236 *
AjK 2:d6a018232650 237 * @param Servo channel
AjK 2:d6a018232650 238 */
AjK 2:d6a018232650 239 void neutral(Servo ch);
AjK 2:d6a018232650 240
AjK 2:d6a018232650 241 }; // class RCservo ends.
AjK 2:d6a018232650 242
AjK 2:d6a018232650 243 }; // namespace AjK ends.
AjK 2:d6a018232650 244
AjK 2:d6a018232650 245 using namespace AjK;
AjK 2:d6a018232650 246
AjK 2:d6a018232650 247 #endif /* AJK_SIMPLERCSERVOS_H */