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

Committer:
AjK
Date:
Mon May 02 18:38:45 2011 +0000
Revision:
0:c680385286e3
Child:
2:d6a018232650
1.0 See ChangeLog.h

Who changed what in which revision?

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