Provides an API software interface to TIMER2 to control upto four stepper motors.
Embed:
(wiki syntax)
Show/hide line numbers
SimpleSteppers.h
00001 /* 00002 Copyright (c) 2011 Andy Kirkham 00003 00004 Permission is hereby granted, free of charge, to any person obtaining a copy 00005 of this software and associated documentation files (the "Software"), to deal 00006 in the Software without restriction, including without limitation the rights 00007 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 00008 copies of the Software, and to permit persons to whom the Software is 00009 furnished to do so, subject to the following conditions: 00010 00011 The above copyright notice and this permission notice shall be included in 00012 all copies or substantial portions of the Software. 00013 00014 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00015 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00016 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00017 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00018 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00019 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 00020 THE SOFTWARE. 00021 */ 00022 00023 #ifndef AJK_SIMPLESTEPPERS_H 00024 #define AJK_SIMPLESTEPPERS_H 00025 00026 #define SIMPLESTEPPER_F 100000 00027 #include "LPC17xx.h" 00028 #include "core_cm3.h" 00029 #include <stdint.h> 00030 00031 #ifndef __ARMCC_VERSION 00032 #include "SimpleStepperMbed.h" 00033 #else 00034 #include "mbed.h" 00035 #endif 00036 00037 #include "SimpleStepperOutput.h" 00038 00039 namespace AjK { 00040 00041 // Forward reference the main controller. 00042 class SimpleStepperController; 00043 00044 /** SimpleStepper 00045 * 00046 * SimpleStepper is a class designed to handle the pulse and direction 00047 * signals for a stepper motor. A simple API is exposed to allow the 00048 * setting of the pulse width and the number of pulses per second. 00049 * 00050 * Note, SimpleStepper uses the SimpleStepperController class to manage 00051 * the TIMER2. SimpleStepperController and SimpleStepper take total 00052 * control of the LPC17xx's TIMER2. Your application or other library that 00053 * your application uses, should <b>not</b>use TIMER2. 00054 * 00055 * This library is a software interface to the TIMER2 MATCH system. It does 00056 * <b>not</b> provide position and/or acceleration, PID control, etc, of 00057 * the motors. Your application or other library should provide the control 00058 * function needed to position/run your stepper motor(s). 00059 * 00060 * @code 00061 * #include "mbed.h" 00062 * #include "SimpleSteppers.h" 00063 * 00064 * SimpleStepperOutput led1(LED1); 00065 * 00066 * // SimpleStepperOutput is basically the same as 00067 * // Mbed's DigitalOut class. However, it's more 00068 * // portable to other platforms without having 00069 * // to also port the entire Mbed library. 00070 * SimpleStepperOutput sdir0(p17); 00071 * SimpleStepperOutput sdir1(p18); 00072 * SimpleStepperOutput sdir2(p19); 00073 * SimpleStepperOutput sdir3(p20); 00074 * 00075 * // Create four steppers. 00076 * // Stepper0 has the pulse output on p8 and dir on p17 00077 * SimpleStepper stepper0(p8, &sdir0); 00078 * // Stepper1 has the pulse output on p7 and dir on p18 00079 * SimpleStepper stepper1(p7, &sdir1); 00080 * // Stepper2 has the pulse output on p7 and dir on p19 00081 * SimpleStepper stepper2(p6, &sdir2); 00082 * // Stepper3 has the pulse output on p7 and dir on p20 00083 * SimpleStepper stepper3(p5, &sdir3); 00084 * 00085 * int main() { 00086 * 00087 * // We do not need to maintain the stepper position 00088 * // for this simple example. This reduces the amount 00089 * // of work the ISR has to do. 00090 * stepper0.setMaintainPositionData(false); 00091 * stepper1.setMaintainPositionData(false); 00092 * stepper2.setMaintainPositionData(false); 00093 * stepper3.setMaintainPositionData(false); 00094 * 00095 * // Set all steppers to top speed of 5000 pulses/second. 00096 * stepper0.setSpeed(5000); 00097 * stepper1.setSpeed(5000); 00098 * stepper2.setSpeed(5000); 00099 * stepper3.setSpeed(5000); 00100 * 00101 * while(1) { 00102 * led1 = !led1; 00103 * wait(0.2); 00104 * } 00105 * } 00106 * @endcode 00107 * @see example1.h 00108 */ 00109 class SimpleStepper { 00110 00111 public: 00112 enum MAT { MAT2_0, MAT2_1, MAT2_2, MAT2_3 }; 00113 enum MATCH_OP { NothingOnMatch, ClrOnMatch, SetOnMatch, ToggleOnMatch }; 00114 enum PULSE_STATE { PulseIdle, PulseAssert, PulseDeassert }; 00115 enum STEPPER_STATE { Stopped, ConstantSpeed }; 00116 00117 protected: 00118 SimpleStepperController *_simpleStepperController; 00119 SimpleStepperOutput *_direction; 00120 00121 PinName _pulse; 00122 MAT _pulseMAT; 00123 uint32_t _operShift; 00124 uint32_t _pMR; 00125 uint32_t _match_shift; 00126 uint32_t _EMmask; 00127 uint32_t _EMCshift; 00128 int _pulseLen; 00129 int _pulseSense; 00130 int _directionSense; 00131 int _commandSpeed; 00132 int64_t _pulseCounter; 00133 int64_t _pulseWrapPos; 00134 int64_t _pulseWrapNeg; 00135 uint32_t _currentMatch; 00136 00137 volatile int _steps_per_second; 00138 00139 bool _maintainPositionData; 00140 00141 PULSE_STATE _pulseState; 00142 00143 STEPPER_STATE _stepperState; 00144 00145 void init(void); 00146 00147 void isr(uint32_t); 00148 00149 void next_step(void); 00150 00151 public: 00152 friend class SimpleStepperController; 00153 00154 /** Constructor 00155 * 00156 * PinName pulse can be p5, p6, p7 or p8 00157 * SimpleStepperOutput *direction is a pointer to an output. 00158 * 00159 * @param PinName The output for the pulse output. 00160 * @param SimpleStepperOutput *direction The output pin for direction control 00161 */ 00162 SimpleStepper(PinName pulse, SimpleStepperOutput *direction = 0); 00163 00164 /** Constructor 00165 * 00166 * PinName pulse can be p5, p6, p7 or p8 00167 * SimpleStepperOutput *direction is a pointer to an output. 00168 * 00169 * @param SimpleStepperController *con A pointer to a base controller. 00170 * @param PinName The output for the pulse output. 00171 * @param SimpleStepperOutput *direction The output pin for direction control 00172 */ 00173 SimpleStepper(SimpleStepperController *con, PinName pulse, SimpleStepperOutput *direction); 00174 00175 /** setPulseSense 00176 * 00177 * Set's the logic value that pulse asserted assumes. Default is 1. 00178 * 00179 * 1 means pulse goes from 0 to 1 and remains 1 for pulseLen time then goes to 0. 00180 * 0 means pulse goes from 1 to 0 and remains 0 for pulseLen time then goes to 1. 00181 * 00182 * @param int What is the logic sense for the pulse output. 00183 */ 00184 void setPulseSense(int i = 1) { _pulseSense = i; } 00185 00186 /** setDirectionSense 00187 * 00188 * Set's the logic value that direction forward assumes. Default is 1. 00189 * 00190 * 1 means that the direction output is 1 for forward and 0 for reverse. 00191 * 0 means that the direction output is 0 for forward and 1 for reverse. 00192 * 00193 * Additionally, for position:- 00194 * 1 means forward pulses are counted upwards, reverse means counted downwards. 00195 * 0 means forward pulses are counted downwards, reverse means counted upwards. 00196 * 00197 * @param int What is the logic sense for the direction output. 00198 */ 00199 void setDirectionSense(int i = 1) { _directionSense = i; } 00200 00201 /** setPulseLen 00202 * 00203 * Used to set the pulse length. Default pulse length is 50us. 00204 * If no arg supplied returns the current pulse length. 00205 * <b>Note,</b> the length is specified as 10us increments. 00206 * The default is 5 which is 50us 00207 * @param int pulse length 00208 * @return int the value of the pulse length. 00209 */ 00210 int setPulseLen(int i = 0) { if (i) _pulseLen = i; return _pulseLen; } 00211 00212 /** setSpeed 00213 * 00214 * Set the motor speed in pulses per second. Zero stops all motor pulses. 00215 * 00216 * With the default pulseLen of 50us (5 timer "ticks") the maximum speed 00217 * that can be set is 10000 pulses per second (pps) which will produce a square 00218 * wave with 50% duty cycle. Pushing it beyond will give a square wave a duty 00219 * cycle shifts so that the off time between pulses becomes shorter than the on 00220 * pulse length. 00221 * 00222 * The pulseLen can be adjusted using setPulseLen() down even more to eek out 00223 * some extra bandwidth. However, you really should be checking both the datasheet 00224 * for your stepper motor amplifier and stepper motor. Running a stepper motor at 00225 * such high speed may have electrical and mechanical issues. 00226 * 00227 * The arg raw is used when you want to "sync" channels. Suppose for example you 00228 * have the following code to set the speed to two front wheels:- 00229 * @code 00230 * stepper0.setSpeed(100); 00231 * stepper1.setSpeed(100); 00232 * @endcode 00233 * 00234 * The problem here is they will be a few "clock ticks" out from each other as the 00235 * TIMER2 TC increments between the two calls. If you wanted to make two motors sync 00236 * together you can pass in the raw value of TIMER2 TC to make both functions calculate 00237 * the same stepp values and so sync together:- 00238 * @code 00239 * uint32_t i = LPC_TIM2->TC; // Capture TC. 00240 * stepper0.setSpeed(100, i); 00241 * stepper1.setSpeed(100, i); 00242 * @endcode 00243 * 00244 * The above code forces setSpeed() to calculate both axis in sync with respect to 00245 * a common TC value. 00246 * 00247 * @param int steps_per_second Number of pulses per second required. 00248 */ 00249 void setSpeed(int steps_per_second = 0, uint32_t raw = 0); 00250 00251 /** setSpeed 00252 * 00253 * Set the motor speed in pulses per second. Zero stops all motor pulses. 00254 * @param double steps_per_second Number of pulses per second required. 00255 */ 00256 void setSpeed(double steps_per_second = 0, uint32_t raw = 0); 00257 00258 /** getSpeed 00259 * 00260 * Get the demanded motor speed in pulses per second. Zero stops all motor pulses. 00261 * @return int steps_per_second Number of pulses per second demanded. 00262 */ 00263 int getSpeed(void) { return _steps_per_second; } 00264 00265 /** setInterval 00266 * 00267 * Set the motor speed pulse interval. Zero stops all motor pulses. 00268 * @param int interval 00269 */ 00270 void setInterval(int i = 0, uint32_t raw = 0); 00271 00272 /** getPosition 00273 * 00274 * Get the current position (the pulse counter). 00275 * 00276 * @return int64_t The current position as maintained by the interrupts. 00277 */ 00278 int64_t getPosition(void) { return _pulseCounter; } 00279 00280 /** setWrapPos 00281 * 00282 * Set the value that we should wrap the pulse position counter. 00283 * Zero (default) means no wrap occurs. 00284 * 00285 * @param int64_t The value to wrap to NEG at. 00286 */ 00287 void setWrapPos(int64_t i = 0) { _pulseWrapPos = i; } 00288 00289 /** setWrapNeg 00290 * 00291 * Set the value that we should wrap the pulse position counter. 00292 * Zero (default) means no wrap occurs. 00293 * 00294 * @param int64_t The value to wrap to POS at. 00295 */ 00296 void setWrapNeg(int64_t i = 0) { _pulseWrapNeg = i; } 00297 00298 /** setMaintainPositionData 00299 * 00300 * Setting this false removes the maintainence of positional data. 00301 * This allows the interrupt service routine to not perform these 00302 * steps (if not required) thus making the ISR run slightly fatser. 00303 * You might want to do this if positional data isn't required. 00304 */ 00305 void setMaintainPositionData(bool b) { _maintainPositionData = b; } 00306 00307 }; 00308 00309 class SimpleStepperController { 00310 protected: 00311 SimpleStepper *_stepper[4]; 00312 00313 public: 00314 friend class SimpleStepper; 00315 00316 SimpleStepperController(); 00317 ~SimpleStepperController(); 00318 void isr(void); 00319 }; 00320 00321 }; // namespace AjK ends 00322 00323 #endif
Generated on Thu Jul 14 2022 17:06:02 by 1.7.2