Slightly altered version of Arduino OneStep
This library is specific to the ST L6474 stepper driver.
Revision 0:92e1b5622620, committed 2015-09-02
- Comitter:
- jonebuckman
- Date:
- Wed Sep 02 15:43:40 2015 +0000
- Commit message:
- Slightly altered version of Arduino OneStep
Changed in this revision
OneStep.cpp | Show annotated file Show diff for this revision Revisions of this file |
OneStep.h | Show annotated file Show diff for this revision Revisions of this file |
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OneStep.cpp Wed Sep 02 15:43:40 2015 +0000 @@ -0,0 +1,458 @@ +/** + * @file OneStep.cpp + * + * @author Jon Buckman + * + * @section LICENSE + * + * Copyright (c) 2014 Jon Buckman + * + * Copyright (C) 2009-2013 Mike McCauley + * $Id: AccelStepper.cpp,v 1.19 2014/10/31 06:05:27 mikem Exp mikem $ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @section DESCRIPTION + * + * OneStep stepper motor accelerate and manipulate. + * + * Datasheet: + * + * + */ + +/** + * Includes + */ +#include "OneStep.h" + +/** + * Methods + */ +OneStep::OneStep(PinName mosi, + PinName miso, + PinName sck, + PinName csn, + PinName step, + PinName dir, + PinName reset, + PinName flag) : spi_(mosi, miso, sck), nCS_(csn), step_(step), dir_(dir), reset_(reset), flag_(flag) // step, direction, reset, flag +{ + //5MHz, see page 13 of datasheet for max clock. May need to be reduces if using long wires + spi_.frequency(5000000); + spi_.format(8,3); + + nCS_ = 1; + + wait_us(500); + + _currentPos = 0; + _targetPos = 0; + _speed = 0.0; + _maxSpeed = 1.0; + _acceleration = 0.0; + _sqrt_twoa = 1.0; + _stepInterval = 0; + _minPulseWidth = 1; + _lastStepTime = 0; + + // NEW + _n = 0; + _c0 = 0.0; + _cn = 0.0; + _cmin = 1.0; + _direction = dir_ = DIRECTION_CCW; + reset_ = 0; + t_.start(); +} + +// No operation. +void OneStep::nop(void) { + wait_us(1); + nCS_ = 0; + spi_.write(0x00); + nCS_ = 1; +} + +// Enable driver. +void OneStep::enable(void) { + wait_us(1); + nCS_ = 0; + spi_.write(ENBL); + nCS_ = 1; +} + +// Disable driver. +void OneStep::disable(void) { + wait_us(1); + nCS_ = 0; + spi_.write(DSBL); + nCS_ = 1; +} + +// Set parameter value; +void OneStep::set_param(char parameter, int length, int value) { + char val[3]; + switch (length) { + case 1: + val[0] = (value & 0x0000ffUL) ; + break; + case 2: + val[0] = (value & 0x00ff00UL) >> 8; + val[1] = (value & 0x0000ffUL) ; + break; + case 3: + val[0] = (value & 0xff0000UL) >> 16; + val[1] = (value & 0x00ff00UL) >> 8; + val[2] = (value & 0x0000ffUL) ; + break; + } + wait_us(1); + nCS_ = 0; + spi_.write(parameter); + nCS_ = 1; + for (int i = 0; i < length; i++) { + wait_us(1); + nCS_ = 0; + spi_.write(val[i]); + nCS_ = 1; + } +} + +// Get parameter value. +int OneStep::get_param(char parameter, int length) { + char output = 0x20 | parameter; + char buf[3] = {0, 0, 0}; + wait_us(1); + nCS_ = 0; + spi_.write(output); + nCS_ = 1; + for (int i = 0; i < length; i++) { + wait_us(1); + nCS_ = 0; + buf[i] = spi_.write(0x00); + nCS_ = 1; + } + switch (length) { + case 1: + return buf[0]; + case 2: + return buf[0] << 8 | buf[1]; + case 3: + return buf[0] << 16 | buf[1] << 8 | buf[2]; + } + return 0; +} + +// Get status. +int OneStep::get_status() { + int ret_bytes[2]; + wait_us(1); + nCS_ = 0; + spi_.write(0xD0); //write request for status return + nCS_ = 1; + wait_us(1); + nCS_ = 0; + ret_bytes[0] = spi_.write(0x00); //read first byte + nCS_ = 1; + wait_us(1); + nCS_ = 0; + ret_bytes[1] = spi_.write(0x00); //read second byte + nCS_ = 1; + return ret_bytes[0] << 8 | ret_bytes[1]; //return i16 response +} + +void OneStep::moveTo(long absolute) +{ + if (_targetPos != absolute) + { + _targetPos = absolute; + computeNewSpeed(); + } +} + +void OneStep::move(long relative) +{ + moveTo(_currentPos + relative); +} + +// Implements steps according to the current step interval. +// You must call this at least once per step +// returns true if a step occurred. +bool OneStep::runSpeed() +{ + // Dont do anything unless we actually have a step interval + if (!_stepInterval) + return false; + + unsigned long time = t_.read_us(); + // Gymnastics to detect wrapping of either the nextStepTime and/or the current time + unsigned long nextStepTime = _lastStepTime + _stepInterval; + if ( ((nextStepTime >= _lastStepTime) && ((time >= nextStepTime) || (time < _lastStepTime))) + || ((nextStepTime < _lastStepTime) && ((time >= nextStepTime) && (time < _lastStepTime)))) + + { + if (_direction == DIRECTION_CW) + { + // Clockwise + _currentPos += 1; + } + else + { + // Anticlockwise + _currentPos -= 1; + } + step(); + + _lastStepTime = time; + return true; + } + else + { + return false; + } +} + +long OneStep::distanceToGo() +{ + return _targetPos - _currentPos; +} + +long OneStep::targetPosition() +{ + return _targetPos; +} + +long OneStep::currentPosition() +{ + return _currentPos; +} + +// Useful during initialisations or after initial positioning +// Sets speed to 0 +void OneStep::setCurrentPosition(long position) +{ + _targetPos = _currentPos = position; + _n = 0; + _stepInterval = 0; +} + +void OneStep::computeNewSpeed() +{ + long distanceTo = distanceToGo(); // +ve is clockwise from curent location + + long stepsToStop = (long)((_speed * _speed) / (2.0f * _acceleration)); // Equation 16 + + if (distanceTo == 0 && stepsToStop <= 1) + { + // We are at the target and its time to stop + _stepInterval = 0; + _speed = 0.0; + _n = 0; + return; + } + + if (distanceTo > 0) + { + // We are anticlockwise from the target + // Need to go clockwise from here, maybe decelerate now + if (_n > 0) + { + // Currently accelerating, need to decel now? Or maybe going the wrong way? + if ((stepsToStop >= distanceTo) || _direction == DIRECTION_CCW) + _n = -stepsToStop; // Start deceleration + } + else if (_n < 0) + { + // Currently decelerating, need to accel again? + if ((stepsToStop < distanceTo) && _direction == DIRECTION_CW) + _n = -_n; // Start accceleration + } + } + else if (distanceTo < 0) + { + // We are clockwise from the target + // Need to go anticlockwise from here, maybe decelerate + if (_n > 0) + { + // Currently accelerating, need to decel now? Or maybe going the wrong way? + if ((stepsToStop >= -distanceTo) || _direction == DIRECTION_CW) + _n = -stepsToStop; // Start deceleration + } + else if (_n < 0) + { + // Currently decelerating, need to accel again? + if ((stepsToStop < -distanceTo) && _direction == DIRECTION_CCW) + _n = -_n; // Start accceleration + } + } + + // Need to accelerate or decelerate + if (_n == 0) + { + // First step from stopped + _cn = _c0; + _direction = dir_ = (distanceTo > 0) ? DIRECTION_CW : DIRECTION_CCW; + } + else + { + // Subsequent step. Works for accel (n is +_ve) and decel (n is -ve). + _cn = _cn - ((2.0f * _cn) / ((4.0f * _n) + 1)); // Equation 13 + _cn = max(_cn, _cmin); + } + _n++; + _stepInterval = _cn; + _speed = 1000000.0f / _cn; + if (_direction == DIRECTION_CCW) + _speed = -_speed; +} + +// Run the motor to implement speed and acceleration in order to proceed to the target position +// You must call this at least once per step, preferably in your main loop +// If the motor is in the desired position, the cost is very small +// returns true if the motor is still running to the target position. +bool OneStep::run() +{ + if (runSpeed()) + computeNewSpeed(); + return _speed != 0.0f || distanceToGo() != 0; +} + +// Step once. +void OneStep::step() +{ + step_ = 1; + wait_us(5); + step_ = 0; +} + +// Set the max speed. +void OneStep::setMaxSpeed(float speed) +{ + if (_maxSpeed != speed) + { + _maxSpeed = speed; + _cmin = 1000000.0f / speed; + // Recompute _n from current speed and adjust speed if accelerating or cruising + if (_n > 0) + { + _n = (long)((_speed * _speed) / (2.0f * _acceleration)); // Equation 16 + computeNewSpeed(); + } + } +} + +// Set the acceleration. +void OneStep::setAcceleration(float acceleration) +{ + if (acceleration == 0.0f) + return; + if (_acceleration != acceleration) + { + // Recompute _n per Equation 17 + _n = _n * (_acceleration / acceleration); + // New c0 per Equation 7 + //_c0 = sqrt(2.0 / acceleration) * 1000000.0; // Accelerates at half the expected rate. Why? + _c0 = sqrt(1.0f/acceleration) * 1000000.0f; + _acceleration = acceleration; + computeNewSpeed(); + } +} + +// Set the speed. +void OneStep::setSpeed(float speed) +{ + if (speed == _speed) + return; + speed = constrain(speed, -_maxSpeed, _maxSpeed); + if (speed == 0.0f) + _stepInterval = 0; + else + { + _stepInterval = fabs(1000000.0f / speed); + _direction = dir_ = (speed > 0.0f) ? DIRECTION_CW : DIRECTION_CCW; + } + _speed = speed; +} + +// Get current speed. +float OneStep::speed() +{ + return _speed; +} + +// Set the minimum pulse width. +void OneStep::setMinPulseWidth(unsigned int minWidth) +{ + _minPulseWidth = minWidth; +} + +// System reset enable. +void OneStep::enableReset() +{ + reset_ = 0; +} + +// System reset disable. +void OneStep::disableReset() +{ + reset_ = 1; +} + +// Blocks until the target position is reached and stopped. +void OneStep::runToPosition() +{ + while (run()) + ; +} + +// Run at speed to a position. +bool OneStep::runSpeedToPosition() +{ + if (_targetPos == _currentPos) + return false; + if (_targetPos >_currentPos) + _direction = dir_ = DIRECTION_CW; + else + _direction = dir_ = DIRECTION_CCW; + return runSpeed(); +} + +// Blocks until the new target position is reached. +void OneStep::runToNewPosition(long position) +{ + moveTo(position); + runToPosition(); +} + +void OneStep::stop() +{ + if (_speed != 0.0f) + { + long stepsToStop = (long)((_speed * _speed) / (2.0f * _acceleration)) + 1; // Equation 16 (+integer rounding) + if (_speed > 0) + move(stepsToStop); + else + move(-stepsToStop); + } +} + +// Get the alarm flag state. +int OneStep::getAlarm() +{ + return(flag_); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OneStep.h Wed Sep 02 15:43:40 2015 +0000 @@ -0,0 +1,801 @@ +/** + * @file OneStep.h + * + * @author Jon Buckman + * + * @section LICENSE + * + * Copyright (c) 2014 Jon Buckman + * + * Copyright (C) 2009-2013 Mike McCauley + * $Id: AccelStepper.cpp,v 1.19 2014/10/31 06:05:27 mikem Exp mikem $ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @section DESCRIPTION + * + * OneStep stepper motor accelerate and manipulate. + * + * Datasheet: + * + * + * + * Example: + * @code + * #include "mbed.h" + * #include "OneStep.h" + * + * Serial pc(USBTX, USBRX); // tx, rx + * + * OneStep stepper(D11, D12, D13, D10, D9, D7, D8, D2); // mosi, miso, sck, nCS_(cs), step, direction, reset, flag + * + * int main() { + * while(1) + * { + * if (stepper.distanceToGo() == 0) + * { + * // Random change to speed, position and acceleration + * // Make sure we dont get 0 speed or accelerations + * wait_us(1000); + * stepper.moveTo(rand() % 200); + * stepper.setMaxSpeed((rand() % 200) + 1); + * stepper.setAcceleration((rand() % 200) + 1); + * if(stepper.getAlarm() == 0) { + * pc.printf("alarm\r\n"); + * } + * } + * stepper.run(); + * } + * } + * @endcode + */ + +#ifndef ONESTEP_H +#define ONESTEP_H + +/** + * Includes + */ +#include <mbed.h> + +/** + * Defines + */ +#define min(a,b) ((a)<(b)?(a):(b)) +#define max(a,b) ((a)>(b)?(a):(b)) +#define abs(x) ((x)>0?(x):-(x)) +#define constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt))) +#define round(x) ((x)>=0?(long)((x)+0.5):(long)((x)-0.5)) +#define radians(deg) ((deg)*DEG_TO_RAD) +#define degrees(rad) ((rad)*RAD_TO_DEG) +#define sq(x) ((x)*(x)) + +/** + * @brief easySPIN Init structure definition + */ +typedef struct { + uint32_t ABS_POS; + uint16_t EL_POS; + uint32_t MARK; + uint8_t TVAL; + uint8_t T_FAST; + uint8_t TON_MIN; + uint8_t TOFF_MIN; + uint8_t ADC_OUT; + uint8_t OCD_TH; + uint8_t STEP_MODE; + uint8_t ALARM_EN; + uint16_t CONFIG; +} RegsStruct_TypeDef; + +/* easySPIN TVAL register options */ +typedef enum { + TVAL_31_25mA = ((uint8_t) 0x00), + TVAL_62_5mA = ((uint8_t) 0x01), + TVAL_93_75mA = ((uint8_t) 0x02), + TVAL_125mA = ((uint8_t) 0x03), + TVAL_156_25mA = ((uint8_t) 0x04), + TVAL_187_5mA = ((uint8_t) 0x05), + TVAL_218_75mA = ((uint8_t) 0x06), + TVAL_250mA = ((uint8_t) 0x07), + TVAL_281_25mA = ((uint8_t) 0x08), + TVAL_312_5mA = ((uint8_t) 0x09), + TVAL_343_75mA = ((uint8_t) 0x0A), + TVAL_375mA = ((uint8_t) 0x0B), + TVAL_406_25mA = ((uint8_t) 0x0C), + TVAL_437_5mA = ((uint8_t) 0x0D), + TVAL_468_75mA = ((uint8_t) 0x0E), + TVAL_500mA = ((uint8_t) 0x0F), + TVAL_531_25mA = ((uint8_t) 0x10), + TVAL_562_5mA = ((uint8_t) 0x11), + TVAL_593_75mA = ((uint8_t) 0x12), + TVAL_625mA = ((uint8_t) 0x13), + TVAL_656_25mA = ((uint8_t) 0x14), + TVAL_687_5mA = ((uint8_t) 0x15), + TVAL_718_75mA = ((uint8_t) 0x16), + TVAL_750mA = ((uint8_t) 0x17), + TVAL_781_25mA = ((uint8_t) 0x18), + TVAL_812_5mA = ((uint8_t) 0x19), + TVAL_843_75mA = ((uint8_t) 0x1A), + TVAL_875mA = ((uint8_t) 0x1B), + TVAL_906_25mA = ((uint8_t) 0x1C), + TVAL_937_5mA = ((uint8_t) 0x1D), + TVAL_968_75mA = ((uint8_t) 0x1E), + TVAL_1000mA = ((uint8_t) 0x1F), + TVAL_1031_25mA = ((uint8_t) 0x20), + TVAL_1062_5mA = ((uint8_t) 0x21), + TVAL_1093_75mA = ((uint8_t) 0x22), + TVAL_1125mA = ((uint8_t) 0x23), + TVAL_1156_25mA = ((uint8_t) 0x24), + TVAL_1187_5mA = ((uint8_t) 0x25), + TVAL_1218_75mA = ((uint8_t) 0x26), + TVAL_1250mA = ((uint8_t) 0x27), + TVAL_1281_25mA = ((uint8_t) 0x28), + TVAL_1312_5mA = ((uint8_t) 0x29), + TVAL_1343_75mA = ((uint8_t) 0x2A), + TVAL_1375mA = ((uint8_t) 0x2B), + TVAL_1406_25mA = ((uint8_t) 0x2C), + TVAL_1437_5mA = ((uint8_t) 0x2D), + TVAL_1468_75mA = ((uint8_t) 0x2E), + TVAL_1500mA = ((uint8_t) 0x2F), + TVAL_1531_25mA = ((uint8_t) 0x30), + TVAL_1562_5mA = ((uint8_t) 0x31), + TVAL_1593_75mA = ((uint8_t) 0x32), + TVAL_1625mA = ((uint8_t) 0x33), + TVAL_1656_25mA = ((uint8_t) 0x34), + TVAL_1687_5mA = ((uint8_t) 0x35), + TVAL_1718_75mA = ((uint8_t) 0x36), + TVAL_1750mA = ((uint8_t) 0x37), + TVAL_1781_25mA = ((uint8_t) 0x38), + TVAL_1812_5mA = ((uint8_t) 0x39), + TVAL_1843_75mA = ((uint8_t) 0x3A), + TVAL_1875mA = ((uint8_t) 0x3B), + TVAL_1906_25mA = ((uint8_t) 0x3C), + TVAL_1937_5mA = ((uint8_t) 0x3D), + TVAL_1968_75mA = ((uint8_t) 0x3E), + TVAL_2000mA = ((uint8_t) 0x3F), + TVAL_2031_25mA = ((uint8_t) 0x40), + TVAL_2062_5mA = ((uint8_t) 0x41), + TVAL_2093_75mA = ((uint8_t) 0x42), + TVAL_2125mA = ((uint8_t) 0x43), + TVAL_2156_25mA = ((uint8_t) 0x44), + TVAL_2187_5mA = ((uint8_t) 0x45), + TVAL_2218_75mA = ((uint8_t) 0x46), + TVAL_2250mA = ((uint8_t) 0x47), + TVAL_2281_25mA = ((uint8_t) 0x48), + TVAL_2312_5mA = ((uint8_t) 0x49), + TVAL_2343_75mA = ((uint8_t) 0x4A), + TVAL_2375mA = ((uint8_t) 0x4B), + TVAL_2406_25mA = ((uint8_t) 0x4C), + TVAL_2437_5mA = ((uint8_t) 0x4D), + TVAL_2468_75mA = ((uint8_t) 0x4E), + TVAL_2500mA = ((uint8_t) 0x4F), + TVAL_2531_25mA = ((uint8_t) 0x50), + TVAL_2562_5mA = ((uint8_t) 0x51), + TVAL_2593_75mA = ((uint8_t) 0x52), + TVAL_2625mA = ((uint8_t) 0x53), + TVAL_2656_25mA = ((uint8_t) 0x54), + TVAL_2687_5mA = ((uint8_t) 0x55), + TVAL_2718_75mA = ((uint8_t) 0x56), + TVAL_2750mA = ((uint8_t) 0x57), + TVAL_2781_25mA = ((uint8_t) 0x58), + TVAL_2812_5mA = ((uint8_t) 0x59), + TVAL_2843_75mA = ((uint8_t) 0x5A), + TVAL_2875mA = ((uint8_t) 0x5B), + TVAL_2906_25mA = ((uint8_t) 0x5C), + TVAL_2937_5mA = ((uint8_t) 0x5D), + TVAL_2968_75mA = ((uint8_t) 0x5E), + TVAL_3000mA = ((uint8_t) 0x5F), + TVAL_3031_25mA = ((uint8_t) 0x60), + TVAL_3062_5mA = ((uint8_t) 0x61), + TVAL_3093_75mA = ((uint8_t) 0x62), + TVAL_3125mA = ((uint8_t) 0x63), + TVAL_3156_25mA = ((uint8_t) 0x64), + TVAL_3187_5mA = ((uint8_t) 0x65), + TVAL_3218_75mA = ((uint8_t) 0x66), + TVAL_3250mA = ((uint8_t) 0x67), + TVAL_3281_25mA = ((uint8_t) 0x68), + TVAL_3312_5mA = ((uint8_t) 0x69), + TVAL_3343_75mA = ((uint8_t) 0x6A), + TVAL_3375mA = ((uint8_t) 0x6B), + TVAL_3406_25mA = ((uint8_t) 0x6C), + TVAL_3437_5mA = ((uint8_t) 0x6D), + TVAL_3468_75mA = ((uint8_t) 0x6E), + TVAL_3500mA = ((uint8_t) 0x6F), + TVAL_3531_25mA = ((uint8_t) 0x70), + TVAL_3562_5mA = ((uint8_t) 0x71), + TVAL_3593_75mA = ((uint8_t) 0x72), + TVAL_3625mA = ((uint8_t) 0x73), + TVAL_3656_25mA = ((uint8_t) 0x74), + TVAL_3687_5mA = ((uint8_t) 0x75), + TVAL_3718_75mA = ((uint8_t) 0x76), + TVAL_3750mA = ((uint8_t) 0x77), + TVAL_3781_25mA = ((uint8_t) 0x78), + TVAL_3812_5mA = ((uint8_t) 0x79), + TVAL_3843_75mA = ((uint8_t) 0x7A), + TVAL_3875mA = ((uint8_t) 0x7B), + TVAL_3906_25mA = ((uint8_t) 0x7C), + TVAL_3937_5mA = ((uint8_t) 0x7D), + TVAL_3968_75mA = ((uint8_t) 0x7E), + TVAL_4000mA = ((uint8_t) 0x7F) +} TVAL_TypeDef; + +/* easySPIN T_FAST register options */ +typedef enum { + TOFF_FAST_0_5_us = ((uint8_t) 0x00 << 4), + TOFF_FAST_1_0_us = ((uint8_t) 0x01 << 4), + TOFF_FAST_1_5_us = ((uint8_t) 0x02 << 4), + TOFF_FAST_2_0_us = ((uint8_t) 0x03 << 4), + TOFF_FAST_2_5_us = ((uint8_t) 0x04 << 4), + TOFF_FAST_3_0_us = ((uint8_t) 0x05 << 4), + TOFF_FAST_3_5_us = ((uint8_t) 0x06 << 4), + TOFF_FAST_4_0_us = ((uint8_t) 0x07 << 4), + TOFF_FAST_4_5_us = ((uint8_t) 0x08 << 4), + TOFF_FAST_5_0_us = ((uint8_t) 0x09 << 4), + TOFF_FAST_5_5_us = ((uint8_t) 0x0A << 4), + TOFF_FAST_6_0_us = ((uint8_t) 0x0B << 4), + TOFF_FAST_6_5_us = ((uint8_t) 0x0C << 4), + TOFF_FAST_7_0_us = ((uint8_t) 0x0D << 4), + TOFF_FAST_7_5_us = ((uint8_t) 0x0E << 4), + TOFF_FAST_8_0_us = ((uint8_t) 0x0F << 4) +} TOFF_FAST_TypeDef; + +typedef enum { + FAST_STEP_0_5_us = ((uint8_t) 0x00), + FAST_STEP_1_0_us = ((uint8_t) 0x01), + FAST_STEP_1_5_us = ((uint8_t) 0x02), + FAST_STEP_2_0_us = ((uint8_t) 0x03), + FAST_STEP_2_5_us = ((uint8_t) 0x04), + FAST_STEP_3_0_us = ((uint8_t) 0x05), + FAST_STEP_3_5_us = ((uint8_t) 0x06), + FAST_STEP_4_0_us = ((uint8_t) 0x07), + FAST_STEP_4_5_us = ((uint8_t) 0x08), + FAST_STEP_5_0_us = ((uint8_t) 0x09), + FAST_STEP_5_5_us = ((uint8_t) 0x0A), + FAST_STEP_6_0_us = ((uint8_t) 0x0B), + FAST_STEP_6_5_us = ((uint8_t) 0x0C), + FAST_STEP_7_0_us = ((uint8_t) 0x0D), + FAST_STEP_7_5_us = ((uint8_t) 0x0E), + FAST_STEP_8_0_us = ((uint8_t) 0x0F) +} FAST_STEP_TypeDef; + +/* easySPIN overcurrent threshold options */ +typedef enum { + OCD_TH_375mA = ((uint8_t) 0x00), + OCD_TH_750mA = ((uint8_t) 0x01), + OCD_TH_1125mA = ((uint8_t) 0x02), + OCD_TH_1500mA = ((uint8_t) 0x03), + OCD_TH_1875mA = ((uint8_t) 0x04), + OCD_TH_2250mA = ((uint8_t) 0x05), + OCD_TH_2625mA = ((uint8_t) 0x06), + OCD_TH_3000mA = ((uint8_t) 0x07), + OCD_TH_3375mA = ((uint8_t) 0x08), + OCD_TH_3750mA = ((uint8_t) 0x09), + OCD_TH_4125mA = ((uint8_t) 0x0A), + OCD_TH_4500mA = ((uint8_t) 0x0B), + OCD_TH_4875mA = ((uint8_t) 0x0C), + OCD_TH_5250mA = ((uint8_t) 0x0D), + OCD_TH_5625mA = ((uint8_t) 0x0E), + OCD_TH_6000mA = ((uint8_t) 0x0F) +} OCD_TH_TypeDef; + +/* easySPIN STEP_MODE register masks */ +typedef enum { + STEP_MODE_STEP_SEL = ((uint8_t) 0x07), + STEP_MODE_SYNC_SEL = ((uint8_t) 0x70) +} STEP_MODE_Masks_TypeDef; + +/* easySPIN STEP_MODE register options */ +/* easySPIN STEP_SEL options */ +typedef enum { + STEP_SEL_1 = ((uint8_t) 0x08), + STEP_SEL_1_2 = ((uint8_t) 0x09), + STEP_SEL_1_4 = ((uint8_t) 0x0A), + STEP_SEL_1_8 = ((uint8_t) 0x0B), + STEP_SEL_1_16 = ((uint8_t) 0x0C) +} STEP_SEL_TypeDef; + +/* easySPIN SYNC_SEL options */ +typedef enum { + SYNC_SEL_1_2 = ((uint8_t) 0x80), + SYNC_SEL_1 = ((uint8_t) 0x90), + SYNC_SEL_2 = ((uint8_t) 0xA0), + SYNC_SEL_4 = ((uint8_t) 0xB0), + SYNC_SEL_8 = ((uint8_t) 0xC0), + SYNC_SEL_UNUSED = ((uint8_t) 0xD0) +} SYNC_SEL_TypeDef; + +/* easySPIN ALARM_EN register options */ +typedef enum { + ALARM_EN_OVERCURRENT = ((uint8_t) 0x01), + ALARM_EN_THERMAL_SHUTDOWN = ((uint8_t) 0x02), + ALARM_EN_THERMAL_WARNING = ((uint8_t) 0x04), + ALARM_EN_UNDERVOLTAGE = ((uint8_t) 0x08), + ALARM_EN_SW_TURN_ON = ((uint8_t) 0x40), + ALARM_EN_WRONG_NPERF_CMD = ((uint8_t) 0x80) +} ALARM_EN_TypeDef; + +/* easySPIN Config register masks */ +typedef enum { + CONFIG_OSC_SEL = ((uint16_t) 0x0007), + CONFIG_EXT_CLK = ((uint16_t) 0x0008), + CONFIG_EN_TQREG = ((uint16_t) 0x0020), + CONFIG_OC_SD = ((uint16_t) 0x0080), + CONFIG_POW_SR = ((uint16_t) 0x0300), + CONFIG_TSW = ((uint16_t) 0x7C00) +} CONFIG_Masks_TypeDef; + +/* easySPIN Config register options */ +typedef enum { + CONFIG_INT_16MHZ = ((uint16_t) 0x0000), + CONFIG_INT_16MHZ_OSCOUT_2MHZ = ((uint16_t) 0x0008), + CONFIG_INT_16MHZ_OSCOUT_4MHZ = ((uint16_t) 0x0009), + CONFIG_INT_16MHZ_OSCOUT_8MHZ = ((uint16_t) 0x000A), + CONFIG_INT_16MHZ_OSCOUT_16MHZ = ((uint16_t) 0x000B), + CONFIG_EXT_8MHZ_XTAL_DRIVE = ((uint16_t) 0x0004), + CONFIG_EXT_16MHZ_XTAL_DRIVE = ((uint16_t) 0x0005), + CONFIG_EXT_24MHZ_XTAL_DRIVE = ((uint16_t) 0x0006), + CONFIG_EXT_32MHZ_XTAL_DRIVE = ((uint16_t) 0x0007), + CONFIG_EXT_8MHZ_OSCOUT_INVERT = ((uint16_t) 0x000C), + CONFIG_EXT_16MHZ_OSCOUT_INVERT = ((uint16_t) 0x000D), + CONFIG_EXT_24MHZ_OSCOUT_INVERT = ((uint16_t) 0x000E), + CONFIG_EXT_32MHZ_OSCOUT_INVERT = ((uint16_t) 0x000F) +} CONFIG_OSC_MGMT_TypeDef; + +typedef enum { + CONFIG_EN_TQREG_INT_REG = ((uint16_t) 0x0000), + CONFIG_EN_TQREG_ADC_IN = ((uint16_t) 0x0020) +} CONFIG_EN_TQREG_TypeDef; + +typedef enum { + CONFIG_OC_SD_DISABLE = ((uint16_t) 0x0000), + CONFIG_OC_SD_ENABLE = ((uint16_t) 0x0080) +} CONFIG_OC_SD_TypeDef; + +typedef enum { + CONFIG_SR_180V_us = ((uint16_t) 0x0000), + CONFIG_SR_290V_us = ((uint16_t) 0x0200), + CONFIG_SR_530V_us = ((uint16_t) 0x0300) +} CONFIG_POW_SR_TypeDef; + +typedef enum { + CONFIG_TSW_4_us = (((uint16_t) 0x01) << 10), + CONFIG_TSW_8_us = (((uint16_t) 0x02) << 10), + CONFIG_TSW_12_us = (((uint16_t) 0x03) << 10), + CONFIG_TSW_16_us = (((uint16_t) 0x04) << 10), + CONFIG_TSW_20_us = (((uint16_t) 0x05) << 10), + CONFIG_TSW_24_us = (((uint16_t) 0x06) << 10), + CONFIG_TSW_28_us = (((uint16_t) 0x07) << 10), + CONFIG_TSW_32_us = (((uint16_t) 0x08) << 10), + CONFIG_TSW_36_us = (((uint16_t) 0x09) << 10), + CONFIG_TSW_40_us = (((uint16_t) 0x0A) << 10), + CONFIG_TSW_44_us = (((uint16_t) 0x0B) << 10), + CONFIG_TSW_48_us = (((uint16_t) 0x0C) << 10), + CONFIG_TSW_52_us = (((uint16_t) 0x0D) << 10), + CONFIG_TSW_56_us = (((uint16_t) 0x0E) << 10), + CONFIG_TSW_60_us = (((uint16_t) 0x0F) << 10), + CONFIG_TSW_64_us = (((uint16_t) 0x10) << 10), + CONFIG_TSW_68_us = (((uint16_t) 0x11) << 10), + CONFIG_TSW_72_us = (((uint16_t) 0x12) << 10), + CONFIG_TSW_76_us = (((uint16_t) 0x13) << 10), + CONFIG_TSW_80_us = (((uint16_t) 0x14) << 10), + CONFIG_TSW_84_us = (((uint16_t) 0x15) << 10), + CONFIG_TSW_88_us = (((uint16_t) 0x16) << 10), + CONFIG_TSW_92_us = (((uint16_t) 0x17) << 10), + CONFIG_TSW_96_us = (((uint16_t) 0x18) << 10), + CONFIG_TSW_100_us = (((uint16_t) 0x19) << 10), + CONFIG_TSW_104_us = (((uint16_t) 0x1A) << 10), + CONFIG_TSW_108_us = (((uint16_t) 0x1B) << 10), + CONFIG_TSW_112_us = (((uint16_t) 0x1C) << 10), + CONFIG_TSW_116_us = (((uint16_t) 0x1D) << 10), + CONFIG_TSW_120_us = (((uint16_t) 0x1E) << 10), + CONFIG_TSW_124_us = (((uint16_t) 0x1F) << 10) +} CONFIG_TSW_TypeDef; + +/* Status Register bit masks */ +typedef enum { + STATUS_HIZ = (((uint16_t) 0x0001)), + STATUS_DIR = (((uint16_t) 0x0010)), + STATUS_NOTPERF_CMD = (((uint16_t) 0x0080)), + STATUS_WRONG_CMD = (((uint16_t) 0x0100)), + STATUS_UVLO = (((uint16_t) 0x0200)), + STATUS_TH_WRN = (((uint16_t) 0x0400)), + STATUS_TH_SD = (((uint16_t) 0x0800)), + STATUS_OCD = (((uint16_t) 0x1000)) +} STATUS_Masks_TypeDef; + +/* Status Register options */ +typedef enum { + STATUS_DIR_FORWARD = (((uint16_t) 0x0001) << 4), + STATUS_DIR_REVERSE = (((uint16_t) 0x0000) << 4) +} STATUS_DIR_TypeDef; + +/* easySPIN internal register addresses */ +typedef enum { + ABS_POS = ((uint8_t) 0x01), + EL_POS = ((uint8_t) 0x02), + MARK = ((uint8_t) 0x03), + RESERVED_REG01 = ((uint8_t) 0x04), + RESERVED_REG02 = ((uint8_t) 0x05), + RESERVED_REG03 = ((uint8_t) 0x06), + RESERVED_REG04 = ((uint8_t) 0x07), + RESERVED_REG05 = ((uint8_t) 0x08), + RESERVED_REG06 = ((uint8_t) 0x15), + TVAL = ((uint8_t) 0x09), + RESERVED_REG07 = ((uint8_t) 0x0A), + RESERVED_REG08 = ((uint8_t) 0x0B), + RESERVED_REG09 = ((uint8_t) 0x0C), + RESERVED_REG10 = ((uint8_t) 0x0D), + T_FAST = ((uint8_t) 0x0E), + TON_MIN = ((uint8_t) 0x0F), + TOFF_MIN = ((uint8_t) 0x10), + RESERVED_REG11 = ((uint8_t) 0x11), + ADC_OUT = ((uint8_t) 0x12), + OCD_TH = ((uint8_t) 0x13), + RESERVED_REG12 = ((uint8_t) 0x14), + STEP_MODE = ((uint8_t) 0x16), + ALARM_EN = ((uint8_t) 0x17), + CONFIG = ((uint8_t) 0x18), + STATUS = ((uint8_t) 0x19), + RESERVED_REG13 = ((uint8_t) 0x1A), + RESERVED_REG14 = ((uint8_t) 0x1B) +} Registers_TypeDef; + +/* easySPIN command set */ +typedef enum { + NOP = ((uint8_t) 0x00), + SET_PARAM = ((uint8_t) 0x00), + GET_PARAM = ((uint8_t) 0x20), + ENBL = ((uint8_t) 0xB8), + DSBL = ((uint8_t) 0xA8), + GET_STATUS = ((uint8_t) 0xD0), + RESERVED_CMD1 = ((uint8_t) 0xEB), + RESERVED_CMD2 = ((uint8_t) 0xF8) +} Commands_TypeDef; + +/* easySPIN movement direction options */ +typedef enum { + DIR_Forward = ((uint8_t) 0x01), DIR_Reverse = ((uint8_t) 0x00) +} Direction_TypeDef; + +/* easySPIN action options */ +typedef enum { + ACTION_RESET = ((uint8_t) 0x00), ACTION_COPY = ((uint8_t) 0x01) +} Action_TypeDef; + +/** + * OneStep stepper motor accelerate and manipulate. + */ +class OneStep { + +public: + + /** + * Constructor. + * + * @param step mbed pin to use for stepper motor interface. + * @param direction mbed pin to use for stepper motor interface. + * @param enable mbed pin to use for stepper motor interface. + */ + OneStep(PinName mosi, + PinName miso, + PinName sck, + PinName csn, + PinName step, + PinName dir, + PinName reset, + PinName flag); + + /** + * No operation. + * + */ + void nop(void); + + /** + * Enable driver + * + */ + void enable(void); + + /** + * Disable driver + * + */ + void disable(void); + + /** + * Move to a position. + * + * @param parameter Parameter. + * @param length The length of the parameter. + * @param value The value of the parameter. + */ + void set_param(char parameter, int length, int value); + + /** + * Get parameter value. + * + * @param parameter Parameter. + * @param length The length of the parameter. + * @return Returns parameter. + */ + int get_param(char parameter, int length); + + /** + * Get status. + * + * @return Returns status word. + */ + int get_status(void); + + /** + * Move to a position. + * + * @param absolute Absolute step count. + */ + void moveTo(long absolute); + + /** + * Move to a position relative to the current position. + * + * @param relative Relative step count. + */ + void move(long relative); + + /** + * Implements steps according to the current step interval. + * + * @return Returns true if a step occurred. + */ + bool runSpeed(); + + /** + * Get distance yet to go. + * + * @return The distance count. + */ + long distanceToGo(); + + /** + * Get target position. + * + * @return The target position count. + */ + long targetPosition(); + + /** + * Get current position. + * + * @return The current position count. + */ + long currentPosition(); + + /** + * Set current position to a count. Set speed to 0. + * + * @param position The count at the current position. + */ + void setCurrentPosition(long position); + + /** + * Calculate the new speed. + * + */ + void computeNewSpeed(); + + /** + * Run the motor to implement speed and acceleration in order to proceed to the target position. + * + * @return Returns true if the motor is still running to the target position. + */ + bool run(); + + /** + * Step once. + * + */ + void step(); + + /** + * Set the max speed. + * + * @param speed Speed maximum. + */ + void setMaxSpeed(float speed); + + /** + * Set the acceleration. + * + * @param acceleration Acceleration. + */ + void setAcceleration(float acceleration); + + /** + * Set the speed. + * + * @param speed Speed. + */ + void setSpeed(float speed); + + /** + * Get current speed. + * + * @return The speed. + */ + float speed(); + + /** + * Set the minimum pulse width. + * + * @param minWidth MinWidth pulse width. + */ + void setMinPulseWidth(unsigned int minWidth); + + /** + * System reset enable. + * + */ + void enableReset(); + + /** + * System reset disable. + * + */ + void disableReset(); + + /** + * Blocks until the target position is reached and stopped. + * + */ + void runToPosition(); + + /** + * Run at speed to a position. + * + * @return The run speed. + */ + bool runSpeedToPosition(); + + /** + * Blocks until the new target position is reached. + * + * @param position Position. + */ + void runToNewPosition(long position); + + /** + * Stop run to position. + * + */ + void stop(); + + /** + * Get the alarm flag state. + * + * @return The alarm flag state. + */ + int getAlarm(); + +protected: + + /** + * Symbolic names for the direction the motor is turning. + * + */ + typedef enum + { + DIRECTION_CCW = 0, ///< Clockwise + DIRECTION_CW = 1 ///< Counter-Clockwise + } Direction; + +private: + + /** + * The current absolution position in steps. + * + */ + long _currentPos; // Steps + + /** + * The current interval between steps in microseconds. + * 0 means the motor is currently stopped with _speed == 0 + * + */ + unsigned long _stepInterval; + + /** + * The last step time in microseconds. + * + */ + unsigned long _lastStepTime; + + /** + * The minimum allowed pulse width in microseconds. + * + */ + unsigned int _minPulseWidth; + + /** + * The target position in steps. The AccelStepper library will move the + * motor from the _currentPos to the _targetPos, taking into account the + * max speed, acceleration and deceleration. + * + */ + long _targetPos; // Steps + + /** + * The current motos speed in steps per second. + * Positive is clockwise. + * + */ + float _speed; // Steps per second + + /** + * The acceleration to use to accelerate or decelerate the motor in steps + * per second per second. Must be > 0. + * + */ + float _acceleration; + float _sqrt_twoa; // Precomputed sqrt(2*_acceleration) + + /** + * The maximum permitted speed in steps per second. Must be > 0. + * + */ + float _maxSpeed; + + /** + * Min step size in microseconds based on maxSpeed. + * + */ + float _cmin; // at max speed + + /** + * Initial step size in microseconds. + * + */ + float _c0; + + /** + * Last step size in microseconds. + * + */ + float _cn; + + /** + * The step counter for speed calculations. + * + */ + long _n; + + /** + * Current direction motor is spinning in. + * + */ + bool _direction; // 1 == CW + + SPI spi_; + Timer t_; + DigitalOut nCS_; + DigitalOut step_; + DigitalOut dir_; + DigitalOut reset_; + DigitalIn flag_; +}; + +#endif \ No newline at end of file