Go Down

Topic: AccelStepper iteration of functions (Read 274 times) previous topic - next topic

dave_robinson_022

is it possible to iterate through an array of steppers in order to only iterate the code once?

Code: [Select]


#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

  }

Robin2

It looks to me like that is what your program does. The setup() function is only called once.

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

dave_robinson_022

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:

Code: [Select]

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?

Robin2

Sorry. I still don't understand.

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.

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

cbrandt

You should declare your stepper array as an array of AccelStepper pointers instead of strings:
Code: [Select]

AccelStepper *stepper[] = {&stepperX, &stepperY, &stepperZ};

Then replace
Code: [Select]

stepper[thisStepper].setMaxSpeed (100.0);

by
Code: [Select]

stepper[thisStepper]->setMaxSpeed (100.0);

And other places as well of course.

Robin2

You should declare your stepper array as an array of AccelStepper pointers instead of strings:
Code: [Select]

AccelStepper *stepper[] = {&stepperX, &stepperY, &stepperZ};

When you do it that way how do your specify the DRIVER type and I/O pins for each instance?

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

cbrandt

#6
Jun 18, 2018, 06:02 pm Last Edit: Jun 18, 2018, 06:12 pm by cbrandt
Well, the OP should still declare stepperX, stepperY and stepperZ as before, the array is just there to store the pointers to the 3 instances...

Of course we could get rid of these 3 variables and initialize the array another way...

EDIT: here we go…

This time stepper is an array of AccelStepper instances, not an array of AccepStepper pointers (like in my previous post):
Code: [Select]

AccelStepper stepper[] = {AccelStepper (1, 2, 5), AccelStepper (1, 3, 6)};

so now each instance can be accessed this way:
Code: [Select]

stepper[0].setMaxSpeed (100);
stepper[1].setMaxSpeed (100);

instead of:
Code: [Select]

stepper[0]->setMaxSpeed (100);
stepper[1]->setMaxSpeed (100);

when using an array of pointers…



Robin2

This time stepper is an array of AccelStepper instances, not an array of AccepStepper pointers (like in my previous post):
Code: [Select]

AccelStepper stepper[] = {AccelStepper (1, 2, 5), AccelStepper (1, 3, 6)};

That is neat. Have you tested it to be sure that it works? If so, perhaps you would post the test program.

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

cbrandt

It compiles fine, but not tested.
I don't see why it wouldn't work, but will try tomorrow just to be sure...

dave_robinson_022

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

Code: [Select]

/* 
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);
      }
  }
 }


dave_robinson_022

Homing sequence works perfectly with 2 steppers... move command and jog not so much...

Robin2

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.

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

cbrandt

#12
Jun 19, 2018, 07:38 pm Last Edit: Jun 19, 2018, 07:39 pm by cbrandt
It works for controlling the steppers, good !

What I can see is that the array HomeSwitch should be declared as
Code: [Select]

byte home_switch[] = {X_home_switch, Y_home_switch};

But that is not related to the problems with your code... it's just cleaner.

As @robin2 said, try to make a simple test sketch to work out the jog and move functions.

dave_robinson_022

Got it.

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.

Code: [Select]

 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.

Thanks for all of your help and advice

dave_robinson_022

Here is my full working code in case it is of any use to anyone else:

Code: [Select]

/* 
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);
      }
  }
 }


Go Up