From 013477d1aa29229fd17e5d0a54c8e9329a087bd8 Mon Sep 17 00:00:00 2001 From: ankur Date: Tue, 27 Sep 2016 12:43:03 +0530 Subject: [PATCH] move multiple stepper at same time --- arduino/src/sketch/MultiStepper.cpp | 72 ++++++++++++++++++++++++++ arduino/src/sketch/MultiStepper.h | 78 +++++++++++++++++++++++++++++ arduino/src/sketch/sketch.ino | 67 ++++++++++++++++++------- 3 files changed, 199 insertions(+), 18 deletions(-) create mode 100644 arduino/src/sketch/MultiStepper.cpp create mode 100644 arduino/src/sketch/MultiStepper.h diff --git a/arduino/src/sketch/MultiStepper.cpp b/arduino/src/sketch/MultiStepper.cpp new file mode 100644 index 0000000..0739b84 --- /dev/null +++ b/arduino/src/sketch/MultiStepper.cpp @@ -0,0 +1,72 @@ +// MultiStepper.cpp +// +// Copyright (C) 2015 Mike McCauley +// $Id: MultiStepper.cpp,v 1.2 2015/10/04 05:16:38 mikem Exp $ + +#include "MultiStepper.h" +#include "AccelStepper.h" + +MultiStepper::MultiStepper() + : _num_steppers(0) +{ +} + +boolean MultiStepper::addStepper(AccelStepper& stepper) +{ + if (_num_steppers >= MULTISTEPPER_MAX_STEPPERS) + return false; // No room for more + _steppers[_num_steppers++] = &stepper; +} + +void MultiStepper::moveTo(long absolute[]) +{ + // First find the stepper that will take the longest time to move + float longestTime = 0.0; + + uint8_t i; + for (i = 0; i < _num_steppers; i++) + { + long thisDistance = absolute[i] - _steppers[i]->currentPosition(); + float thisTime = abs(thisDistance) / _steppers[i]->maxSpeed(); + + if (thisTime > longestTime) + longestTime = thisTime; + } + + if (longestTime > 0.0) + { + // Now work out a new max speed for each stepper so they will all + // arrived at the same time of longestTime + for (i = 0; i < _num_steppers; i++) + { + long thisDistance = absolute[i] - _steppers[i]->currentPosition(); + float thisSpeed = thisDistance / longestTime; + _steppers[i]->moveTo(absolute[i]); // New target position (resets speed) + _steppers[i]->setSpeed(thisSpeed); // New speed + } + } +} + +// Returns true if any motor is still running to the target position. +boolean MultiStepper::run() +{ + uint8_t i; + boolean ret = false; + for (i = 0; i < _num_steppers; i++) + { + if ( _steppers[i]->distanceToGo() != 0) + { + _steppers[i]->runSpeed(); + ret = true; + } + } + return ret; +} + +// Blocks until all steppers reach their target position and are stopped +void MultiStepper::runSpeedToPosition() +{ + while (run()) + ; +} + diff --git a/arduino/src/sketch/MultiStepper.h b/arduino/src/sketch/MultiStepper.h new file mode 100644 index 0000000..d801bb0 --- /dev/null +++ b/arduino/src/sketch/MultiStepper.h @@ -0,0 +1,78 @@ +// MultiStepper.h + +#ifndef MultiStepper_h +#define MultiStepper_h + +#include +#if ARDUINO >= 100 +#include +#else +#include +#include +#endif + +#define MULTISTEPPER_MAX_STEPPERS 10 + +class AccelStepper; + +///////////////////////////////////////////////////////////////////// +/// \class MultiStepper MultiStepper.h +/// \brief Operate multiple AccelSteppers in a co-ordinated fashion +/// +/// This class can manage multiple AccelSteppers (up to MULTISTEPPER_MAX_STEPPERS = 10), +/// and cause them all to move +/// to selected positions at such a (constant) speed that they all arrive at their +/// target position at the same time. This can be used to support devices with multiple steppers +/// on say multiple axes to cause linear diagonal motion. Suitable for use with X-Y plotters, flatbeds, +/// 3D printers etc +/// to get linear straight line movement between arbitrary 2d (or 3d or ...) positions. +/// +/// Caution: only constant speed stepper motion is supported: acceleration and deceleration is not supported +/// All the steppers managed by MultiStepper will step at a constant speed to their +/// target (albeit perhaps different speeds for each stepper). +class MultiStepper +{ +public: + /// Constructor + MultiStepper(); + + /// Add a stepper to the set of managed steppers + /// There is an upper limit of MULTISTEPPER_MAX_STEPPERS = 10 to the number of steppers that can be managed + /// \param[in] stepper Reference to a stepper to add to the managed list + /// \return true if successful. false if the number of managed steppers would exceed MULTISTEPPER_MAX_STEPPERS + boolean addStepper(AccelStepper& stepper); + + /// Set the target positions of all managed steppers + /// according to a coordinate array. + /// New speeds will be computed for each stepper so they will all arrive at their + /// respective targets at very close to the same time. + /// \param[in] absolute An array of desired absolute stepper positions. absolute[0] will be used to set + /// the absolute position of the first stepper added by addStepper() etc. The array must be at least as long as + /// the number of steppers that have been added by addStepper, else results are undefined. + void moveTo(long absolute[]); + + /// Calls runSpeed() on all the managed steppers + /// that have not acheived their target position. + /// \return true if any stepper is still in the process of running to its target position. + boolean run(); + + /// Runs all managed steppers until they acheived their target position. + /// Blocks until all that position is acheived. If you dont + /// want blocking consider using run() instead. + void runSpeedToPosition(); + +private: + /// Array of pointers to the steppers we are controlling. + /// Fills from 0 onwards + AccelStepper* _steppers[MULTISTEPPER_MAX_STEPPERS]; + + /// Number of steppers we are controlling and the number + /// of steppers in _steppers[] + uint8_t _num_steppers; +}; + +/// @example MultiStepper.pde +/// Use MultiStepper class to manage multiple steppers and make them all move to +/// the same position at the same time for linear 2d (or 3d) motion. + +#endif diff --git a/arduino/src/sketch/sketch.ino b/arduino/src/sketch/sketch.ino index 3684dbc..ceac8d6 100644 --- a/arduino/src/sketch/sketch.ino +++ b/arduino/src/sketch/sketch.ino @@ -1,22 +1,44 @@ #include "AccelStepper.h" #include "axisDirectionStruct.h" //importing AxisAndDirection +#include "MultiStepper.h" String incomingByte; // for incoming serial data int speed = 20; // The X Stepper pins -#define STEPPER_DIR_PIN 10 -#define STEPPER_STEP_PIN 2 +#define STEPPER1_DIR_PIN 2 +#define STEPPER1_STEP_PIN 3 + +#define STEPPER2_DIR_PIN 8 +#define STEPPER2_STEP_PIN 9 + +//#define STEPPER3_DIR_PIN 10 +//#define STEPPER3_STEP_PIN 2 #define led_pin 13 -// Define some stepper and the pins the will use -//AccelStepper::DRIVER means that we are using Driver, or we can write simply "1" -AccelStepper stepper(AccelStepper::DRIVER, STEPPER_STEP_PIN, STEPPER_DIR_PIN); +/** Define some stepper and the pins the will use +AccelStepper::DRIVER means that we are using Driver, or we can write simply "1" +stepper1 : x-axis movement +stepper2, stepper3 : y and z axis movement +when both motor move in same direction with same speed : y axis, and when both motor moves in different direction with same speed : z axis +*/ +AccelStepper stepper1(AccelStepper::DRIVER, STEPPER1_DIR_PIN, STEPPER1_STEP_PIN); +AccelStepper stepper2(AccelStepper::DRIVER, STEPPER2_DIR_PIN, STEPPER2_STEP_PIN); +//To add multiple steppers to MultiStepper +MultiStepper steppers; void setup() { + Serial.begin(9600); pinMode(led_pin, OUTPUT); - stepper.setMaxSpeed(40); + //Set Max speed of steppers + stepper1.setMaxSpeed(10); + stepper2.setMaxSpeed(10); + stepper1.moveTo(0); + stepper2.moveTo(0); + // Then give them to MultiStepper to manage + steppers.addStepper(stepper1); + steppers.addStepper(stepper2); } void blockingRunSpeedToPosition(long position) @@ -27,18 +49,27 @@ void blockingRunSpeedToPosition(long position) But we want blocking so we have to implement own loop using while */ - stepper.setCurrentPosition(0); - - ///stepper.moveTo function : Set the target position absolute to the current position - // stepper.moveTo(position); - - ///stepper.move funtion : Set the target position relative to the current position - /// if position is negative then anticlockwise from the current position, else clockwise from current position - stepper.move(position); - stepper.setSpeed(speed); + stepper1.setCurrentPosition(0); + stepper2.setCurrentPosition(0); + stepper1.setAcceleration(100); + stepper2.setAcceleration(100); + /**stepper.moveTo function : Set the target position absolute to the current position + stepper.moveTo(position); + stepper.move funtion : Set the target position relative to the current position + if position is negative then anticlockwise from the current position, else clockwise from current position + */ +// stepper1.move(position); +// stepper1.setSpeed(speed); // stepper.setAcceleration(100.0); - while (stepper.distanceToGo() != 0) - stepper.runSpeedToPosition(); +// while (stepper1.distanceToGo() != 0) +// stepper1.runSpeedToPosition(); + + long positions[2]; + positions[0] = position; + positions[1] = position; +// steppers.setCurrentPosition(0); + steppers.moveTo(positions); + steppers.runSpeedToPosition(); } @@ -50,7 +81,7 @@ void loop() Serial.println(incomingByte); AxisAndDirection axisAndDirection = getAxisAndDirection(incomingByte); int stepsPerKeyStrock = 200; - if(axisAndDirection.axis == 'x') { + if(axisAndDirection.axis == 'y') { digitalWrite(led_pin,HIGH); if(axisAndDirection.direction == -1) { stepsPerKeyStrock = -stepsPerKeyStrock;