Hey, I'm working on a project that will allow me to control two NEMA 17 stepper motors using a joystick. These two motors can change direction and have variable speed based on the input of the controller. This code works well but I'm having trouble on two key issues.
First : My motors are supposed to be able to change directions, I have attempted to switch the step value for counterclockwise movement from positive 8 to negative 8 in these two lines of code stepper.move(8); , stepper1.move(8); , but when I do the program breaks, causing the motors and values displayed on the Serial monitor to freeze.
Second : The motors are supposed to take their RPM values from adjJoystick and adjJoystick1 , which take their numbers from Analog pin 1 and 0. But for some reason when both motors are activated they lose the ability to adjust their speed independently. [Note: after doing some testing I found that the DIRE, DIRE1, STEP, and STEP1 pins are not processed by the boards. If that is the problem would somebody be able to explain how to fix that?]
[code]
#include <Arduino.h>
#include "A4988.h" // Defining the A4988 Library
const int SW_pin = 8; // digital pin connected to switch output
const int Y_pin = 0; // analog pin connected to X output
const int X_pin = 1; // analog pin connected to Y output
int Step = 3; // Step of stepper motor driver
int Dire = 2; // Direction of stepper motor driver
int Sleep = 4; // Control Sleep Mode on A4988
int MS1 = 7; // MS1 for A4988
int MS2 = 6; // MS2 for A4988
int MS3 = 5; // MS3 for A4988
int Step1 = 9; // Step of the second stepper motor driver
int Dire1 = 13; // Direction of the second stepper motor driver
int Sleep1 = 11; // Sleep mode for second stepper motor driver
int MS11 = 12; // MS1 for the second A4988
int MS21 = 10; // Merging MS21 and MS31 to allow full and half steps,
int MS31 = 10; // This has to be done because the number of pins avalible has reached capacity
enum movementState { // defining the three states motor #1 can exist in
STATIONARY,
CLOCKWISE,
COUNTCLOCKWISE
};
enum movementState1 { // defining the three states motor #2 can exist in
STATIONARY1,
CLOCKWISE1,
COUNTCLOCKWISE1
};
int i;
// motor specs
const int spr = 200; // Steps per revolution of the first motor
const int spr1 = 200; // Steps per revolution of the second motor
int RPM = 100; // Motor Speed in revolutions per minute
int Microsteps = 2; // Stepsize (1 for full steps, 2 for half steps, 4 for quarter steps, etc)
const int maxRPM = 100; // gives limits on the fastest the motor can move. Changing this will change the maximum RPM
const int minRPM = 0; // gives limits for the slowest the motor can move. Changing this will chnage the minimum RPM
enum movementState currentState; // This creates an enclosed function that can process the movement states of motor #1
enum movementState1 currentState1; // This creates an enclosed function that can process the movement states of motor #2
// A4988 pins
A4988 stepper (spr, Dire, Step, MS1, MS2, MS3); // This defines the pins of the first stepper motor driver
A4988 stepper1(spr1,Dire1,Step1,MS11,MS21,MS31); // This defines the pins of the second stepper motor driver
void setup() {
Serial.begin(9600);
pinMode(SW_pin, INPUT);
digitalWrite(SW_pin,HIGH);
pinMode(Step, OUTPUT); // Step pin as output
pinMode(Dire, OUTPUT); // Direction pin as output for the first Stepper motor driver
pinMode(Sleep, OUTPUT); // Set Sleep OUTPUT Control button as output for the first Stepper motor driver
digitalWrite(Step, LOW); // Start with no stepper motor movement for the first Stepper motor driver
digitalWrite(Dire, LOW); // Start with no directional movement for the first Stepper motor driver
pinMode(Step1, OUTPUT); // Step1 pin as output for the second Stepper motor driver
pinMode(Dire1, OUTPUT); //Direction1 pin as output for the second Stepper motor driver
pinMode(Sleep1, OUTPUT); //Set Sleep1 OUTPUT Control button as output for the second Stepper motor driver
digitalWrite(Step1, LOW); // Start with no stepper motor movement on the second Stepper motor driver
digitalWrite(Dire1, LOW); // Start with no directional movement for the second Stepper motor driver
currentState = STATIONARY; // defining the start position for the first stepper motor
currentState1 = STATIONARY1; // defining the start position for the second stepper motor
stepper.begin(RPM, Microsteps);
stepper1.begin(RPM, Microsteps);
}
void loop() {
int xAxis = analogRead(X_pin); // defining the X-value given through the controller
int yAxis = analogRead(Y_pin); // defining the Y-value given through the controller
digitalWrite(Sleep, HIGH); // This takes the first motor out of sleep mode
digitalWrite(Sleep1,HIGH); // This takes the second motor out of sleep mode
// Serial.print("Y-axis: ");
// Serial.println(analogRead(Y_pin));
// Serial.print("\n\n");
// Serial.print("X-axis: ");
// Serial.println(analogRead(X_pin));
// Serial.print("\n\n");
int adjJoystick = calc(analogRead(Y_pin)); // adjJoystick is the adjusted value of the joystick to fit between +- 100, also used in setting RPM
switch (currentState) {
case STATIONARY:
// Stationary Code - Hard stop, no motor movement, clear all movement actions
stepper.stop(); // stops the movement when the controller is stationary
Serial.print("STATIONARY: ");
Serial.println(adjJoystick );
// delay(450);
if(adjJoystick > 2){ // The resting position of +-2 provides plenty of room for the motor to still function incase of controller drift.
currentState = CLOCKWISE; // if the RPM found on the Serial Moniter rises above 2, then follow the code found in the clockwise case.
} else if (adjJoystick < -2) {
currentState = COUNTCLOCKWISE; // if the RPM found on the Serial Moniter falls below -2, then follow the code found in the countclockwise case.
}
break;
case CLOCKWISE:
digitalWrite(Dire, HIGH); // sets the direction of motor 1 to Clockwise
stepper.setRPM(adjJoystick);
stepper.move(8);
Serial.print("CLOCKWISE: ");
Serial.println(adjJoystick);
// delay(100);
if(adjJoystick <= 2 && adjJoystick >= -2){
currentState = STATIONARY; // if the RPM found on the Serial Moniter rises above -2 AND falls under 2, then follow the code found in the stationary case.
} else if (adjJoystick < -2) {
currentState = COUNTCLOCKWISE; // if the RPM found on the Serial Moniter falls below -2, then follow the code found in the countclockwise case.
}
break;
case COUNTCLOCKWISE:
digitalWrite(Dire, LOW); // sets the direction of motor 1 to CounterClockwise
stepper.setRPM(adjJoystick);
stepper.move(8);
Serial.print("COUNTERCLOCKWISE: ");
Serial.println(adjJoystick);
// delay(100);
if(adjJoystick <= 2 && adjJoystick >= -2){
currentState = STATIONARY; // if the RPM found on the Serial Moniter rises above -2 AND falls under 2, then follow the code found in the stationary case.
} else if (adjJoystick > 2){
currentState = CLOCKWISE; // if the RPM found on the Serial Moniter rises above 2, then follow the code found in the clockwise case.
}
break;
default:
// Something has gone very very wrong if this is true.
Serial.println("UHOH");
break;
}
int adjJoystick1 = calc(analogRead(X_pin));// adjJoystick1 is the adjusted value of the joystick to fit between +- 100, also used in setting RPM
switch (currentState1) {
case STATIONARY1:
// Stationary Code - Hard stop, no motor movement, clear all movement actions
stepper1.stop();
Serial.print("STATIONARY 1: ");
Serial.println(adjJoystick1);
// delay(450);
if(adjJoystick1 > 2){
currentState1 = CLOCKWISE1; // if the RPM found on the Serial Moniter rises above 2, then follow the code found in the clockwise1 case.
} else if (adjJoystick1 < -2) {
currentState1 = COUNTCLOCKWISE1; // if the RPM found on the Serial Moniter falls below -2, then follow the code found in the countclockwise1 case.
}
break;
case CLOCKWISE1:
digitalWrite(Dire1, HIGH); // sets the direction of motor 2 to Clockwise
stepper1.setRPM(adjJoystick1);
stepper1.move(8);
Serial.print("CLOCKWISE 1: ");
Serial.println(adjJoystick1);
// delay(100);
if(adjJoystick1 <= 2 && adjJoystick1 >= -2){
currentState1 = STATIONARY1; // if the RPM found on the Serial Moniter rises above -2 AND falls under 2, then follow the code found in the stationary1 case.
} else if (adjJoystick1 < -2) {
currentState1 = COUNTCLOCKWISE1; // if the RPM found on the Serial Moniter falls below -2, then follow the code found in the countclockwise1 case.
}
break;
case COUNTCLOCKWISE:
digitalWrite(Dire1, LOW); // sets the direction of motor 2 to CounterClockwise
stepper1.setRPM(adjJoystick1);
stepper1.move(8);
Serial.print("COUNTERCLOCKWISE 1: ");
Serial.println(adjJoystick1);
// delay(100);
if(adjJoystick1 <= 2 && adjJoystick1 >= -2){
currentState1 = STATIONARY1; // if the RPM found on the Serial Moniter rises above -2 AND falls under 2, then follow the code found in the stationary1 case.
} else if (adjJoystick1 > 2){
currentState1 = CLOCKWISE1; // if the RPM found on the Serial Moniter rises above 2, then follow the code found in the clockwise1 case.
}
break;
default:
// Something has gone very very wrong if this is true.
Serial.println("UHOH");
break;
}
}
int calc(int x ) { // this equation defines the term calc
float k = x - 512; // k is kvalue, it is the conversion from the controller range of 1024 down to the motor range of 100 RPM. x is xvalue, it's the incriment between 0-1024 displayed as between -512 -> 512
k = k*0.195; // ratio of controller range to RPM. 512 for the controller, and 100RPM for the motor
return (int)k;
}
[/code]