Accelstepper an' 2 steppers.

sooo..
kind of a newby in arduino, zo be gentle please)

I'm building a 2-dof arm to draw or print something. right now I'm into my second prototype, understanding how to move steppers (the first one used 9g servos). now it's 28BYJ-48 5v steppers with 1/64 gear with ULN2003 driver. next on the plan are 24v steppers from old printer with cnc shield and dvr8825.
guess the pictures explains best in which state it is

the code homes all motors, gets x and y values from formula (like in here), or u just uses 2 coordinates, then a bit of trigonometry to calculate angles and poof we done (recently added a servo to move a pen).

//debugging LED
const int ledPin = 13;
 
// Servo Angles
float ServoS_1_Angle = 0;
float ServoS_2_Angle = 0;
 
// Define arm Constants
const float a = 10;      // lower joint length (cm)
const float b = 8.5;      // upper joint length (cm)
 
// Correction factors to align servo values with their respective axis
const float S_1_CorrectionFactor = 10;     // Align arm "a" with the horizontal when at 0 degrees
const float S_2_CorrectionFactor = 0;     // Align arm "b" with arm "a" when at 0 degrees
 
// Correction factor to shift origin out to edge of the mount
const float X_CorrectionFactor = 7;       // X direction correction factor (cm)
const float Y_CorrectionFactor = 0;       // Y direction correction factor (cm)
 
// Angle Variables
float A;            //Angle oppposite side a (between b and c)
float B;            //Angle oppposite side b
float C;            //Angle oppposite side c
float theta;        //Angle formed between line from origin to (x,y) and the horizontal
 
// Distance variables
float x;            // x position (cm)
float y;            // y position (cm)
float c;            // Hypotenuse legngth in cm
const float pi = M_PI;  //Store pi in a less annoying format
 
//Circle Setup
const float Radius = 2.5;       // Radius of circle in centimeters
const int CircleCenterX = 5;   // X coordinate of the center of the circle 
const int CircleCenterY = 0;    // Y coordinate of the center of the circle
 
//=====================================================================
//===========STEPPERS=================================================
//=====================================================================
#include <AccelStepper.h>
 
#define HALFSTEP 8   
 
// Определение пинов для управления двигателем 1
#define motor1Pin1  8 // IN1 на 1-м драйвере ULN2003
#define motor1Pin2  9 // IN2 на 1-м драйвере ULN2003
#define motor1Pin3  10 // IN3 на 1-м драйвере ULN2003
#define motor1Pin4  11 // IN4 на 1-м драйвере ULN2003
#define button  7 
AccelStepper stepper1(HALFSTEP, motor1Pin1, motor1Pin3, motor1Pin2, motor1Pin4);
 
const int homeButton1 = 7;
byte hBval;
 
// Определение пинов для управления двигателем 2
#define motor2Pin1  2 // IN1 на 2-м драйвере ULN2003
#define motor2Pin2  3 // IN2 на 2-м драйвере ULN2003
#define motor2Pin3  4 // IN3 на 2-м драйвере ULN2003
#define motor2Pin4  5 // IN4 на 2-м драйвере ULN2003
#define button  6 
AccelStepper stepper2(HALFSTEP, motor2Pin1, motor2Pin3, motor2Pin2, motor2Pin4);
 
const int homeButton2 = 6;
byte hBva2;
 
//=========================================
//==============SERVO=======================
//=========================================
#include <Servo.h>
 
Servo Servo_p;      // pen joint
 
const float serv_ang1 = 140; // angle for up pen position
const float serv_ang2 = 165; // angle for down pen position
 
//=====================================================================
//==============SETUP=================================================
//=====================================================================
void setup(){
 
  //steppers setup
  stepper1.setMaxSpeed(800); //nice and slow for testing
  stepper1.setAcceleration(500);
  stepper1.setSpeed(600);
  pinMode(homeButton1, INPUT_PULLUP);
  
  stepper2.setMaxSpeed(1000); //nice and slow for testing
  stepper2.setAcceleration(500);
  stepper2.setSpeed(800);
  
  pinMode(homeButton2, INPUT_PULLUP);
  
  //servo setup
  Servo_p.attach(12);             // pen joint
 
  pinMode(ledPin, OUTPUT);        // -For debugging
  
  Serial.begin(9600);             // -For debugging
  Serial.println(0);
 
  servo_pHome(); //runs routine to home servo_p
  stepper2Home(); //runs routine to home motor1
  stepper1Home(); //runs routine to home motor2
 
}
//==============LOOP====================================
void loop()
{
  for (float t = 0; t<20; t++)           // Get t value
  {
    
    x = 4 ; 
    y = t/2 ;
 
    //parabola
    //x = sq(t/2)/10 ; 
    //y = t/2 ;
 
    // Equation of a circle in parametric form
    //x = Radius * cos(t *(pi/180)) + CircleCenterX; 
    //y = Radius * sin(t *(pi/180)) + CircleCenterY;
    
    FixCoordinates(x,y);          // Enter coordinates of point.
    CalculateServoAngles();           // Calculate angle of servos
    MoveArm();                        // Move arm to new position
    delay(200);
    MoveServo();
    delay(200);
  }
}
 //==============HOMING-RUTINE==============================
void stepper1Home(){ //this routine should run the motor
  hBval = digitalRead(homeButton1);
  while (hBval == LOW)
  {
    //backwards slowly till it hits the switch and stops
    stepper1.moveTo(4000);
    stepper1.run();
    hBval = digitalRead(homeButton1);
  }
  delay(1000);
  stepper1.setCurrentPosition(0); //should set motor position to zero and go back to main routine
  delay(1000);
  }
 void stepper2Home(){ //this routine should run the motor
  hBva2 = digitalRead(homeButton2);
  while (hBva2 == LOW)
  {
    //backwards slowly till it hits the switch and stops
    stepper2.moveTo(4000);
    stepper2.run();
    hBva2 = digitalRead(homeButton2);
  }
  delay(1000);
  stepper2.setCurrentPosition(0); //should set motor position to zero and go back to main routine
  delay(1000);
}
 void servo_pHome(){
   digitalWrite(ledPin, HIGH);
   delay(500);
   digitalWrite(ledPin, LOW);
   delay(500);
   digitalWrite(ledPin, HIGH);
   delay(500);
   digitalWrite(ledPin, LOW);
   delay(500);
   Servo_p.write(serv_ang1);              // risen pen 
   delay(1000);
 }
//======================CALCULATING==============================================
 //gets x and y measured from the bottom of the base. function corrects for offset
void FixCoordinates(float x_input, float y_input)
{
 x = x_input + X_CorrectionFactor;
 y = y_input + Y_CorrectionFactor;
}
 //calculates necessary servo angles to move arm to desired points
void CalculateServoAngles()
{
  c = sqrt( sq(x) + sq(y) );                                            // pythagorean theorem
  B = (acos( (sq(b) - sq(a) - sq(c))/(-2*a*c) )) * (180/pi);            // Law of cosines: Angle opposite upper arm section
  C = 180-(acos( (sq(c) - sq(b) - sq(a))/(-2*a*b) )) * (180/pi);            // Law of cosines: Angle opposite hypotenuse
  theta = (asin( y / c )) * (180/pi);                                   // Solve for theta to correct for lower joint's impact on upper joint's angle
  ServoS_1_Angle = ( B + theta + S_1_CorrectionFactor ) * 11,37777777777778;     // Find necessary angle. Add Correction. Multiply by gear ratio
  ServoS_2_Angle = ( C + S_2_CorrectionFactor ) * 11,37777777777778;           // Find neceesary angle. Add Correction. Multiply by gear ratio
 }
 //updates the motors
void MoveArm()
{
          Serial.println(22);
          stepper1.moveTo(-ServoS_1_Angle);
          stepper1.runToPosition();
          stepper2.moveTo(-ServoS_2_Angle);
          stepper2.runToPosition();
          delay(2);
}

soooo the problem now is with the "and poof" part. right now I'm using this to actualy move the arm. MoveArm()
ServoS_1_Angle is a value of an angle when 360=4096
the problem is that second stepper waits for the first to stop. They move one after another.
I actually read the topic on the same subject, but still I don't get how to make 2 steppers to simontaniously move
I could make a some kind of point-drawing bot with this setup, but my goal is to draw lines
Now to the questions
1)How to make them move simontaniously in my setup?
2)Will it be possible to apply this code to my next physical setup? uno+cnc shield+24v steppers+dvr8825?
in advance - I've been trying to run(), but steppers do not move at all. runSpeed() same. Also I am concerned that without RunToPosition and all that relative stuff with angles it is not possible... :frowning:

Look at the MultiStepper library, which coordinates AccelStepper across multiple stepper motors.

Or get rid of the .runToPosition() function and use something more appropriate like .runSpeed()

Your pictures have not appeared.

The steppers are moving one after the other largely because you are using the blocking runToPosition() function rather than the non-blocking run() function. You need to study the Accelstepper documentation carefully and maybe experiment with some of the examples.

You may find that you need to use the MultiStepper library but IMHO it would be advisable to learn to use the basic AccelStepper library properly first.

And it is always a good idea to learn new techniques with short programs that do nothing but the thing you are learning - in this case moving the motors. That sort of short program also makes it much easier to get advice here.

...R
Stepper Motor Basics
Simple Stepper Code

When you install the library you have the examples installed in IDE.
Play with them to see the difference between blocking and non-blocking (run-to-position vs runSpeed)

// Servo Angles
float ServoS_1_Angle = 0;
float ServoS_2_Angle = 0;

But you got rid of the servos.

const float pi = M_PI;  //Store pi in a less annoying format

pi, which could have ANY value is somehow less annoying than M_PI which WILL have a KNOWN value?

#define button  7
const int homeButton1 = 7;

Here's what's annoying. Two different names for the same pin.

const float serv_ang1 = 140; // angle for up pen position
const float serv_ang2 = 165; // angle for down pen position

penUp and penDn are far easier to use later on, when you want to raise or lower the pen. Having to scroll back to the top to determine if serv_ang1 means up or down is ... what's that word you used? Oh, yeah. Annoying.

  for (float t = 0; t<20; t++)           // Get t value

That does does not GET a value for t. It assigns a value to t. But, the point is does that comment add ANY value?

Comments are great, when they describe WHY the code is doing what it does. They are nearly useless when they describe WHAT the code does. That is usually quite obvious, unless you are diddling with timers.

void stepper1Home(){ //this routine should run the motor
  hBval = digitalRead(homeButton1);
  while (hBval == LOW)
  {

Consistent placement of curly braces (on a new line where they belong) is good. Random placement of curly braces is not.

  ServoS_1_Angle = ( B + theta + S_1_CorrectionFactor ) * 11,37777777777778;     // Find necessary angle. Add Correction. Multiply by gear ratio
  ServoS_2_Angle = ( C + S_2_CorrectionFactor ) * 11,37777777777778;           // Find neceesary angle. Add Correction. Multiply by gear ratio

Commas?

I actually read the topic on the same subject, but still I don't get how to make 2 steppers to simontaniously move

Your code tells one stepper where to go, and then says "Hey, I'll wait for you to get there...". Then, it tells other stepper where to go, and then says "Hey, I'll wait for you to get there...".

You completely defeat the purpose of using AccelStepper or MultiStepper.

You tell the two steppers to move to some new position. Then, if you want to wait for them to get there, you use a while loop that spins until stepper1 and stepper2 (did I mention that these are dumb names? Well, they are) have arrived at their commanded positions. In the body of the loop, you call stepper1.run() and stepper2.run(). You can look up the function that tells how far the stepper is from its commanded position.

maaan thanks for your replies, I've checked multistepper, as MorganS suggested. Robin2 - thanx for the code for A4988!! And PaulS - dude that's not mine like 80%)) But I tidy it up

sorry took a while to get back here. I've been improving the physical setup.
Also wanted to mention, that the previous version of calculations was unable to get -x value (it was only used in pythagorean theorem, zo abs abs abs) - the resulting point always pinned to positive x. I figured that double the angle, opposite of theta is a way to correct stepper1 position.

  • the setup is much nicer now. u'll see it now

so about 2 steppers waiting on each other. I tried run(); so it even moves simontaniously, but like a freak. the 2 vidoes use the same calculations, only difference is the @bad file has run() and the @good - runToPosition

both mute
good - video
bad - video

zo what to do now?

ps. i added the previous photo
pps. the code is too big, so txt

PaulS:
Here's what's annoying. Two different names for the same pin.

yeah no idea how to fix it..

code.txt (9.11 KB)

I don't see stepper1.run() and stepper2.run() in loop() - which is where they should be.

You need to write a short program (maybe 20 lines long) that allows you to learn how to use AccelStepper without all the confusion of your other stuff. Just get it to move each motor 500 steps at the same time. Take one of the AccelStepper example programs as your starting point.

Don't worry about geometry or anything else until you know how to control the motors.

...R