Provides an API software interface to TIMER2 to control upto four stepper motors.
Revision 4:7b7940df7865, committed 2011-05-20
- Comitter:
- AjK
- Date:
- Fri May 20 09:13:31 2011 +0000
- Parent:
- 3:71ab7209adb3
- Commit message:
- 1.1 See ChangeLog.h
Changed in this revision
diff -r 71ab7209adb3 -r 7b7940df7865 inc/ChangeLog.h --- a/inc/ChangeLog.h Mon May 02 10:17:33 2011 +0000 +++ b/inc/ChangeLog.h Fri May 20 09:13:31 2011 +0000 @@ -3,7 +3,13 @@ SimpleSteppers change log history. ================================== +1.1 20/May/2011 + + * Added the SimpleStepperProfiler class to control start/stop accel profiles. + * Added example2.h to show how to use the profiler. + 1.0 2/May/2011 + * Initial release. */ \ No newline at end of file
diff -r 71ab7209adb3 -r 7b7940df7865 inc/SimpleStepperProfiler.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/inc/SimpleStepperProfiler.h Fri May 20 09:13:31 2011 +0000 @@ -0,0 +1,104 @@ +/* + 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_SIMPLESTEPERPROFILER_H +#define AJK_SIMPLESTEPERPROFILER_H + +#include "mbed.h" +#include "SimpleSteppers.h" + +namespace AjK { + +class SimpleStepperProfiler : public SimpleStepper { + +protected: + Ticker _poll; + int _desired_speed; + int _step_pos; + int _step_neg; + int _poll_interval; + + void poll(void) + { + if (_steps_per_second < _desired_speed) { + _steps_per_second += _step_pos; + if (_steps_per_second > _desired_speed) { + _steps_per_second = _desired_speed; + } + SimpleStepper::setSpeed(_steps_per_second); + } + if (_steps_per_second > _desired_speed) { + _steps_per_second -= _step_neg; + if (_steps_per_second < _desired_speed) { + _steps_per_second = _desired_speed; + } + SimpleStepper::setSpeed(_steps_per_second); + } + } + +public: + + friend class Ticker; + + SimpleStepperProfiler(PinName pulse, SimpleStepperOutput *direction = 0) : + SimpleStepper(pulse, direction) + { + _desired_speed = 0; + _step_pos = 10; + _step_neg = 10; + _poll_interval = 10000; // 10ms + _poll.attach_us(this, &SimpleStepperProfiler::poll, _poll_interval); + } + + int getStepPos(void) { return _step_pos; } + void setStepPos(int i) { _step_pos = i; } + + int getStepNeg(void) { return _step_neg; } + void setStepNeg(int i) { _step_neg = i; } + + int getPollInterval(void) { return _poll_interval; } + void setPollInterval(int i) + { + _poll_interval = i; + _poll.detach(); + _poll.attach_us(this, &SimpleStepperProfiler::poll, _poll_interval); + } + + void setSpeed(int steps_per_second = 0, uint32_t raw = 0) + { + _desired_speed = steps_per_second; + } + + void eStop(void) + { + _desired_speed = _steps_per_second = 0; + SimpleStepper::setSpeed(_steps_per_second); + } + + +}; + +}; // namespace AjK ends. + + +#endif
diff -r 71ab7209adb3 -r 7b7940df7865 inc/SimpleSteppers.h --- a/inc/SimpleSteppers.h Mon May 02 10:17:33 2011 +0000 +++ b/inc/SimpleSteppers.h Fri May 20 09:13:31 2011 +0000 @@ -134,6 +134,8 @@ int64_t _pulseWrapNeg; uint32_t _currentMatch; + volatile int _steps_per_second; + bool _maintainPositionData; PULSE_STATE _pulseState; @@ -253,6 +255,13 @@ */ void setSpeed(double steps_per_second = 0, uint32_t raw = 0); + /** getSpeed + * + * Get the demanded motor speed in pulses per second. Zero stops all motor pulses. + * @return int steps_per_second Number of pulses per second demanded. + */ + int getSpeed(void) { return _steps_per_second; } + /** setInterval * * Set the motor speed pulse interval. Zero stops all motor pulses.
diff -r 71ab7209adb3 -r 7b7940df7865 inc/example1.h --- a/inc/example1.h Mon May 02 10:17:33 2011 +0000 +++ b/inc/example1.h Fri May 20 09:13:31 2011 +0000 @@ -1,46 +1,46 @@ - -#include "mbed.h" -#include "SimpleSteppers.h" - -SimpleStepperOutput led1(LED1); - -// SimpleStepperOutput is basically the same as -// Mbed's DigitalOut class. However, it's more -// portable to other platforms without having -// to also port the entire Mbed library. -SimpleStepperOutput sdir0(p17); -SimpleStepperOutput sdir1(p18); -SimpleStepperOutput sdir2(p19); -SimpleStepperOutput sdir3(p20); - -// Create four steppers. -// Stepper0 has the pulse output on p8 and dir on p17 -SimpleStepper stepper0(p8, &sdir0); -// Stepper1 has the pulse output on p7 and dir on p18 -SimpleStepper stepper1(p7, &sdir1); -// Stepper2 has the pulse output on p7 and dir on p19 -SimpleStepper stepper2(p6, &sdir2); -// Stepper3 has the pulse output on p7 and dir on p20 -SimpleStepper stepper3(p5, &sdir3); - -int main() { - - // We do not need to maintain the stepper position - // for this simple example. This reduces the amount - // of work the ISR has to do. - stepper0.setMaintainPositionData(false); - stepper1.setMaintainPositionData(false); - stepper2.setMaintainPositionData(false); - stepper3.setMaintainPositionData(false); - - // Set all steppers to top speed of 5000 pulses/second. - stepper0.setSpeed(5000); - stepper1.setSpeed(5000); - stepper2.setSpeed(5000); - stepper3.setSpeed(5000); - - while(1) { - led1 = !led1; - wait(0.2); - } -} + +#include "mbed.h" +#include "SimpleSteppers.h" + +SimpleStepperOutput led1(LED1); + +// SimpleStepperOutput is basically the same as +// Mbed's DigitalOut class. However, it's more +// portable to other platforms without having +// to also port the entire Mbed library. +SimpleStepperOutput sdir0(p17); +SimpleStepperOutput sdir1(p18); +SimpleStepperOutput sdir2(p19); +SimpleStepperOutput sdir3(p20); + +// Create four steppers. +// Stepper0 has the pulse output on p8 and dir on p17 +SimpleStepper stepper0(p8, &sdir0); +// Stepper1 has the pulse output on p7 and dir on p18 +SimpleStepper stepper1(p7, &sdir1); +// Stepper2 has the pulse output on p7 and dir on p19 +SimpleStepper stepper2(p6, &sdir2); +// Stepper3 has the pulse output on p7 and dir on p20 +SimpleStepper stepper3(p5, &sdir3); + +int main() { + + // We do not need to maintain the stepper position + // for this simple example. This reduces the amount + // of work the ISR has to do. + stepper0.setMaintainPositionData(false); + stepper1.setMaintainPositionData(false); + stepper2.setMaintainPositionData(false); + stepper3.setMaintainPositionData(false); + + // Set all steppers to top speed of 5000 pulses/second. + stepper0.setSpeed(5000); + stepper1.setSpeed(5000); + stepper2.setSpeed(5000); + stepper3.setSpeed(5000); + + while(1) { + led1 = !led1; + wait(0.2); + } +}
diff -r 71ab7209adb3 -r 7b7940df7865 inc/example2.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/inc/example2.h Fri May 20 09:13:31 2011 +0000 @@ -0,0 +1,54 @@ + +#include "mbed.h" +#include "SimpleStepperProfiler.h" + +SimpleStepperOutput led1(LED1); + +// SimpleStepperOutput is basically the same as +// Mbed's DigitalOut class. However, it's more +// portable to other platforms without having +// to also port the entire Mbed library. +SimpleStepperOutput sdir0(p17); + +// Create four stepper profilers. +// Stepper0 has the pulse output on p8 and dir on p17 +SimpleStepperProfiler stepper0(p8, &sdir0); + +int main() { + + // We do not need to maintain the stepper position + // for this simple example. This reduces the amount + // of work the ISR has to do. + stepper0.setMaintainPositionData(false); + + // Set all steppers to top speed of 5000 pulses/second. + // Because we are using the SimpleStepperProfiler then + // the accel will be 1000pps/s, so to reach 5000pps will + // take 5seconds. + + // The accel profile can be adjusted by altering the profilers + // step value and poll interval. The default step value is 10 + // each poll interval and the default poll interval is 10ms. + // This equates to 100 * 10 = 1000pps/s. Adjust as required + // using :- + // setStepPos(int i); where i is the step value +/- each poll interval accel + // setStepNeg(int i); where i is the step value +/- each poll interval decel + // setPollInterval(int i) where i is the poll interval in microseconds. + + stepper0.setSpeed(5000); + while(stepper0.getSpeed() != 5000); // wait to reach speed. + + // Decel stepper to halt/stop. + stepper0.setSpeed(0); + while(stepper0.getSpeed() != 0); // wait to reach speed. + + // Set speed but peform async emergency stop while accelerating. + stepper0.setSpeed(5000); + wait(2.5); + stepper0.eStop(); + + while(1) { + led1 = !led1; + wait(0.2); + } +}
diff -r 71ab7209adb3 -r 7b7940df7865 src/SimpleSteppers.cpp --- a/src/SimpleSteppers.cpp Mon May 02 10:17:33 2011 +0000 +++ b/src/SimpleSteppers.cpp Fri May 20 09:13:31 2011 +0000 @@ -57,6 +57,8 @@ _maintainPositionData = true; + _steps_per_second = 0; + setPulseSense(1); setDirectionSense(1); @@ -194,12 +196,14 @@ if (steps_per_second == 0) { LPC_TIM2->EMR |= (NothingOnMatch << _EMCshift); LPC_TIM2->MCR &= ~(7UL << _match_shift); - if (_pulseSense) LPC_TIM2->EMR &= ~_EMmask; else LPC_TIM2->EMR |= _EMmask; + if (_pulseSense) LPC_TIM2->EMR |= _EMmask; else LPC_TIM2->EMR &= ~_EMmask; _stepperState = Stopped; _pulseState = PulseIdle; _commandSpeed = 0; + _steps_per_second = 0; } else { + _steps_per_second = steps_per_second; int n = steps_per_second; if (n < 0) n *= -1; if (_direction) {