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

Dependents:   Steppermotor

Revision:
0:7393c52297ee
Child:
1:1030a91cbf4c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/inc/SimpleSteppers.h	Mon May 02 10:02:18 2011 +0000
@@ -0,0 +1,262 @@
+/*
+    Copyright (c) 2011 Andy Kirkham
+ 
+    Permission is hereby granted, free of charge, to any person obtaining a copy
+    of this software and associated documentation files (the "Software"), to deal
+    in the Software without restriction, including without limitation the rights
+    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+    copies of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+ 
+    The above copyright notice and this permission notice shall be included in
+    all copies or substantial portions of the Software.
+ 
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+    THE SOFTWARE.
+*/
+
+#ifndef AJK_SIMPLESTEPPERS_H
+#define AJK_SIMPLESTEPPERS_H
+
+#define SIMPLESTEPPER_F 100000
+#include "LPC17xx.h"
+#include "core_cm3.h"
+#include <stdint.h>
+
+#ifndef __ARMCC_VERSION
+#include "SimpleStepperMbed.h"
+#else
+#include "mbed.h"
+#endif
+
+#include "SimpleStepperOutput.h"
+
+namespace AjK {
+
+// Forward reference the main controller.
+class SimpleStepperController;
+
+/** SimpleStepper
+ *
+ * SimpleStepper is a class designed to handle the pulse and direction
+ * signals for a stepper motor. A simple API is exposed to allow the
+ * setting of the pulse width and the number of pulses per second.
+ *
+ * Note, SimpleStepper uses the SimpleStepperController class to manage
+ * the TIMER2. SimpleStepperController and SimpleStepper take total
+ * control of the LPC17xx's TIMER2. Your application or other library that
+ * your application uses, should use TIMER2.
+ *
+ * @include example1.h
+ */
+class SimpleStepper {
+
+public:
+    enum MAT           { MAT2_0, MAT2_1, MAT2_2, MAT2_3 };
+    enum MATCH_OP      { NothingOnMatch, ClrOnMatch, SetOnMatch, ToggleOnMatch };
+    enum PULSE_STATE   { PulseIdle, PulseAssert, PulseDeassert };
+    enum STEPPER_STATE { Stopped, ConstantSpeed };
+        
+protected:    
+    SimpleStepperController *_simpleStepperController;    
+    SimpleStepperOutput *_direction;
+    
+    PinName     _pulse;
+    MAT         _pulseMAT;
+    uint32_t    _operShift;
+    uint32_t    _pMR;
+    uint32_t    _match_shift;
+    uint32_t    _EMmask;
+    uint32_t    _EMCshift;
+    int         _pulseLen;
+    int         _pulseSense;
+    int         _directionSense;
+    int         _commandSpeed;
+    int64_t     _pulseCounter;
+    int64_t     _pulseWrapPos;
+    int64_t     _pulseWrapNeg;    
+    uint32_t    _currentMatch;
+    
+    bool        _maintainPositionData;
+    
+    PULSE_STATE _pulseState;
+    
+    STEPPER_STATE _stepperState;
+
+    void init(void);
+    
+    void isr(uint32_t);
+    
+    void next_step(void);
+    
+public:
+    friend class SimpleStepperController;
+    
+    /** Constructor
+     * 
+     * PinName pulse can be p5, p6, p7 or p8
+     * SimpleStepperOutput *direction is a pointer to an output.
+     *
+     * @param PinName The output for the pulse output.
+     * @param SimpleStepperOutput *direction The output pin for direction control
+     */
+    SimpleStepper(PinName pulse, SimpleStepperOutput *direction = 0);
+    
+    /** Constructor
+     * 
+     * PinName pulse can be p5, p6, p7 or p8
+     * SimpleStepperOutput *direction is a pointer to an output.
+     *
+     * @param SimpleStepperController *con A pointer to a base controller.
+     * @param PinName The output for the pulse output.
+     * @param SimpleStepperOutput *direction The output pin for direction control
+     */
+    SimpleStepper(SimpleStepperController *con, PinName pulse, SimpleStepperOutput *direction);
+   
+    /** setPulseSense
+     *
+     * Set's the logic value that pulse asserted assumes. Default is 1.
+     *
+     * 1 means pulse goes from 0 to 1 and remains 1 for pulseLen time then goes to 0.
+     * 0 means pulse goes from 1 to 0 and remains 0 for pulseLen time then goes to 1.
+     *
+     * @param int What is the logic sense for the pulse output.
+     */
+    void setPulseSense(int i = 1) { _pulseSense = i; }
+    
+    /** setDirectionSense
+     *
+     * Set's the logic value that direction forward assumes. Default is 1.
+     *
+     * 1 means that the direction output is 1 for forward and 0 for reverse.
+     * 0 means that the direction output is 0 for forward and 1 for reverse.
+     *
+     * Additionally, for position:-
+     * 1 means forward pulses are counted upwards, reverse means counted downwards.
+     * 0 means forward pulses are counted downwards, reverse means counted upwards.
+     *
+     * @param int What is the logic sense for the direction output.
+     */
+    void setDirectionSense(int i = 1) { _directionSense = i; }
+    
+    /** setPulseLen
+     *
+     * Used to set the pulse length. Default pulse length is 50us.
+     * If no arg supplied returns the current pulse length.
+     * <b>Note,</b> the length is specified as 10us increments.
+     * The default is 5 which is 50us
+     * @param int pulse length
+     * @return int the value of the pulse length.
+     */
+    int setPulseLen(int i = 0) { if (i) _pulseLen = i; return _pulseLen; }
+    
+    /** setSpeed
+     * 
+     * Set the motor speed in pulses per second. Zero stops all motor pulses.
+     * 
+     * With the default pulseLen of 50us (5 timer "ticks") the maximum speed
+     * that can be set is 10000 pulses per second (pps) which will produce a square
+     * wave with 50% duty cycle. Pushing it beyond will give a square wave a duty 
+     * cycle shifts so that the off time between pulses becomes shorter than the on 
+     * pulse length.
+     *
+     * The pulseLen can be adjusted using setPulseLen() down even more to eek out 
+     * some extra bandwidth. However, you really should be checking both the datasheet
+     * for your stepper motor amplifier and stepper motor. Running a stepper motor at
+     * such high speed may have electrical and mechanical issues.
+     *
+     * The arg raw is used when you want to "sync" channels. Suppose for example you
+     * have the following code to set the speed to two front wheels:-
+     * @code
+     *      stepper0.setSpeed(100);
+     *      stepper1.setSpeed(100);
+     * @endcode
+     *
+     * The problem here is they will be a few "clock ticks" out from each other as the
+     * TIMER2 TC increments between the two calls. If you wanted to make two motors sync
+     * together you can pass in the raw value of TIMER2 TC to make both functions calculate
+     * the same stepp values and so sync together:-
+     * @code
+     *      uint32_t i = LPC_TIM2->TC; // Capture TC.
+     *      stepper0.setSpeed(100, i);
+     *      stepper1.setSpeed(100, i);
+     * @endcode     
+     *
+     * The above code forces setSpeed() to calculate both axis in sync with respect to 
+     * a common TC value.
+     *
+     * @param int steps_per_second Number of pulses per second required.     
+     */
+    void setSpeed(int steps_per_second = 0, uint32_t raw = 0); 
+    
+    /** setSpeed
+     * 
+     * Set the motor speed in pulses per second. Zero stops all motor pulses.
+     * @param double steps_per_second Number of pulses per second required.     
+     */
+    void setSpeed(double steps_per_second = 0, uint32_t raw = 0); 
+    
+    /** setInterval
+     * 
+     * Set the motor speed pulse interval. Zero stops all motor pulses.
+     * @param int interval 
+     */
+    void setInterval(int i = 0, uint32_t raw = 0); 
+    
+    /** getPosition
+     * 
+     * Get the current position (the pulse counter).
+     *
+     * @return int64_t The current position as maintained by the interrupts.
+     */
+    int64_t getPosition(void) { return _pulseCounter; }
+
+    /** setWrapPos
+     *     
+     * Set the value that we should wrap the pulse position counter.
+     * Zero (default) means no wrap occurs.
+     *
+     * @param int64_t The value to wrap to NEG at.
+     */
+    void setWrapPos(int64_t i = 0) { _pulseWrapPos = i; }
+    
+    /** setWrapNeg
+     *     
+     * Set the value that we should wrap the pulse position counter.
+     * Zero (default) means no wrap occurs.
+     *
+     * @param int64_t The value to wrap to POS at.
+     */
+    void setWrapNeg(int64_t i = 0) { _pulseWrapNeg = i; }
+    
+    /** setMaintainPositionData
+     *
+     * Setting this false removes the maintainence of positional data.
+     * This allows the interrupt service routine to not perform these
+     * steps (if not required) thus making the ISR run slightly fatser.
+     * You might want to do this if positional data isn't required.
+     */
+    void setMaintainPositionData(bool b) { _maintainPositionData = b; }
+    
+};
+
+class SimpleStepperController {
+protected:
+    SimpleStepper   *_stepper[4];
+
+public:
+    friend class SimpleStepper;
+    
+    SimpleStepperController();    
+    ~SimpleStepperController();    
+    void isr(void);
+};
+
+}; // namespace AjK ends
+
+#endif