Nema 17 stepper w/encoder+driver index off 2 degrees on startup and vibrations

Hi, I have an indexing application, when I start up the Arduino 5V Pro Mini and electronics
the closed loop NEMA 17 stepper motor automatically rotates and is off by 2 degrees on startup.
Depending on which way the plate is slightly oriented towards it’ll either rotate 2 degrees to the clockwise direction or counterclockwise direction.
I’m using a NEMA 17 stepper w/encoder with an HBS57 driver.

There is no coupling in between the plate and motor. The motor shaft d-cut has a set screw against it that causes the plate to index with it.

I know for sure that my code is not causing this but I will post anyways for reference.
I’m using the code to get it to home back to zero at the beginning of the cycle but want to avoid this.

The other issue is after the plate indexes there are slight back and forth oscillations of the motor shaft that causes the indexing plate to vibrate or oscillate slightly continuously until I place my finger on it to stop it.
I noticed slight improvements in vibrations reductions with micro stepping but it’s still happening.
I am able to adjust the micro steps via the motor’s driver.
I also adjust the number of pulses in the code to account for 90 degrees of rotation.

The default stepper setting of 400 steps per revolution are what is being used currently.

Could it be the delayMicroseconds timing for stepper pulses that are causing these vibrations to occur?

/*
  Cycle steps:
  Two capacitive sensors are touched
  Stepper motor rotates 90 degrees
  Solenoid activates
  Solenoid deactivates
  Stepper motor rotates 90 degrees

  Microsteps Wanted = (Wanted Angle/360) * Driver Micro Steps Setting

  Micro Steps             Micro Steps for
  Setting for Driver      Wanted Angle Movement of 90 degrees
  400                     100
  800                     200
  1600                    400
  3200                    800
  6400                    1600
  12800                   3200
  25600                   6400
  51200                   12800
  1000                    250
  2000                    500
  4000                    1000
  5000                    1250
  8000                    2000
  10000                   2500
  20000                   5000
  40000                   10000

  Micro Steps for 1 Degree Angle Movement based on 400 Micro Steps
  1.11111111111111
  2.22222222222222
  4.44444444444444
  8.88888888888889
  17.7777777777778
  35.5555555555556
  71.1111111111111
  142.222222222222
  2.77777777777778
  5.55555555555556
  11.1111111111111
  13.8888888888889
  22.2222222222222
  27.7777777777778
  55.5555555555556
  111.111111111111
*/

// defines pins numbers
const int stepPin = 3;
const int dirPin = 4;
const int enaPin = 5;

// When Sig Output is high, touch sensor is being pressed
#define ctsLeftPin 11 // Pin for capacitive touch sensor
#define ctsRightPin 12

int ledPin = 13; // pin for the LED
int SSRPin = 10; // pin for Solid State Relay

void setup()
{
  Serial.begin(9600);

  // Sets pins as Outputs
  pinMode(stepPin, OUTPUT);
  pinMode(dirPin, OUTPUT);
  pinMode(enaPin, OUTPUT);

  pinMode(ledPin, OUTPUT);
  pinMode(SSRPin, OUTPUT);
  pinMode(ctsLeftPin, INPUT);
  pinMode(ctsRightPin, INPUT);

  digitalWrite(enaPin, LOW);
  digitalWrite(dirPin, LOW); // Enables the motor to move in a CCW direction

  delay(2000);

  // 2 degree offset needed in counterclockwise direction to home indexer straight
  for (int x = 0; x < 2; x++)
  {
    digitalWrite(stepPin, HIGH);
    delayMicroseconds(4000);
    digitalWrite(stepPin, LOW);
    delayMicroseconds(4000);
  }
}

void loop()
{
  int ctsLeftValue = digitalRead(ctsLeftPin);
  int ctsRightValue = digitalRead(ctsRightPin);

  if (ctsLeftValue && ctsRightValue == HIGH)
  {
    digitalWrite(enaPin, LOW);
    digitalWrite(dirPin, HIGH); // Enables the motor to move in a CW direction

    {
      // Makes pulses for making 90 degree rotation
      for (int x = 0; x < 100; x++)
      {
        digitalWrite(stepPin, HIGH);
        delayMicroseconds(4000);
        digitalWrite(stepPin, LOW);
        delayMicroseconds(4000);
      }
      delay(1000);

      digitalWrite(ledPin, HIGH);
      digitalWrite(SSRPin, HIGH);
      Serial.println("TOUCHED");

      delay(2000);

      digitalWrite(ledPin, LOW);
      digitalWrite(SSRPin, LOW);
      Serial.println("TOUCHED");
    }
  }
  else
  {
    digitalWrite(ledPin, LOW);
    digitalWrite(SSRPin, LOW);
    Serial.println("not touched");
  }
}

Well... I did a little bit of experimenting.

I completely removed the microsecond delay timings from the pulses sent to the motor.

As soon as I started up the machine, the motor shaft and plate started vibrating really fast.

I've changed microstepping to 6400 pulses and lowered the delayMicroseconds timing to 1000.
If I go any lower i.e. 500 it doesn't move at all.

I'm suspecting the back and forth turning of the shaft/plate has something to do with the encoder.
I wonder if using an open loop stepper will fix the issue?

I can't understand the problem from your description. Can you post a diagram that shows the mechanical arrangement.

Have you tried making the motor move at a very much slower speed - such as 10 times slower?

Like any other motor a stepper motor needs to be accelerated to higher speeds if it is not to miss steps.

...R
Stepper Motor Basics
Simple Stepper Code
Simple acceleration code.

also look up the AccelStepper library

Hi, okay I'll post a diagram.

Thanks for the links.

I don't think I'm missing/skipping any steps since I'm not spinning too fast and have an encoder.
However, I'm wondering if the shaking has to do with the acceleration of the plate even though it's indexing pretty slowly.

I am rotating in intervals of 90 degrees.
When I first start the motor, it seems to adjust itself to what I'm presuming is the home position for the motor based on the encoder.

I've attached a gif of what it's doing when I start it up sometimes.
It also tends to do this after completing a 90 degree rotation.
However, after I
I don't really need to spin at high rpms.

I've also attached a spreadsheet for calculating what type of RPMs to expect based on pulses and microstep settings.

I based it on a formula I found on the forums but can't seem to find that post again.
I was a bit doubtful of it so I found another link and used that formula and my results were different.
I used 1/seconds delay for calculating frequency.
https://www.se.com/sa/en/faqs/FA337686/

So I'm a bit stuck and confused on RPM calculations based on what I've been googling around.
Lot's of sites have calculators but no display of formulas.

I can't attach the spreadsheet it gave me a security error.
I've attached the .gif movement though.

Edit....can't attach .gif either. Some security error.

I don't know if the Forum accepts GIF files but it certainly accepts JPG and PNG files. However you must make sure they don't include any EXIF data from a camera or phone.

See this Simple Image Posting Guide

...R

Thanks. I've posted images before.
I wanted to include the .gif file to show the erratic movement I'm getting.
It's the closest thing to a video that I can post since the file attachment limit size is 2 mb. My next best option would be to include a Dropbox link, but I'd rather have it on the forum site so that people can view it permanently in case I delete it from my Dropbox folder.

I wanted to attach a spreadsheet that I thought could be useful for others to download too regarding motor RPMs and setting proper Microseconds intervals.
It's too bad the forum doesn't allow attachment of .xls or .ods (libreoffice version of excel) files.

I have attached a screenshot instead.

I have two formulas so far but I get two different sets of results that are slightly offset. I know it has to do with the step angle being used but still having trouble figuring out why the results are different

One formula I found on the forum.

RPM = 60/(Default motor steps per rev * Microstep * Number of coils * Microseconds interval (in seconds))

The other I found on the Schneider electric website.

Formula for calculating stepping motor speed.

Below is the RPM formula for steppering motor drives that use pulse signals to create motion.
RPM = a/360 * fz * 60

RPM = Revolutions per minute.
“a” = step angle
“fz” = pulse frequency in hertz

Example 1: Drive step resolution is set for 1000 steps per revolution.
Find step angle: 360 (degrees of rotation) divided by 1000 (steps per revolution) = .36 (degrees of rotation per step)
With input frequency of 1000hz, .36 / 360 * 1000 * 60 = 60 rpm

Microsteps and rpm chart attached again for clarity.
Hopefully it can be zoomed in further and be clearer with less text in this post.

When first powered, any stepper will go to the first real notch in the armature design. Is that your problem?

Otherwise, the voltage and current rating of your power and controller mat not be set at maximum usable values.

Paul

knightridar:
Thanks. I've posted images before.
I wanted to include the .gif file to show the erratic movement I'm getting.
It's the closest thing to a video that I can post since the file attachment limit size is 2 mb

The simplest way is to post a link to a YouTube video - a very short one, please

I wanted to attach a spreadsheet that I thought could be useful for others to download too regarding motor RPMs and setting proper Microseconds intervals.

Isn't the relationship between the step interval and the motor speed sufficiently simple not to need a spreadsheet?

...R

Maybe that is part of the problem.
Since I couldn't attach a video .gif file here are images to clarify the indexing issue.

I'm using a 24V, 5A power supply.
The only other things I'm powering with them is a solenoid and Arduino Pro Mini.
I was never able to modify any driver settings via software.
The pulse/rev is currently set to 6400.

index plate with nema 17 shaft.png

index plate with nema 17 shaft.png

Please describe what we are intended to see in the first two pictures. The third picture just seems to be a view of your driver and connections which is not useful,

In the first picture I think I see a few aluminium cylinders standing in some sort of tray. There are two things with green lights either side of the tray.

The second picture seems to be the indentations in the tray into which the cylinders are placed. One of the indentations seems to have a channel cut in its bottom surface.

It is impossible to tell the diameter of the cylinders but my wild guess is about 50mm - the sort of guess you might make at a church fete hoping to win a mars bar.

...R

Hi, thanks for the Youtube idea.
Here is a link to see what is happening.

Basically two hand touch sensors are touched.
That activates the motor to index 90 degrees.
Then a cylinder comes down and presses on parts.

You can see as soon as I powered up the machine the plate rotated back and forth.
Sometimes it does this after indexing too but I’ve changed the code that I’m using in this video.
Prior to this it was indexing slightly by itself before actually starting the cycle in my code.
This ruins my indexing.

Basically at 6400 pulses (what driver is set to) I should be getting 90 degrees rotation with 1600 steps.
However it has rotated several times and activated the press several times for touching both capacitive sensors only once. This was not my intent but I will take a look at the code more carefully.
It should only rotate 90 degrees and activate the solenoid once for every time that both sensors are touched.

/*
  Cycle steps:
  Two capacitive sensors are touched
  Stepper motor rotates 90 degrees
  Solenoid activates
  Solenoid deactivates
  Stepper motor rotates 90 degrees

  Microsteps Wanted = (Wanted Angle/360) * Driver Micro Steps Setting

  Micro Steps             Micro Steps for
  Setting for Driver      Wanted Angle Movement of 90 degrees
  400                     100
  800                     200
  1600                    400
  3200                    800
  6400                    1600
  12800                   3200
  25600                   6400
  51200                   12800
  1000                    250
  2000                    500
  4000                    1000
  5000                    1250
  8000                    2000
  10000                   2500
  20000                   5000
  40000                   10000

  Micro Steps for 1 Degree Angle Movement corresponding to microstep settings mentioned above
  1.11111111111111
  2.22222222222222
  4.44444444444444
  8.88888888888889
  17.7777777777778
  35.5555555555556
  71.1111111111111
  142.222222222222
  2.77777777777778
  5.55555555555556
  11.1111111111111
  13.8888888888889
  22.2222222222222
  27.7777777777778
  55.5555555555556
  111.111111111111
*/

// defines pins numbers
const int stepPin = 3;
const int dirPin = 4;
const int enaPin = 5;

// When Sig Output is high, touch sensor is being pressed
#define ctsLeftPin 11 // Pin for capacitive touch sensor
#define ctsRightPin 12

int ledPin = 13; // pin for the LED
int SSRPin = 10; // pin for Solid State Relay

void setup()
{
  Serial.begin(9600);

  // Sets pins as Outputs
  pinMode(stepPin, OUTPUT);
  pinMode(dirPin, OUTPUT);
  pinMode(enaPin, OUTPUT);

  pinMode(ledPin, OUTPUT);
  pinMode(SSRPin, OUTPUT);
  pinMode(ctsLeftPin, INPUT);
  pinMode(ctsRightPin, INPUT);

  digitalWrite(ledPin, LOW);
  digitalWrite(SSRPin, LOW);
  Serial.println("Solenoid Inactive");

  digitalWrite(enaPin, LOW);
  digitalWrite(dirPin, LOW); // Enables the motor to move in a CCW direction

  delay(1000);

  // 2 degree offset needed in counterclockwise direction to home indexer straight
  /*for (int x = 0; x < 18; x++)
  {
    digitalWrite(stepPin, HIGH);
    delayMicroseconds(10000);
    digitalWrite(stepPin, LOW);
    delayMicroseconds(10000);
  }*/
}

void loop()
{
  int ctsLeftValue = digitalRead(ctsLeftPin);
  int ctsRightValue = digitalRead(ctsRightPin);

  digitalWrite(ledPin, LOW);
  digitalWrite(SSRPin, LOW);
  Serial.println("Solenoid Inactive");

  if (ctsLeftValue && ctsRightValue == HIGH)
  {
    digitalWrite(enaPin, LOW);
    digitalWrite(dirPin, HIGH); // Enables the motor to move in a CW direction
    {
      // Makes pulses for making 90 degree rotation
      for (int x = 0; x < 1600; x++)
      {
        digitalWrite(stepPin, HIGH);
        delayMicroseconds(8000);
        digitalWrite(stepPin, LOW);
        delayMicroseconds(8000);
      }
      delay(1000);

      digitalWrite(ledPin, HIGH);
      digitalWrite(SSRPin, HIGH);
      Serial.println("Solenoid Activated");

      delay(2000);

      digitalWrite(ledPin, LOW);
      digitalWrite(SSRPin, LOW);
      Serial.println("Solenoid Deactivated");
    }
  }
  else
  {
    digitalWrite(ledPin, LOW);
    digitalWrite(SSRPin, LOW);
    Serial.println("Solenoid Deactivated");
  }
}

How do you know the offset is EXACTLY 2 degrees? I think you will need to fix the offset on the mechanical side, maybe with a slotted mounting bracket that can be rotated for precise alignment then clamped down.

My wild guess is that those touch switches are not behaving as you think and may be the cause of the rough jiggles. What happens if you write a short program that does nothing except rotate the plate 1600 steps every time the Arduino re-starts.

You MUST get rid of the unwanted jiggles before you can deal with any other problem.

Separately...

this code

digitalWrite(stepPin, HIGH);
delayMicroseconds(8000);
digitalWrite(stepPin, LOW);
delayMicroseconds(8000);

would make more sense written like this

digitalWrite(stepPin, HIGH);
delayMicroseconds(10);                   // most stepper drivers just need a short pulse
digitalWrite(stepPin, LOW);
delayMicroseconds(16000);             // this value is the interval between steps

...R

Regarding the two degrees measurement. It has been ages since I used a protractor and I didn't have one on me so I used the compass on my phone. I put the phone against the flat side edge of the base plate. Then I put it against the side of the index plate and got a 2 degree offset.

I'll try the mentioned code. Last time I used low timings near 500 microseconds for both high and low the motor just stayed stalled. I can't remember what micro step setting the driver was at.

knightridar:
I'll try the mentioned code. Last time I used low timings near 500 microseconds for both high and low the motor just stayed stalled. I can't remember what micro step setting the driver was at.

I have not suggested any alteration in the overall timing.

The important part of my Reply #14 was the suggestion to try testing a very simple program but you have not responded to that.

...R

So I kept only the code that is necessary to index the stepper 90 degrees and I still get jiggling in the beginning and in between indexes.

I’m wondering if it’s an acceleration issue, even though I’m indexing really slow.

I even attempted to unplug the hand touch sensors and still got jiggling.

Video of movement:

Code for reference:

/*
  Cycle steps:
  Stepper motor rotates 90 degrees 4 times

  Microsteps Wanted = (Wanted Angle/360) * Driver Micro Steps Setting

  Micro Steps             Micro Steps for
  Setting for Driver      Wanted Angle Movement of 90 degrees
  400                     100
  800                     200
  1600                    400
  3200                    800
  6400                    1600
  12800                   3200
  25600                   6400
  51200                   12800
  1000                    250
  2000                    500
  4000                    1000
  5000                    1250
  8000                    2000
  10000                   2500
  20000                   5000
  40000                   10000

  Micro Steps for 1 Degree Angle Movement corresponding to microstep settings mentioned above
  1.11111111111111
  2.22222222222222
  4.44444444444444
  8.88888888888889
  17.7777777777778
  35.5555555555556
  71.1111111111111
  142.222222222222
  2.77777777777778
  5.55555555555556
  11.1111111111111
  13.8888888888889
  22.2222222222222
  27.7777777777778
  55.5555555555556
  111.111111111111
*/

// defines pins numbers
const int stepPin = 3;
const int dirPin = 4;
const int enaPin = 5;

void setup()
{
  Serial.begin(9600);

  // Sets pins as Outputs
  pinMode(stepPin, OUTPUT);
  pinMode(dirPin, OUTPUT);
  pinMode(enaPin, OUTPUT);

  digitalWrite(enaPin, LOW);
  digitalWrite(dirPin, HIGH); // Enables the motor to move in a CW direction

  delay(1000);
}

void loop()
{
  // Makes pulses for making 90 degree rotation
  for (int x = 0; x < 1600; x++)
  {
    digitalWrite(stepPin, HIGH);
    delayMicroseconds(10);                   // most stepper drivers just need a short pulse
    digitalWrite(stepPin, LOW);
    delayMicroseconds(16000);             // this value is the interval between steps
  }
  delay(1000);
}

How does it behave if you take the big weights off the turntable?

I would modify the program so it only does a single 90deg movement.

Then I would try a much shorter movement - perhaps 200 steps and see what happens

My guess is that the shudder is the initial part of the 1600 steps - but you need to prove verify that.

...R

Post a link to that stepper & encoder.