I am using an Arduino mega 2560 rev3 board together with an Arduino CNC shield and stepper motor driver A4988 to run (for now) only one stepper motor (Nema 17 39.5 mm-1.5A). I want to use them to first get some experience and to build up a 3D printer machine later.
But the problem is that when I connect everything, the stepper motor runs only when I touch the STEP pin of the driver. I have spent a lot of time figuring out what the issue is and how to solve it, but I still couldn’t succeed. Would appreciate it a lot if someone could help me solve this issue.
More about the issue. What I find quite strange is that the stepper motor spins even when no code is running. I.e., I just connect the Arduino mega board to my laptop, connect the power supply of (19 V) to the CNC shield, insert the A4988 driver and touch the STEP pin → stepper motor spins even when no code is running.
Additionally, I thought the problem may be that the A4988 drivers are out of the order. So, I bought another driver DRV8825 which can handle a bit more current, but it did not solve the problem.
Finally, I want to use Python programming to control the stepper motor(s).
In the first image, the pin that I’m pointing to is the STEP pin.
The input pins of A4988 are high impedance ( apart from some special with pullup/pulldown resistors). If you don't connect them to a low impedance output, you can transfer anything with your fingers ( as an antenna ) to it.
Is a sketch running with the correct step pin configured as OUTPUT when you touch the step pin?
The CNC shield doesn't have any pullup or pull down resistors. By default, the Arduino pins are set to input, and with nothing driving the pin it is quite easy to inject stray noise, for example from a finger.
But I wouldn't worry about that, as you are going to have code running which will drive the STEP and DIR pins.
In that case I guess you will not be using the Mega but a different board?
If you want to test with the Mega, you could try the AccelStepper library, but maybe not much point if want to use Python.
If I upload a sketch to the board or even when running without any sketch uploaded, the stepper motor keeps spinning. I am very new to Arduino ide so it may be that the sketch I upload is not doing what I expect. I have looked up a good source to get some guidance on how to communicate between Python and Arduino but I couldn't find any useful thing. Do you know a source where I can find more information on how to use Python with Arduino for a stepper motor?
You said it ONLY ran if you touched the STEP pin
Now you are saying it always runs no matter what.
So which is true?
Can't help if I don't know exactly what the problem is.
By using Python, I mean I want to do most of the code in Python and send the outcome to the Arduino IDE sketch that I have uploaded on my board to move the stepper motor. So, the communication is between Arduino and Python. I already have a basic code using Pyserial that sends data to my Arduino board and receives data back, but I have not been able to change the behaviour of the stepper motor to just spin when data is received and stop when you are at the exact location. When I feed the CNC shield, the stepper motor starts rotating.
I have used <Stepper.h> in my Arduino sketch. I will try AccelStepper to see if things change. I will update you on this.
Please show the sketch. Don't forget code tags when posting the sketch as described here:
There is always a sketch running - at least the one you uploaded last. The Arduino doesn't loose it when you switch the Arduino off.
I don't think you can program the Mega with pyton. C++ is the language for arduino. There are some special boards then can use Micropython, but I don't know anything about these.
The step requires a voltage level transition (low to high) to for each step. By putting your finger on that pin you are injecting noise or 60 cycle frequencies into the pin. The frequency is enough to toggle the step pin, so the stepper steps. Look at your code to see that the step pin toggles high to low etc.
Have you written a simple bit of C++ Arduino IDE code to prove you have control of the stepper?
You need to get back to basics and prove your hardware before adding complexity of python and PC comms.
Can you please post your code that you are using at the moment.
Are you sure you are sending commands to active the correct stepper driver of the three?
I managed to make the stepper motor run when receiving a command from Python. And for now, everything works well except that the stepper does not move in the reverse direction. I use the following code:
#include <AccelStepper.h>
// AccelStepper stepperX(AccelStepper::FULL4WIRE, 2, 5);
// AccelStepper stepperY(AccelStepper::FULL4WIRE, 3, 6);
// AccelStepper stepperZ(AccelStepper::FULL4WIRE, 4, 7);
// AccelStepper stepperA(AccelStepper::FULL4WIRE, 8, 9);
AccelStepper stepperX(1, 2, 5);
AccelStepper stepperY(2, 3, 6);
AccelStepper stepperZ(3, 4, 7);
AccelStepper stepperA(4, 8, 9);
////////////////////////////////////////
///////////// INITIALIZE //////////////
//////////////////////////////////////
int Steps;
int run_count = 0;
float current_pos = 0.;
int total_num_stps = 0;
int maxspeed = 10000; // Set this to the desired speed
int acceleration = 500000;
////////////////////////////////////////
///////////// END INITIALIZE //////////
//////////////////////////////////////
void setup() {
stepperX.setMaxSpeed(maxspeed);
stepperX.setAcceleration(acceleration);
stepperX.setSpeed(maxspeed);
// stepperY.setMaxSpeed(1000.0);
// stepperY.setAcceleration(500.0);
// stepperZ.setMaxSpeed(1000.0);
// stepperZ.setAcceleration(500.0);
// stepperA.setMaxSpeed(1000.0);
// stepperA.setAcceleration(500.0);
// Set the initial position (optional)
stepperX.setCurrentPosition(0);
// stepperY.setCurrentPosition(0);
// stepperZ.setCurrentPosition(0);
// stepperZ.setCurrentPosition(0);
Serial.begin(115200);
}
void loop() {
// Check for serial commands
if (Serial.available() > 0) {
// String command = Serial.readStringUntil('\n');
String input = Serial.readString();
// Serial.println(input);
int commaPosition = input.indexOf(' ');
String command = input.substring(0, commaPosition);
String x = input.substring(commaPosition+1);
int steps = command.toInt();
////////////////////////////////
//////////////////////////////
////////////////////////////
if (x == "S") {
// Stop the motors
stepperX.stop();
// stepperY.stop();
// stepperZ.stop();
// stepperA.stop();
Serial.print(x);
Serial.print(",");
Serial.println("Motor(s) stopped");
// delay(100);
}
else {
// Extract the number of steps from the command
// int steps = command.substring(5).toInt();
// int steps = Serial.readString().toInt();
// int steps = 200; //command.toInt();
if (x == "F"){
Steps=steps;
}
else if (x == "B"){
Steps=-steps;
}
// Move motors a specified number of steps in one direction
// stepperX.moveTo(steps);
stepperX.moveTo(Steps);
stepperX.setSpeed(1000.0);
// stepperX.setAcceleration(500.0);
// stepperX.setSpeed(200);
stepperX.run();
stepperX.runToPosition();
// stepperX.runSpeedToPosition(); // use it if target position is known.
//stepperX.runSpeed();
total_num_stps = total_num_stps + steps; //stepperX.currentPosition();
// stepperX.setCurrentPosition(current_pos);
// delay(1000);
// stepperY.moveTo(steps);
// stepperY.runToPosition();
// stepperZ.moveTo(steps);
// stepperZ.runToPosition();
// stepperA.moveTo(steps);
// stepperA.runToPosition();
// Print success message
// Serial.print("current pos ");
Serial.print(total_num_stps);
Serial.print(",");
Serial.print(stepperX.currentPosition());
Serial.print(",");
Serial.println("Command executed successfully");
}
///////////////////////////
////////////////////////////
/////////////////////////////
// stepperX.run();
delay(100);
}
}
I would be great if someone could help me solve this issue.
The first parameter is wrong. This is the motor interfac type AccelStepper uses and it must be the same for all steppers at your CNC board. Because all of these are step/dir drivers you must use AccelStepper::DRIVER, ( which is type = 1 ).
That doesn't make sense. run() is used if you want the stepper run non blocking - and you have to call run() again and again as quickly as possible. runToPosition() blocks until the target position is reached. So you can use one or the other, but not both.
It is a very bad idea to have two variables that are only different in case.
Thank you for this update. I was trying to figure out what it does. When using AccelStepper stepperX(1, 2, 5); the stepper motor rotates much better than using AccelStepper stepperX(AccelStepper::FULL4WIRE, 2, 5);
This is also very useful to know. But my main problem is that the stepper motor moves only in one (clockwise) direction. and when I use negative steps Steps = -steps; stepperX.moveTo(Steps);
the motor does not change the direction of rotation.
stepperY, that is connected to pins 3 and 6 rotates both clockwise and anticlockwise while other stepper motors (stepperX and stepperZ) only rotate clockwise. What would be the case? Because everything else is the same.
#include <AccelStepper.h>
// AccelStepper stepperX(AccelStepper::FULL4WIRE, 2, 5);
// AccelStepper stepperY(AccelStepper::FULL4WIRE, 3, 6);
// AccelStepper stepperZ(AccelStepper::FULL4WIRE, 4, 7);
// AccelStepper stepperA(AccelStepper::FULL4WIRE, 8, 9);
AccelStepper stepperX(AccelStepper::DRIVER, 2, 5);
AccelStepper stepperY(AccelStepper::DRIVER, 3, 6);
AccelStepper stepperZ(AccelStepper::DRIVER, 4, 7);
AccelStepper stepperA(AccelStepper::DRIVER, 8, 9);
// AccelStepper stepperX(1, 2, 5);
// AccelStepper stepperY(1, 3, 6);
// AccelStepper stepperZ(1, 4, 7);
// AccelStepper stepperA(1, 8, 9);
////////////////////////////////////////
///////////// INITIALIZE //////////////
//////////////////////////////////////
int target;
int run_count = 0;
float current_pos = 0.;
int total_num_stps = 0;
int maxspeed = 10000; // Set this to the desired speed
int acceleration = 500000;
////////////////////////////////////////
///////////// END INITIALIZE //////////
//////////////////////////////////////
void setup() {
stepperX.setMaxSpeed(maxspeed);
stepperX.setAcceleration(acceleration);
stepperX.setSpeed(maxspeed);
// stepperX.enableOutputs();
stepperY.setMaxSpeed(maxspeed);
stepperY.setAcceleration(acceleration);
stepperY.setSpeed(maxspeed);
stepperZ.setMaxSpeed(maxspeed);
stepperZ.setAcceleration(acceleration);
stepperZ.setSpeed(maxspeed);
// stepperA.setMaxSpeed(maxspeed);
// stepperA.setAcceleration(acceleration);
// stepperA.setSpeed(maxspeed);
// Set the initial position (optional)
// stepperX.setCurrentPosition(0);
// stepperY.setCurrentPosition(0);
// stepperZ.setCurrentPosition(0);
// stepperA.setCurrentPosition(0);
Serial.begin(115200);
}
void loop() {
// Check for serial commands
if (Serial.available() > 0) {
// String command = Serial.readStringUntil('\n');
String input = Serial.readString();
// Serial.println(input);
int commaPosition = input.indexOf(' ');
String command = input.substring(0, commaPosition);
String x = input.substring(commaPosition+1);
int steps = command.toInt();
////////////////////////////////
//////////////////////////////
////////////////////////////
if (x == "S") {
// Stop the motors
stepperX.stop();
stepperY.stop();
stepperZ.stop();
// stepperA.stop();
Serial.print(x);
Serial.print(",");
Serial.println("Motor(s) stopped");
// delay(100);
}
else {
if (x == "F"){ // Forward rotation
target=steps;
}
else if (x == "B"){ //Backward rotation
target=-steps;
}
stepperX.moveTo(target);
while (stepperX.currentPosition() != target){
stepperX.run();
}
stepperY.moveTo(target);
while (stepperY.currentPosition() != target){
stepperY.run();
}
stepperZ.moveTo(target);
while (stepperZ.currentPosition() != target){
stepperZ.run();
}
// stepperA.moveTo(target);
// while (stepperA.currentPosition() != target){
// stepperA.run();
// }
// stepperX.setCurrentPosition(0);
// stepperY.setCurrentPosition(0);
// stepperZ.setCurrentPosition(0);
// stepperA.setCurrentPosition(0);
// stepperX.setCurrentPosition(target);
// stepperX.moveTo(-target);
// while (stepperX.currentPosition()!=-target){
// stepperX.run();
// }
// Move motors a specified number of steps in one direction
// stepperX.move(Steps);
// stepperX.moveTo(Steps);
// stepperX.setSpeed(1000.0);
// stepperX.setAcceleration(500.0);
// stepperX.setSpeed(200);
// stepperX.run();
// stepperX.runToPosition();
// stepperX.runSpeedToPosition(); // use it if target position is known.
//stepperX.runSpeed();
total_num_stps = total_num_stps + target; //stepperX.currentPosition();
// stepperX.setCurrentPosition(current_pos);
// delay(1000);
// stepperY.moveTo(steps);
// stepperY.runToPosition();
// stepperZ.moveTo(steps);
// stepperZ.runToPosition();
// stepperA.moveTo(steps);
// stepperA.runToPosition();
// Print success message
// Serial.print("current pos ");
Serial.print(total_num_stps);
Serial.print(",");
Serial.print(total_num_stps);
// Serial.print(stepperX.currentPosition());
Serial.print(",");
Serial.println("Command executed successfully");
}
///////////////////////////
////////////////////////////
/////////////////////////////
// stepperX.run();
delay(100);
}
}
Are you shure that your motor connection is correct? With the motors I know having this JST connector ( regarding to your picture in first post) black and red would be one coil and green and blue the other. But that doesn't fit to your connection to the driver.
Looking at the supplied pictures I don't see any wires connected to the Dir pins for any of the stepper driver boards, and I didn't see any code for stepper direction. may that's why it runs in only one direction.