Step motor shifting problem

hi, i am on a project that make some experiment on biological cell. for this purpose i build a machine and it has 2 step motor. i want them to move simultaneously clockwise for some preiod and then counter-clockwise at same period of time. then repeat this motion continuously. my code works fine but after a while there is some mis angle between two motor. approximately 360 degree per hour. motor does this mistake when there is no load on them.

im using

*2 x 17HS3401 step motor
*arduino mega
*2 x a4988 step motor driver - half step mode-

1- this shifting is normal in step motor. or approximately what is the percantage of an average step motor makes misstep?

2- is there any way to prevent this mistake?

3- i think that adding a encoder disk and a photo resistor to understand start point and if motor shift i can detect and make them in start position. is it a proper way to prevent this mistake

i am not very experienced eith step motors so any help will be greatful for me.

// Define pin connections & motor's steps per revolution
const int dirPin1 = 3;
const int stepPin1 = 2;

const int dirPin2 = 4;//BEYAZ SAĞ
const int stepPin2 = 5;

//screen
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,20,2);  // set the LCD address to 0x27 for a 16 chars and 2 line display

//j1

#define j1sw A0
#define j1y A2
#define j1x A1
int j1swVal=0;
int j1yVal=0;
int j1xVal=0;

#define testButon 8
bool testVal;
#define initButon 9




//parameters
const int stepsPerRevolution = 200;
int stepdelay=4000;
int hiz=0;

int steps=200;
int mesafe=1;

int beklemeSuresi=3000;
float bekleme=3.0;

unsigned long counter=0;

void setup(){
  // Declare pins as Outputs
  Serial.begin(9600);
  // Declare pins as Outputs
  pinMode(stepPin1, OUTPUT);
  pinMode(dirPin1, OUTPUT);

  pinMode(stepPin2, OUTPUT);
  pinMode(dirPin2, OUTPUT);
  
  //j1
  pinMode(j1sw,INPUT);
  pinMode(j1x,INPUT);
  pinMode(j1y,INPUT);

  
  //screen
  lcd.init();                      // initialize the lcd 
  lcd.backlight();
  //welcome screen
  lcd.setCursor(2,0);
  lcd.print("Hucre Uyarim");
  lcd.setCursor(2,1);
  lcd.print("v2");
  delay(2000);

  //parameters
  initialize();
  
}


void loop(){
    // Set motor direction clockwise

  lcd.setCursor(0,1);lcd.print("dongu: ");lcd.print(counter);
  counter++;
  
  digitalWrite(dirPin1, HIGH);
  digitalWrite(dirPin2, LOW);
  
  for(int x = 0; x < steps; x++)
  {

    digitalWrite(stepPin1, HIGH);
    digitalWrite(stepPin2, HIGH);
    delayMicroseconds(stepdelay);
    digitalWrite(stepPin1, LOW);
    digitalWrite(stepPin2, LOW);
    delayMicroseconds(stepdelay);
  }
  delay(beklemeSuresi); // Wait a second
  
  // Set motor direction counterclockwise
  digitalWrite(dirPin1, LOW);
  digitalWrite(dirPin2, HIGH);
  
  for(int x = 0; x < steps; x++)
  {
    digitalWrite(stepPin1, HIGH);
    digitalWrite(stepPin2, HIGH);
    delayMicroseconds(stepdelay);
    digitalWrite(stepPin1, LOW);
    digitalWrite(stepPin2, LOW);
    delayMicroseconds(stepdelay);
  }
  delay(beklemeSuresi); // Wait a second
  bool initButonVal=0;
  initButonVal=digitalRead(initButon);
  if (initButonVal==1)initialize();
  Serial.println(initButon);
  
}
void test(){
  // Set motor direction clockwise
  digitalWrite(dirPin1, HIGH);
  digitalWrite(dirPin2, LOW);
  
  for(int x = 0; x < steps; x++)
  {

    digitalWrite(stepPin1, HIGH);
    digitalWrite(stepPin2, HIGH);
    delayMicroseconds(stepdelay);
    digitalWrite(stepPin1, LOW);
    digitalWrite(stepPin2, LOW);
    delayMicroseconds(stepdelay);
  }
  delay(beklemeSuresi); // Wait a second
  
  // Set motor direction counterclockwise
  digitalWrite(dirPin1, LOW);
  digitalWrite(dirPin2, HIGH);
  
  for(int x = 0; x < steps; x++)
  {
    digitalWrite(stepPin1, HIGH);
    digitalWrite(stepPin2, HIGH);
    delayMicroseconds(stepdelay);
    digitalWrite(stepPin1, LOW);
    digitalWrite(stepPin2, LOW);
    delayMicroseconds(stepdelay);
  }
  delay(10); // Wait a second

  
}


  


void stepup(){
  
  Serial.println("stepup");
  digitalWrite(dirPin1, HIGH);
  digitalWrite(dirPin2, LOW);

  
  for(int x = 0; x < 10; x++)
  {   
    digitalWrite(stepPin1, HIGH);
    digitalWrite(stepPin2, HIGH);
    delayMicroseconds(2000);
    digitalWrite(stepPin1, LOW);
    digitalWrite(stepPin2, LOW);
    delayMicroseconds(2000);
  }
  delay(100);

}


void stepdown(){
  
  Serial.println("stepup");
  digitalWrite(dirPin1, LOW);
  digitalWrite(dirPin2, HIGH);

  
  for(int x = 0; x < 10; x++)
  {   
    digitalWrite(stepPin1, HIGH);
    digitalWrite(stepPin2, HIGH);
    delayMicroseconds(2000);
    digitalWrite(stepPin1, LOW);
    digitalWrite(stepPin2, LOW);
    delayMicroseconds(2000);
  }
  delay(100);

}

void initialize(){


  //start position  
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("Baslangic Konumu");
  lcd.setCursor(0,1);
  lcd.print("ayarlayin");
  
  while(1){    
    j1swVal=digitalRead(j1sw);
    j1yVal=analogRead(j1y);
    j1xVal=analogRead(j1x);
    
    testVal=digitalRead(testButon);//test
    if (testVal==1) test();
    
    if (j1yVal<200) stepup();
    if (j1yVal>800) stepdown(); 
    if (j1swVal==0) {       
      while(j1swVal==0){
        j1swVal=digitalRead(j1sw);
        delay(100);
      }
      break;
      }    
  }


//speed define
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("Hizi ayarlayin");
  lcd.setCursor(0,1);
  lcd.print("hiz:");

  while(1){    
    j1swVal=digitalRead(j1sw);
    j1yVal=analogRead(j1y);
    j1xVal=analogRead(j1x);

    testVal=digitalRead(testButon);//test
    if (testVal==1) test();
    
    lcd.setCursor(6,1);
    lcd.print(hiz);
    if (j1yVal<200) hiz++;    
    if (j1yVal>800) hiz--; 
    if (j1swVal==0) {       
      while(j1swVal==0){
        j1swVal=digitalRead(j1sw);
        delay(100);
        }
      break;
      }    
    if (hiz<0) hiz=0;
    if (hiz>9) hiz=9;
      
    stepdelay=(4000-(hiz*300))/4;
    delay(150);
  }

//updown distance

    
  while(1){    
  


    j1swVal=digitalRead(j1sw);
    j1yVal=analogRead(j1y);
    j1xVal=analogRead(j1x);
    
    testVal=digitalRead(testButon);//test
    if (testVal==1) test();
    
   
    
    if (j1yVal<200){
      mesafe++; 
      lcd.clear();   
    }
    if (j1yVal>800){
      mesafe--; 
      lcd.clear();
    }
    if (j1swVal==0) {       
      while(j1swVal==0){
        j1swVal=digitalRead(j1sw);
        delay(150);
        }
      break;
      } 
         
    if (mesafe<1) mesafe=1;
    if (mesafe>40) mesafe=40;
      
    steps=(200/8)*mesafe*2;

    lcd.setCursor(0,0);
    lcd.print("Hareket mesafesi");
    lcd.setCursor(0,1);
    lcd.print("mesafe:");
    lcd.setCursor(7,1);
    lcd.print(mesafe);
    lcd.setCursor(10,1);
    lcd.print("mm");
    
    delay(100);

  }
  
//wait between up and down
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("bekleme suresi");
  lcd.setCursor(0,1);
  lcd.print("sure: ");

  while(1){    
    j1swVal=digitalRead(j1sw);
    j1yVal=analogRead(j1y);
    j1xVal=analogRead(j1x);

    testVal=digitalRead(testButon);//test
    if (testVal==1) test();
    
    lcd.setCursor(6,1);
    lcd.print(bekleme);
    lcd.setCursor(10,1);
    lcd.print(" sn");
    if (j1yVal<200) bekleme+=0.1;    
    if (j1yVal>800) bekleme-=0.1; 
    if (j1swVal==0) {       
      while(j1swVal==0){
        j1swVal=digitalRead(j1sw);
        delay(100);
        }
      break;
      } 
         
    if (bekleme<0.1) bekleme=0.1;
    if (bekleme>15) bekleme=15;
      
    beklemeSuresi=bekleme*1000;
    delay(150);   
  
  }
  
  lcd.clear();
  lcd.setCursor(0,0);lcd.print("v:");lcd.print(hiz);
  lcd.setCursor(4,0);lcd.print(mesafe);lcd.print("mm");
  lcd.setCursor(9,0);lcd.print(bekleme);lcd.print("sn");
  counter=0;

}

Try the AccelStepper library that allows to limit not only the maximum step rate but also the maximum acceleration.

i know accel library but i think mine is more simple. i dont want to complex movement. in this case why accel library better?

Most likely, you have not set the current limit correctly on the A4988 driver. If you have a genuine Pololu driver, follow this video: https://www.pololu.com/blog/484/video-setting-the-current-limit-on-pololu-stepper-motor-driver-carriers

If you have one from a different manufacturer, then you need to know the value of the current sense resistor on the board, in order to set the current limit properly.

NOTE: the A4988 can provide no more than 1 Ampere per winding, or it will overheat and shut down.

Why not connect the motor coils of the two motors in series,
and drive both of them with one driver.
Leo..

Read what I wrote. Stepper motors are not that simple to use.

Makes it hard to move both to their initial position.

Loosing steps happens when you try and move the motor too fast, either when moving or when trying to reverse the direction when you don't give the motor enough time to fully stop before setting off in the reverse direction.

Accelerating to the final speed allows a higher speed to be achieve, but you should also decelerate when bringing it to a stop.

i made ref voltage 0.68 volt as mantioned here:

https://lastminuteengineers.com/a4988-stepper-motor-driver-arduino-tutorial/

2 driver has same ref voltage but one of them became hotter than the other

that would be very good. but i am thought that 1 driver doesnt have sufficent amper for 2 motors. am i wrong? because 17HS3401 step moter need 1.3 amps and a4988 max power 2 amp.

oh do u mean that library makes something diffrent with manuel drive. i didnt know that. i will try it thank you.

i want to learn this but i dont have a good documentation. could you give me more details to solve this problem or documents? thank you.

No, it does not. If that is the motor rating, that is the maximum steady state current allowed, per winding.

i made ref voltage 0.68 volt as mantioned here

That may not be correct for your motor driver. The correct setting depends on the current sense resistor value.

What is the resistance value of the current sense resistor on your A4988 modules? Post a clear, focused picture of the module.

Hi, @obyilmaz .

Due to the structure, steppers cannot be controlled by simply providing a command voltage, unlike DC motors.

Please see this wiki.
Stepper motor - Wikipedia
Steppers are rotated by attracting teeth of the electromagnet turn on and the nearest teeth of the gear-shaped iron rotor. If the next electromagnet is turned on before the electromagnet attracts the teeth, the stepper will not rotate properly.
So we should control with acceleration to be first speed slowly.

The stepper acceleration control document is below.
Acceleration and deceleration of stepping motors | Engineering | Nippon Pulse Motor Co., Ltd.
Specifically, start with a signal of sufficiently broad pulses and accelerate by gradually narrowing the interval.

Creating such controls from scratch can be daunting in many cases, so I recommend using libraries.
Libraries include AccelStepper and MobaTools.
For sequential control, AccelStepper should be fine.

Suppose you rotate the stepper slowly enough but miss the angle. In that case, you may need to look for another problem, such as overheating the driver.
If you could include a schematic or a photo of the actual product, I can give you better advice.

I hope this helps you.

Two coils in series means twice the voltage, but the same current.
Just make sure the A4988 has sufficient supply voltage for the torque at the speed you need.
12volt or 24volt, or an old 19volt laptop supply would be ok.
Leo..

Try http://www.thebox.myzen.co.uk/Workshop/Motors_3.html
for uni-pole motors and
http://www.thebox.myzen.co.uk/Workshop/Motors_4.html
For bi-polar motors
For a look at the two types of stepping motors, and how they work.