Provides an API software interface to TIMER2 to control upto four stepper motors.

Dependents:   Steppermotor

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers SimpleSteppers.h Source File

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