Pololu A4988 and SY28STH32-0674A stepper motor weird issues

Hi all!

I’m working on a positioning system with a Pololu A4988 driver and SY28STH32-0674A stepper motor.

I set the Vref to 0.36V, because of this formula:

0.068 x 8 x 0.670 = 0.364

Which, as many of you know, is a value that you can get without the formula (current consumption / 2 gives basically the same value).

The code, posted below, should do those things:

  1. Homing (via limit switch, CW)
  2. Move to Position 1 (CCW)
  3. Wait for an input from Switch 2, 3 or 4 ignoring Switch 1 (because it’s already in position 1)
  4. Move to position X depending on the Switch pressed

That’s it

The problem is that the motor moves very weirdly back and forth, especially on slow speed, it’s jerky and sometimes it just spins to a random position (even if in the serial monitor the position is correct).

I suspect that the motor is missing steps or that (on a very last possibility) there may be some EMF issues.

Wiring seems fine.

Before I dig into the endless pit of EMF problems, please, take a look at the code, maybe there’s something I’m missing or doing wrong!

Thank you!

(And last but not least, if somebody find this code interesting to use, feel free to use and share it!)

#include "AccelStepper.h"

AccelStepper stepperX(1, 8, 9);

#define first_btn 7
#define second_btn 6
#define third_btn 5
#define fourth_btn 4

#define home_switch 3

int first_btn_state = 0;
int second_btn_state = 0;
int third_btn_state = 0;
int fourth_btn_state = 0;

int selected_filter = 0;

long TravelX;
int move_finished = 1;
long initial_homing = -1;

int max_travel_distance = 500;

bool initial_positioning = false;

void setup() {

  Serial.begin(9600);

  while (!Serial) {
    ;
  }

  pinMode(13, OUTPUT);

  digitalWrite(13, HIGH);

  pinMode(home_switch, INPUT_PULLUP);
  pinMode(first_btn, INPUT_PULLUP);
  pinMode(second_btn, INPUT_PULLUP);
  pinMode(third_btn, INPUT_PULLUP);
  pinMode(fourth_btn, INPUT_PULLUP);

  delay(5);

  stepperX.setMaxSpeed(500.0);
  stepperX.setAcceleration(500.0);

  Serial.print("Homing...");

  while (digitalRead(home_switch)) {
    stepperX.moveTo(initial_homing);
    initial_homing--;
    stepperX.run();
    delay(5);
  }

  stepperX.setCurrentPosition(0);
  stepperX.setMaxSpeed(500.0);
  stepperX.setAcceleration(500.0);
  initial_homing = 1;

  while (!digitalRead(home_switch)) {
    stepperX.moveTo(initial_homing);
    stepperX.run();
    initial_homing++;
    delay(5);
  }

  stepperX.setCurrentPosition(0);
  Serial.println("Completed");
  stepperX.setMaxSpeed(500.0);
  stepperX.setAcceleration(500.0);
  delay(500);

}

void loop() {

  if (initial_positioning == false) {
    move_finished = 0;
    TravelX = -30;
    selected_filter = 1;
    stepperX.moveTo(TravelX);
    Serial.print("automatic move to ");
    Serial.println(selected_filter);
    Serial.print("moving to ");
    Serial.println(TravelX);
    delay(500);
    initial_positioning = true;
  }

  first_btn_state = digitalRead(first_btn);
  second_btn_state = digitalRead(second_btn);
  third_btn_state = digitalRead(third_btn);
  fourth_btn_state = digitalRead(fourth_btn);

  if (first_btn_state == LOW && selected_filter != 1 && move_finished == 1) {
    move_finished = 0;
    TravelX = -30;
    selected_filter = 1;
    stepperX.moveTo(TravelX);
    Serial.print("pressed ");
    Serial.println(selected_filter);
    Serial.print("moving to ");
    Serial.println(TravelX);
    delay(500);
  }
  if (second_btn_state == LOW  && selected_filter != 2 && move_finished == 1) {
    move_finished = 0;
    TravelX = -80;
    selected_filter = 2;
    stepperX.moveTo(TravelX);
    Serial.print("pressed ");
    Serial.println(selected_filter);
    Serial.print("moving to ");
    Serial.println(TravelX);
    delay(500);
  }
  if (third_btn_state == LOW && selected_filter != 3 && move_finished == 1) {
    move_finished = 0;
    TravelX = -150;
    selected_filter = 3;
    stepperX.moveTo(TravelX);
    Serial.print("pressed ");
    Serial.println(selected_filter);
    Serial.print("moving to ");
    Serial.println(TravelX);
    delay(500);
  }
  if (fourth_btn_state == LOW && selected_filter != 4 && move_finished == 1) {
    move_finished = 0;
    TravelX = -200;
    selected_filter = 4;
    stepperX.moveTo(TravelX);
    Serial.print("pressed ");
    Serial.println(selected_filter);
    Serial.print("moving to ");
    Serial.println(TravelX);
    delay(500);
  }

  if (TravelX >= -200 && TravelX <= max_travel_distance) {

    if ((stepperX.distanceToGo() != 0)) {

      stepperX.run();

    }

    // non toccare, controlla che sia arrivato a destinazione
    if ((move_finished == 0) && (stepperX.distanceToGo() == 0)) {

      move_finished = 1;
      Serial.println("position reached");
      delay(500);

    }

    Serial.println(stepperX.currentPosition());
  }

}

Please post a link to the datasheet for your stepper motor.

What motor power supply are you using (volts and amps)?

Test your motor with this Simple Stepper Code. And always do initial tests with a very slow step rate.

...R
Stepper Motor Basics

Does AccelStepper set pins 8 & 9 to OUTPUT? Yes. :stuck_out_tongue:

Robin2:
Please post a link to the datasheet for your stepper motor.

What motor power supply are you using (volts and amps)?

Test your motor with this Simple Stepper Code. And always do initial tests with a very slow step rate.

...R
Stepper Motor Basics

That's the motor, I'll try the code now and post the result

PSU is a 12v 16a power supply

UPDATE: after testing the demo code, the results are:

  • int millisbetweenSteps = 15; the motor sweep very smoothly and then stops as coded
  • int millisbetweenSteps = 250; it does work but it's ticking because of the delay, but I guess it's supposed to be like that

Now I'm starting to believe that there's a code issue, however I can't really find anything wrong in the code, at least now!

Or could this be temperature related?

Thank you!

c0rsa1r:
Or could this be temperature related?

Very unlikely.

Go for the lost likely problem - the program.

Have you got one of the AccelStepper example programs to work?

…R

Robin2:
Very unlikely.

Go for the lost likely problem - the program.

Have you got one of the AccelStepper example programs to work?

…R

Yes and unfortunately I see the same problem.

I’m trying to build an hybrid code between the one you posted and mine taking away the accelstepper library.

As of now, the code is not completed at all, I need to understand how to do the homing and create the related positions without the library.

I’ll post it anyway so you can see how I am moving on, any help with the code would be really appreciated, I think I’m very close to the solution…

#define first_btn 7
#define second_btn 6
#define third_btn 5
#define fourth_btn 4

#define home_switch 3

int first_btn_state = 0;
int second_btn_state = 0;
int third_btn_state = 0;
int fourth_btn_state = 0;

int selected_filter = 0;

long TravelX;
int move_finished = 1;
long initial_homing = -1;

int actual_position = 0;

int max_travel_distance = 500;

bool initial_positioning = false;

byte directionPin = 9;
byte stepPin = 8;
int numberOfSteps = 100;
byte ledPin = 13;
int pulseWidthMicros = 20;  // microseconds
int millisbetweenSteps = 15; // milliseconds - or try 1000 for slower steps

void setup() {

  pinMode(13, OUTPUT);
  digitalWrite(13, HIGH);

  Serial.begin(9600);
  Serial.println("Starting StepperTest");

  pinMode(home_switch, INPUT_PULLUP);
  pinMode(first_btn, INPUT_PULLUP);
  pinMode(second_btn, INPUT_PULLUP);
  pinMode(third_btn, INPUT_PULLUP);
  pinMode(fourth_btn, INPUT_PULLUP);

  delay(2000);

  pinMode(directionPin, OUTPUT);
  pinMode(stepPin, OUTPUT);


  /*digitalWrite(directionPin, HIGH);
    for (int n = 0; n < numberOfSteps; n++) {
    digitalWrite(stepPin, HIGH);
    delayMicroseconds(pulseWidthMicros); // this line is probably unnecessary
    digitalWrite(stepPin, LOW);

    delay(millisbetweenSteps);

    }

    delay(3000);


    digitalWrite(directionPin, LOW);
    for (int n = 0; n < numberOfSteps; n++) {
    digitalWrite(stepPin, HIGH);
    // delayMicroseconds(pulseWidthMicros); // probably not needed
    digitalWrite(stepPin, LOW);

    delay(millisbetweenSteps);
    }*/

  //homing

  while (digitalRead(home_switch)) {

    digitalWrite(directionPin, LOW);
    for (int n = 0; n < numberOfSteps; n++) {
      digitalWrite(stepPin, HIGH);
      delayMicroseconds(pulseWidthMicros);
      digitalWrite(stepPin, LOW);
      delay(millisbetweenSteps);

    }
  }

  initial_homing = 1;

  while (!digitalRead(home_switch)) {
    digitalWrite(directionPin, HIGH);
    for (int n = 0; n < numberOfSteps; n++) {
      digitalWrite(stepPin, HIGH);
      delayMicroseconds(pulseWidthMicros);
      digitalWrite(stepPin, LOW);
      delay(millisbetweenSteps);

    }
  }

  actual_position = 0;
  delay(500);

}

void loop() {

  first_btn_state = digitalRead(first_btn);
  second_btn_state = digitalRead(second_btn);
  third_btn_state = digitalRead(third_btn);
  fourth_btn_state = digitalRead(fourth_btn);

  /* if (first_btn_state == LOW && selected_filter != 1 && move_finished == 1) {
     move_finished = 0;
     TravelX = -30;
     selected_filter = 1;
     ///
     digitalWrite(directionPin, HIGH);
     for (int n = 0; n < numberOfSteps; n++) {
       digitalWrite(stepPin, HIGH);
       delayMicroseconds(pulseWidthMicros); // this line is probably unnecessary
       digitalWrite(stepPin, LOW);

       delay(millisbetweenSteps);

     }
     ///
     delay(500);
     move_finished = 1;
    }
    if (second_btn_state == LOW  && selected_filter != 2 && move_finished == 1) {
     move_finished = 0;
     TravelX = -80;
     selected_filter = 2;
     ///
     digitalWrite(directionPin, LOW);
     for (int n = 0; n < numberOfSteps; n++) {
       digitalWrite(stepPin, HIGH);
       delayMicroseconds(pulseWidthMicros); // this line is probably unnecessary
       digitalWrite(stepPin, LOW);

       delay(millisbetweenSteps);

     }
     ///
     delay(500);
     move_finished = 1;
    }
    if (third_btn_state == LOW && selected_filter != 3 && move_finished == 1) {
     move_finished = 0;
     TravelX = -150;
     selected_filter = 3;
     ///
     digitalWrite(directionPin, HIGH);
     for (int n = 0; n < numberOfSteps; n++) {
       digitalWrite(stepPin, HIGH);
       delayMicroseconds(pulseWidthMicros); // this line is probably unnecessary
       digitalWrite(stepPin, LOW);

       delay(millisbetweenSteps);

     }
     ///
     delay(500);
     move_finished = 1;
    }
    if (fourth_btn_state == LOW && selected_filter != 4 && move_finished == 1) {
     move_finished = 0;
     TravelX = -200;
     selected_filter = 4;
     ///
     digitalWrite(directionPin, LOW);
     for (int n = 0; n < numberOfSteps; n++) {
       digitalWrite(stepPin, HIGH);
       delayMicroseconds(pulseWidthMicros); // this line is probably unnecessary
       digitalWrite(stepPin, LOW);

       delay(millisbetweenSteps);

     }
     ///
     delay(500);
     move_finished = 1;
    }
  */

}

c0rsa1r:
Yes and unfortunately I see the same problem.

If that means that you have the same problem with the AccelStepper examples then that is where you need to focus your attention. There is no point trying anything more complicated if you can't get one of the simple examples to work.

Post the example code that you are having trouble with and tell us exactly what happens when you try to run it.

...R

If I run this code, the initial motion, especially on low speed, is jerky and it “stutter” as if something is wrong with the wiring or the motor itself.

Another example code is the continuous rotation one, it does work well only when the motor is spinning at full speed, but it still struggle to start.

I really don’t know what’s wrong because the code that you provided does not act like that! That is really strange!

// Bounce.pde
// -*- mode: C++ -*-
//
// Make a single stepper bounce from one limit to another
//
// Copyright (C) 2012 Mike McCauley
// $Id: Random.pde,v 1.1 2011/01/05 01:51:01 mikem Exp mikem $

#include <AccelStepper.h>

// Define a stepper and the pins it will use
AccelStepper stepper; // Defaults to AccelStepper::FULL4WIRE (4 pins) on 2, 3, 4, 5

void setup()
{  
  // Change these to suit your stepper if you want
  stepper.setMaxSpeed(100);
  stepper.setAcceleration(20);
  stepper.moveTo(500);
}

void loop()
{
    // If at the end of travel go to the other end
    if (stepper.distanceToGo() == 0)
      stepper.moveTo(-stepper.currentPosition());

    stepper.run();
}

c0rsa1r:
If I run this code, the initial motion, especially on low speed, is jerky and it "stutter" as if something is wrong with the wiring or the motor itself.

Another example code is the continuous rotation one, it does work well only when the motor is spinning at full speed, but it still struggle to start.

It's natural for stepper motors to move in obvious steps at slow speed - that's why they are called stepper motors.

Can you make a short YouTube video showing the bounce program working and post a link to it?

...R

Robin2:
It's natural for stepper motors to move in obvious steps at slow speed - that's why they are called stepper motors.

Can you make a short YouTube video showing the bounce program working and post a link to it?

...R

I found the issue. It is not the code! It was the limit switch! Whenever the stepper rotates and tryies to push the limit switch, it simply can not (I suppose that more strength is required) and it does act weirdly, like going back and forth randomly at full speed. If I try to upload new code, or reupload the same code, or anything, it will just "stay" mad for about 10 minutes (don't know why!). However, if I let it sit for 10 minutes, then upload the simple code, it works as intended!

Really, I don't know why this happen, and I don't know if that's the issue. As of now, I've been able to replace the switch with a waaay softer one, uploaded the old code and the new one, no issues so far, at all!

If someone could provide an explanation it would be awesome!