Overheating + Microstepping

Hello all,

I'm writing a code to control some stepper motors with Arduino. I have two issues so far.

Issue 1: overheating
I have written two codes: one using the AccelStepper library and another one using the EasyDrivers library, since these are the drivers that I'm using. When using the EasyDrivers library, the motors tend to overheat after some being run for a while, but they cool down pretty quickly when they stop, even connected to the power supply. However, when I use the AccelStepper library they overheat A LOT and VERY quickly, and they won't cool down unless they are completely disconnected. I must say, they won't even move using AccelStepper. They just overheat once the program is loaded into the board. I will leave both codes at the end of the question.

Issue 2: microstepping and lack of accuracy (only tested with the EasyDrivers library)
I want to use the motors with full step, not microstepping. According to the datasheet that is also attached here, when used in full step, they should take 20 step to do a whole turn (right?), that means I would have 18degrees/step. However, I find that with the code that I have written, I need around 5000 steps for one turn.
Also, while testing this, I realized that there is a big lack of consistency with the steps sent and the angle moved. I mean: for 5000 steps sometimes they move 360deg, others 347deg, others 372deg, without an apparent pattern.

My setup is:

  • Arduino UNO board
  • BigEasy drivers
  • Faulhaber Stepper motors AM1020SB009008
  • Power supply with 12V

As far as I understand, the voltage provided to the motors by the drivers is either 3.3V or 5V (I have chosen 5V). I have regulated the current to the minimum that I need for the motors to move, although it is true that these drivers don't allow a very accurate control of the current sent.

Here are the codes:

  • Using EasyDrivers library:
#include <AH_EasyDriver_long.h>
#include <SoftwareSerial.h>

#include <stdio.h>
#include <stdlib.h>
 
 
//sending the characters via sc
const byte numChars = 32;    //number of characters per piece of info
char receivedChars[numChars];
char tempChars[numChars];   //temporary array for use when parsing

#define MS1 3
#define MS2 4

long m1steps = 0.0;
long m2steps = 0.0;
long m3steps = 0.0; 
long m4steps = 0.0;

float speedrpm = 170;

boolean newdata = false;


//AH_EasyDriver(int RES, int DIR, int STEP, int MS1, int MS2, int SLP, int ENABLE, int RST);
AH_EasyDriver m1stepper(20,6,7,MS1,MS2,2);   //initialize with the basics functions 
                                          //MS1, MS2 and SLP control microstepping 
                                          //RES is resolution per full revolve
AH_EasyDriver m2stepper(20,8,9,MS1,MS2,2); 
AH_EasyDriver m3stepper(20,10,11,MS1,MS2,2); 
AH_EasyDriver m4stepper(20,12,13,MS1,MS2,2); 

                                          

//add the rest of the drivers (when i have them)
                                        
void setup() {

  Serial.begin(9600);                  //initialize sc
  Serial.println("Arduino is ready");
  
  pinMode(MS1, OUTPUT);
  pinMode(MS2, OUTPUT);
  digitalWrite(MS1, LOW);
  digitalWrite(MS2, LOW);

  m1stepper.resetDriver();              
  m1stepper.enableDriver();           
  //m1stepper.setMicrostepping(0);        // 0 -> Full Step                                
                                        // 1 -> 1/2 microstepping
                                        // 2 -> 1/4 microstepping
                                        // 3 -> 1/8 microstepping
  m1stepper.setSpeedRPM(speedrpm);           // set speed in RPM, rotations per minute
//  m1stepper.setSpeedHz(100);            

  m2stepper.resetDriver();
  m2stepper.enableDriver();
  //m2stepper.setMicrostepping(0);
  m2stepper.setSpeedRPM(speedrpm);

  m3stepper.resetDriver();
  m3stepper.enableDriver();
  //m3stepper.setMicrostepping(0);
  m3stepper.setSpeedRPM(speedrpm);
  
  m4stepper.resetDriver();
  m4stepper.enableDriver();
  //m4stepper.setMicrostepping(0);
  m4stepper.setSpeedRPM(speedrpm);
  
 
}

void loop() {
  
  receive();
  if (newdata == true) {
    strcpy(tempChars, receivedChars);  //this copies the values in recerivedchars into tempchars (string) for a temporary copy
    parsedata();
    showpd();  //show parsed data
    newdata = false;
    
    m1stepper.sleepOFF();                 
    m1stepper.move(-m1steps);      //movement of the motor1     
    m1stepper.sleepON();

    m2stepper.sleepOFF();                 
    m2stepper.move(-m2steps);         
    m2stepper.sleepON();

    m3stepper.sleepOFF();                 
    m3stepper.move(-m3steps);         
    m3stepper.sleepON();

    m4stepper.sleepOFF();                 
    m4stepper.move(-m4steps);       
    m4stepper.sleepON();

  }

}

//=======functions======

//receiving (and stop receiving) the data
//the data needs to be sent as <m1steps,m2steps,m3steps,m4steps>
void receive() {
  static boolean rip = false;  //receive in process
  static byte ndx = 0;
  char startmarker = '<';      //start of the reading 
  char endmarker = '>';        //end of the reading
  char rc;

  while (Serial.available() > 0 && newdata == false) {  //check to see if anything is available in the serial receive buffer
    rc = Serial.read();                                 // we add to the array the characters until the endmarker
    if (rip == true) {
      if (rc != endmarker) {
        receivedChars[ndx] = rc;
        ndx++;
        if (ndx >= numChars) {
          ndx = numChars - 1;
        }
      } else {
        receivedChars[ndx] = '\0';  //terminate the string
        rip = false;
        ndx = 0;
        newdata = true;
      }
    } else if (rc == startmarker) {
      rip = true;
    }
  }
}

//split the data into the different parts
//four sets of data in float 

void parsedata() {
  char* strtokindx; //use as an index for the strtok funtion

  strtokindx = strtok(tempChars, ",");  //get the first part of the string
  m1steps = atol(strtokindx);           //converts this to a float
  
  strtokindx = strtok(NULL, ",");  //continues where the previous call left
  m2steps = atol(strtokindx);

  strtokindx = strtok(NULL, ",");  //continues where the previous call left
  m3steps = atol(strtokindx);

  strtokindx = strtok(NULL, ",");  //continues where the previous call left
  m4steps = atol(strtokindx);
}


//show what we have received the characters (confirmation of arrival and movement of the motors)
void showpd() {  //show parsed data
  Serial.print("m1steps: ");
  Serial.print( m1steps);
  Serial.print("; m2steps: ");
  Serial.print( m2steps);
  Serial.print("; m3steps: ");
  Serial.print( m3steps);
  Serial.print("; m4steps: ");
  Serial.print( m4steps);
  Serial.println();
}

  • Using AccelStepper library:
#include <SoftwareSerial.h>
#include <AccelStepper.h>

//serial communication 
const byte numChars = 32;  //number of characters per piece of info
char receivedChars[numChars];
char tempChars[numChars];  //temporary array for use when parsing

//pin def
const int DIR1 = 6;
const int STP1 = 7;
const int DIR2 = 8; 
const int STP2 = 9;
const int DIR3 = 10; 
const int STP3 = 11;
const int DIR4 = 12; 
const int STP4 = 13;


float m1steps = 0.0;
float m2steps = 0.0;
float m3steps = 0.0;
float m4steps = 0.0;

float speedrpm = 150;

boolean newdata = false;


AccelStepper m1stepper(AccelStepper::DRIVER, STP1, DIR1);
AccelStepper m2stepper(AccelStepper::DRIVER, STP2, DIR2);
AccelStepper m3stepper(AccelStepper::DRIVER, STP3, DIR3);
AccelStepper m4stepper(AccelStepper::DRIVER, STP4, DIR4);


//
void setup() {

  Serial.begin(9600);
  Serial.println("Arduino is ready");

  //m1stepper.setAcceleration(1);
  m1stepper.setMaxSpeed(10);
  //m2stepper.setAcceleration(1);
  m2stepper.setMaxSpeed(10);
  //m3stepper.setAcceleration(1);
  m3stepper.setMaxSpeed(10);
  //m4stepper.setAcceleration(1);
  m4stepper.setMaxSpeed(10);

}

void loop() {

  receive();
  if (newdata == true) {
    strcpy(tempChars, receivedChars);  //this copies the values in recerivedchars into tempchars (string) for a temporary copy
    parsedata();
    showpd();  //show parsed data
    newdata = false;
  }

  m1stepper.moveTo(m1steps);
  m1stepper.run();
  m2stepper.moveTo(m2steps);
  m2stepper.run();
  m3stepper.moveTo(m3steps);
  m3stepper.run();
  m4stepper.moveTo(m4steps);
  m4stepper.run();

}

//======= define the used functions======

//receiving (and stop receiving) the data
void receive() {
  static boolean rip = false;  //receive in process
  static byte ndx = 0;
  char startmarker = '<';  //character that will mark the start of the reading by the serial monitor (i need to send the characters like that from labview)
  char endmarker = '>';    //the same but with the end of the reading
  char rc;

  while (Serial.available() > 0 && newdata == false) {  //check to see if anything is available in the serial receive buffer
    rc = Serial.read();                                 // we add to the array the characters until the endmarker
    if (rip == true) {
      if (rc != endmarker) {
        receivedChars[ndx] = rc;
        ndx++;
        if (ndx >= numChars) {
          ndx = numChars - 1;
        }
      } else {
        receivedChars[ndx] = '\0';  //terminate the string
        rip = false;
        ndx = 0;
        newdata = true;
      }
    } else if (rc == startmarker) {
      rip = true;
    }
  }
}

//split the data into the different parts -> depending in how many characters and what kind of characters we are sending
//this function will change
//we are getting in principle 4 sets of steps data (although we will try first with two) that are supposed to be float type
//
void parsedata() {
  char* strtokindx; //use as an index for the strtok funtion

  strtokindx = strtok(tempChars, ",");  //get the first part of the string
  m1steps = atof(strtokindx);           //converts this to a float
  
  strtokindx = strtok(NULL, ",");  //continues where the previous call left
  m2steps = atof(strtokindx);

  strtokindx = strtok(NULL, ",");  //continues where the previous call left
  m3steps = atof(strtokindx);

  strtokindx = strtok(NULL, ",");  //continues where the previous call left
  m4steps = atof(strtokindx);
}


//show what we have received (that serves as a confirmation that we did receive it or at least i think and hope so)
void showpd() {  //show parsed data
  Serial.print("m1steps: ");
  Serial.print( m1steps);
  Serial.print("; m2steps: ");
  Serial.print( m2steps);
  Serial.print("; m3steps: ");
  Serial.print( m3steps);
  Serial.print("; m4steps: ");
  Serial.print( m4steps);
  Serial.println();
}

And lastly, the technical specifications of the motors:
EN_AM1020_FPS.pdf (237.2 KB)

This is a very long question, so thank you very much in advance!

Please post a link to the motor datasheet, and tell us what you set for the current limit on the motor driver.

Steppers are designed to run hot (typically up to 80 degrees C).

it is true that these drivers don't allow a very accurate control of the current sent.

Actually, they do. You probably don't understand how to set it correctly, so check the motor driver data sheet for instructions. This incorrect statement reinforces my suspicion.

the voltage provided to the motors by the drivers is either 3.3V or 5V (I have chosen 5V).

That means simply you are trying to go too fast and the motor is skipping pulses.

Bad idea, because then you can't drive them very fast.
Did you know that a stepping motor draws more current when it is stationary. When they move they draw less current.

I think the big problem here is that nether of the two methods you are using is right for a stepping motor.

A stepping motor needs as high a voltage as you have and then needs a driver that will limit the current to the required level. The high voltage makes sure the current gets into the coils quickly, but then they do not get too much current.
You basically need a stepping motor driver, the ones from pololu are good ones see Pololu - Stepper Motor Drivers.

Does this project have a practical use or are you just exploring how to (or rather how not to) drive stepping motors?

Let me give a commercial for-instance. I have the remains of a test set we used to test a commercial product that used two stepper motors. The product was canceled in 2007-2008 recession.

The stepper motors are factory labeled as 4.2 volts. The commercial product used 42 volt power supplies for the stepper motors. The product was used continuously in apartment building construction and never failed.

So do not be afraid to use up to 10X the voltage rating of the stepper, BUT limit the current to factory specifications.

1 Like

"Status: Rationed"
It seems the likelihood of any recovery is remote.

You can get them from other places if you know the model to search from. Anyway rationed means that there is a limit on the number you can buy, not that you can't buy any.

Here is a list of what status words mean what:-
https://www.pololu.com/product-status

Motor voltage is not as relevant with a "chopper" drive as is current, how do you have the current set? Looks like it should be set to 90 ~ 180mA.

I will try to go slower, then, and see what happens.
I really would rather don't change the drivers thought...

It has a practical use, it's part of my education

I know that the drivers have a current regulator, but I don't know how to measure the exact current that I'm sending for these drivers in particular... Any suggestion?
Why is it incorrect the statement about the driver's voltage?

The Big Easy driver uses the A4988 IC. The datasheet explains how to set the current limit, as do the instructions for the Big Easy driver. Pololu also has a video showing how to set the current limit for the A4988, for their motor drivers.

It is very important to set the current limit correctly.

Why is it incorrect the statement about the driver's voltage?

Stepper motors are current driven, not voltage driven. The A4988 requires that the motor power supply voltage be 8V or greater.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.