is it possible to iterate through an array of steppers in order to only iterate the code once?
#include "AccelStepper.h"
// AccelStepper Setup
AccelStepper stepperX(1, 2, 5); // 1 = Driver interface, Pin 2 STEP, Pin 5 DIR
AccelStepper stepperY(1, 3, 6); // 1 = Driver interface, Pin 3 STEP, Pin 6 DIR
// Stepper Travel Variables
char* stepper[] = {"stepperX", "stepperY"};
int stepperCount = 2;
void setup() {
pinMode(8, OUTPUT);
digitalWrite(8, LOW); // enable pin needs to be set LOW with DRV 8825
// Set Max Speed and Acceleration of each Steppers at startup for homing
for (int thisStepper = 0; thisStepper < stepperCount; thisStepper ++) {
stepper[thisStepper].setMaxSpeed(100.0); // Set Max Speed of Stepper (Slower to get better accuracy)
stepper[thisStepper].setAcceleration(100.0); // Set Acceleration of Stepper
}
Apologies; not articulated very well. The rest of the code does other functions but I was wondering if it is possible to use an array to store multiple names to add to functions like you can with PIN numbers for example.
So instead of using:
stepperX.setMaxSpeed(100);
stepperX.setAcceleration(100);
stepperY.setMaxSpeed(100);
stepperY.setAcceleration(100);
stepperZ.setMaxSpeed(100);
stepperZ.setAcceleration(100);
etc.
and the same for other functions such as movement, I could use the array as shown above? I can't seem to get it to work though and wasn't sure it it is even possible to insert strings like this?
If you are asking can you have an array of stepper instances then I suspect the answer should be yes, but I don't know how to do it and a quick Google of accelstepper array did not produce an obvious solution.
It may be that after the individual stepper instances have been created you can create an array of pointers to them.
Hopefully someone with more knowledge of C++ will come along.
Have a look at the MultiStepper library - it creates an array of stepper instances - but it may not allow the full use of all the stepper library features.
Testing this now; a few bugs which I am ironing out; but first stepper initialised and homed correctly
Here is the full test code: I am using CmdArduino as the final plan is to pass commands over serial from a RaspberryPi with touchscreen and GUI.
There are a few TODOs in the description at the top
/*
Implementation of AccelSteppr control of X and Y axis
AxisJoystick Jog funtion
Library created by Mike McCauley at http://www.airspayce.com/mikem/arduino/AccelStepper/
Using code from Yvan / https://Brainy-Bits.com for AccelStepper
Using code from Akiba for CmdArduino
Help and code from cbrandt on arduino forum
TODO
Return stepper position from thisStepper to stored vale for X, Y, Z and A
Set max move distance for each axis
Set multiplier for move / mm for each axis
*/
#include "AccelStepper.h"
#include <Cmd.h>
#include <AxisJoystick.h>
// Define the Pins used
#define X_home_switch 9 // Pin 9 connected to Home Switch (MicroSwitch)
#define Y_home_switch 10 // Pin 10 connected to Home Switch (MicroSwitch)
#define SW_PIN 7 // Pin 7 for Joystick Press
#define VRX_PIN A1 // Pin A1 for Joystick Right and Left
#define VRY_PIN A2 // Pin A2 for Joystick Up and Down
// AccelStepper Setup
AccelStepper stepper[] = {AccelStepper (1, 2, 5), AccelStepper (1, 3, 6)}; // 1 = Driver interface, then STEP pin, finally DIR Pin
byte *home_switch[] = {X_home_switch, Y_home_switch};
// AccelStepper stepperZ(1, 4, 7); // 1 = Driver interface, Pin 4 STEP, Pin 7 DIR
// AccelStepper stepperA(1, 12, 13); // 1 = Driver interface, Pin 12 STEP, Pin 13 DIR
AxisJoystick* joystick;
// Stepper Travel Variables
long Travel; // Used to store the value entered in the Serial Monitor
byte move_finished=1; // Used to check if move is completed
long initial_homing=-1; // Used to Home Stepper at startup
byte stepperCount = 1;
void setup() {
delay(5); // Wait for Driver wake up
pinMode(X_home_switch, INPUT_PULLUP);
pinMode(Y_home_switch, INPUT_PULLUP);
pinMode(8, OUTPUT);
digitalWrite(8, LOW); // enable pin needs to be set LOW with DRV 8825
Serial.begin(9600); // Start the Serial monitor with speed of 9600 Bauds
cmdInit(&Serial); // Initiate CmdArduino over serial bus
cmdAdd("move", move_stepper); // Add commmand "move" to run function move_stepper
cmdAdd("jog", jog_stepper); // Add command "jog" to run function jog_stepper
joystick = new AxisJoystick(SW_PIN, VRX_PIN, VRY_PIN); // Start Joystick
// Set Max Speed and Acceleration of each Steppers at startup for homing
for (byte thisStepper = 0; thisStepper < stepperCount; thisStepper ++) {
stepper[thisStepper].setMaxSpeed(100.0); // Set Max Speed of Stepper (Slower to get better accuracy)
stepper[thisStepper].setAcceleration(100.0); // Set Acceleration of Stepper
}
// Start Homing procedure of Stepper Motor at startup
Serial.print("Stepper is Homing . . . . . . . . . . . ");
for (byte thisStepper = 0; thisStepper < stepperCount; thisStepper ++) {
while (digitalRead(home_switch[thisStepper])) { // Make the Stepper move CCW until the switch is activated
stepper[thisStepper].moveTo(initial_homing); // Set the position to move to
initial_homing--; // Decrease by 1 for next move if needed
stepper[thisStepper].run(); // Start moving the stepper
delay(5);
}
stepper[thisStepper].setCurrentPosition(0); // Set the current position as zero for now
stepper[thisStepper].setMaxSpeed(100.0); // Set Max Speed of Stepper (Slower to get better accuracy)
stepper[thisStepper].setAcceleration(100.0); // Set Acceleration of Stepper
initial_homing=1;
while (!digitalRead(home_switch[thisStepper])) { // Make the Stepper move CW until the switch is deactivated
stepper[thisStepper].moveTo(initial_homing);
stepper[thisStepper].run();
initial_homing++;
delay(5);
}
stepper[thisStepper].setCurrentPosition(0);
Serial.print("Stepper "); Serial.print(thisStepper); Serial.println("Homing Completed");
Serial.println("");
stepper[thisStepper].setMaxSpeed(1000.0); // Set Max Speed of Stepper (Faster for regular movements)
stepper[thisStepper].setAcceleration(1000.0); // Set Acceleration of Stepper
}
// Print out Instructions on the Serial Monitor at Start
Serial.println("Use command move followed by array number 0 = X. 1 = Y, finally distance e.g. move 0 100): ");
}
void loop()
{
cmdPoll();
}
void move_stepper(int arg_cnt, char **args) {
move_finished=0; // Set variable for checking move of the Stepper
Travel = cmdStr2Num(args[2], 10);
byte thisStepper = (args[1]);
if (Travel < 0 || Travel > 225) { // Make sure the position entered is not beyond the HOME or MAX position
Serial.println("");
Serial.println("Please enter a value greater than zero and smaller or equal to 225.....");
Serial.println("");
} else {
Serial.print("Moving stepper into position: ");
Serial.println(Travel);
stepper[thisStepper].moveTo(Travel); // Set new moveto position of Stepper
delay(1000); // Wait 1 seconds before moving the Stepper
}
if (Travel >= 0 && Travel <= 225) {
// Check if the Stepper has reached desired position
while ((stepper[thisStepper].distanceToGo() != 0)) {
stepper[thisStepper].run(); // Move Stepper into position
}
// If move is completed display message on Serial Monitor
if ((move_finished == 0) && (stepper[thisStepper].distanceToGo() == 0)) {
Serial.println("COMPLETED!");
Serial.println("");
Serial.println("Enter Travel distance (Positive for CW / Negative for CCW and Zero for back to Home): ");
move_finished=1; // Reset move variable
}
}
}
void jog_stepper(int arg_cnt, char **args) {
while (true){
const AxisJoystick::Move move = joystick->multipleRead();
byte thisStepper = (args[1]);
byte jogstep = 0;
if (move == AxisJoystick::Move::LEFT) {
if ((stepper[thisStepper].currentPosition() !=0)){
jogstep = stepper[thisStepper].currentPosition();
stepper[thisStepper].moveTo(jogstep-1); // Set new move to position of Stepper
while ((stepper[thisStepper].distanceToGo() !=0)){
stepper[thisStepper].run(); // Move Stepper into position
delay(5);
Serial.print (stepper[thisStepper].currentPosition());
}
}
}
if (move == AxisJoystick::Move::RIGHT) {
if ((stepper[thisStepper].currentPosition() !=85)){
jogstep = stepper[thisStepper].currentPosition();
stepper[thisStepper].moveTo(jogstep+1); // Set new move to position of Stepper
while ((stepper[thisStepper].distanceToGo() !=0)){
stepper[thisStepper].run(); // Move Stepper into position
delay(5);
Serial.print (stepper[thisStepper].currentPosition());
}
}
}
if (move == AxisJoystick::Move::PRESS) {
return(0);
}
}
}
As you have proved that @cbrandt's array solution works then it should work for any type of movement.
I suggest you get the move and jog working properly with a single stepper so that the code can be simplified before applying it to the array of steppers.
I will bookmark @cbrandt's post for future reference.
I made the changes to initialising home switches as suggested. I had already made simple sketches having the other 2 functions work with a single stepper.
What I failed to do was declare "thisStepper" correctly in the functions by using the cmdStr2Num function.
byte thisStepper = cmdStr2Num(args[1], 10);
Onwards to sorting the TODO list:
Return stepper position from thisStepper to stored vale for X, Y, Z and A
Set max move distance for each axis
Set multiplier for move / mm for each axis
Then I should be able to initiate from User interface over serial.
Here is my full working code in case it is of any use to anyone else:
/*
Implementation of AccelSteppr control of X and Y axis
AxisJoystick Jog funtion
Library created by Mike McCauley at http://www.airspayce.com/mikem/arduino/AccelStepper/
Using code from Yvan / https://Brainy-Bits.com for AccelStepper
Using code from Akiba for CmdArduino
Help and code from cbrandt on arduino forum
TODO
Return stepper position from thisStepper to stored vale for X, Y, Z and A
*/
#include "AccelStepper.h"
#include <Cmd.h>
#include <AxisJoystick.h>
// Define the Pins used
#define X_home_switch 9 // Pin 9 connected to Home Switch (MicroSwitch)
#define Y_home_switch 10 // Pin 10 connected to Home Switch (MicroSwitch)
#define SW_PIN 7 // Pin 7 for Joystick Press
#define VRX_PIN A1 // Pin A1 for Joystick Right and Left
#define VRY_PIN A2 // Pin A2 for Joystick Up and Down
// AccelStepper Setup
AccelStepper stepper[] = {AccelStepper (1, 2, 5), AccelStepper (1, 3, 6)}; // 1 = Driver interface, then STEP pin, finally DIR Pin
byte home_switch[] = {X_home_switch, Y_home_switch};
// AccelStepper stepperZ(1, 4, 7); // 1 = Driver interface, Pin 4 STEP, Pin 7 DIR
// AccelStepper stepperA(1, 12, 13); // 1 = Driver interface, Pin 12 STEP, Pin 13 DIR
AxisJoystick* joystick;
// Stepper Travel Variables
long Travel; // Used to store the value entered in the Serial Monitor
long maxTravel[] {255, 255}; // Array for soft limit max travel of each axis in order X, Y, Z, A
float mmRatio[] {1, 1}; // Array for mm/step ratio for each axis in order X, Y, Z, A
byte move_finished=1; // Used to check if move is completed
long initial_homing=-1; // Used to Home Stepper at startup
byte stepperCount = 2;
long axisPosition[] {0, 0}; // Array to store current axis positions
void setup() {
delay(5); // Wait for Driver wake up
pinMode(X_home_switch, INPUT_PULLUP);
pinMode(Y_home_switch, INPUT_PULLUP);
pinMode(8, OUTPUT);
digitalWrite(8, LOW); // enable pin needs to be set LOW with DRV 8825
Serial.begin(9600); // Start the Serial monitor with speed of 9600 Bauds
cmdInit(&Serial); // Initiate CmdArduino over serial bus
cmdAdd("move", move_stepper); // Add commmand "move" to run function move_stepper
cmdAdd("jog", jog_stepper); // Add command "jog" to run function jog_stepper
joystick = new AxisJoystick(SW_PIN, VRX_PIN, VRY_PIN); // Start Joystick
// Set Max Speed and Acceleration of each Steppers at startup for homing
for (byte thisStepper = 0; thisStepper < stepperCount; thisStepper ++) {
stepper[thisStepper].setMaxSpeed(100.0); // Set Max Speed of Stepper (Slower to get better accuracy)
stepper[thisStepper].setAcceleration(100.0); // Set Acceleration of Stepper
}
// Start Homing procedure of Stepper Motor at startup
Serial.print("Stepper is Homing . . . . . . . . . . . ");
for (byte thisStepper = 0; thisStepper < stepperCount; thisStepper ++) {
while (digitalRead(home_switch[thisStepper])) { // Make the Stepper move CCW until the switch is activated
stepper[thisStepper].moveTo(initial_homing); // Set the position to move to
initial_homing--; // Decrease by 1 for next move if needed
stepper[thisStepper].run(); // Start moving the stepper
delay(5);
}
stepper[thisStepper].setCurrentPosition(0); // Set the current position as zero for now
stepper[thisStepper].setMaxSpeed(100.0); // Set Max Speed of Stepper (Slower to get better accuracy)
stepper[thisStepper].setAcceleration(100.0); // Set Acceleration of Stepper
initial_homing=1;
while (!digitalRead(home_switch[thisStepper])) { // Make the Stepper move CW until the switch is deactivated
stepper[thisStepper].moveTo(initial_homing);
stepper[thisStepper].run();
initial_homing++;
delay(5);
}
stepper[thisStepper].setCurrentPosition(0);
Serial.print("Stepper "); Serial.print(thisStepper); Serial.println(" Homing Completed");
Serial.println("");
stepper[thisStepper].setMaxSpeed(1000.0); // Set Max Speed of Stepper (Faster for regular movements)
stepper[thisStepper].setAcceleration(1000.0); // Set Acceleration of Stepper
}
Serial.println("Homing complete for all axes");
Serial.println("");
// Print out Instructions on the Serial Monitor at Start
Serial.println("Move: Moves absolute distance from 0. Use: move (stepper array number) (distance) e.g. move 0 100 - move X axis 100mm ");
Serial.println("");
Serial.println("Jog: Jogs by set step size. Use: jog (stepper array number) (jog size) e.g. jog 1 10 - jogs Y axis in 10mm steps");
}
void loop()
{
cmdPoll();
}
void move_stepper(int arg_cnt, char **args) {
move_finished=0; // Set variable for checking move of the Stepper
byte thisStepper = cmdStr2Num(args[1], 10);
Travel = (cmdStr2Num(args[2], 10) * mmRatio[thisStepper]);
if (Travel < 0 || Travel > maxTravel[thisStepper]) { // Make sure the position entered is not beyond the HOME or MAX position
Serial.println("");
Serial.println("Please enter a value greater than zero and smaller or equal to 225.....");
Serial.println("");
} else {
Serial.print("Moving stepper into position: ");
Serial.println(Travel);
stepper[thisStepper].moveTo(Travel); // Set new moveto position of Stepper
delay(1000); // Wait 1 seconds before moving the Stepper
}
if (Travel >= 0 && Travel <= 225) {
// Check if the Stepper has reached desired position
while ((stepper[thisStepper].distanceToGo() != 0)) {
stepper[thisStepper].run(); // Move Stepper into position
}
// If move is completed display message on Serial Monitor
if ((move_finished == 0) && (stepper[thisStepper].distanceToGo() == 0)) {
Serial.println("COMPLETED!");
Serial.println("");
axisPosition[thisStepper] = stepper[thisStepper].currentPosition();
for (byte thisAxis = 0; thisAxis < stepperCount; thisAxis ++) {
Serial.print("Axis "); Serial.print(thisAxis); Serial.print(" position is: "); Serial.println(axisPosition[thisAxis]);
}
move_finished=1; // Reset move variable
}
}
}
void jog_stepper(int arg_cnt, char **args) {
while (true){
const AxisJoystick::Move move = joystick->multipleRead();
byte thisStepper = cmdStr2Num(args[1], 10);
byte jogSize = cmdStr2Num(args[2], 10);
byte jogstep = 0;
if (move == AxisJoystick::Move::LEFT) {
if ((stepper[thisStepper].currentPosition() !=0)){
jogstep = stepper[thisStepper].currentPosition();
stepper[thisStepper].moveTo(jogstep - (jogSize * mmRatio[thisStepper])); // Set new move to position of Stepper
while ((stepper[thisStepper].distanceToGo() !=0)){
stepper[thisStepper].run(); // Move Stepper into position
delay(5);
Serial.print (stepper[thisStepper].currentPosition());
}
}
}
if (move == AxisJoystick::Move::RIGHT) {
if ((stepper[thisStepper].currentPosition() != maxTravel[thisStepper])){
jogstep = stepper[thisStepper].currentPosition();
stepper[thisStepper].moveTo(jogstep + (jogSize * mmRatio[thisStepper])); // Set new move to position of Stepper
while ((stepper[thisStepper].distanceToGo() !=0)){
stepper[thisStepper].run(); // Move Stepper into position
delay(5);
Serial.print (stepper[thisStepper].currentPosition());
}
}
}
if (move == AxisJoystick::Move::PRESS) {
axisPosition[thisStepper] = stepper[thisStepper].currentPosition();
for (byte thisAxis = 0; thisAxis < stepperCount; thisAxis ++) {
Serial.print("Axis "); Serial.print(thisAxis); Serial.print(" position is: "); Serial.println(axisPosition[thisAxis]);
}
return(0);
}
}
}