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!