Hi there! Thank you for sharing your intention and also your code.
I see some issues, I'll try my best to explain them and suggest what you should do instead.
Firstly, let me summarize what I understand you are trying to do:
SITUATION A:
- When you twist the poteniometer so that it is above 0, the stepper should keep spinning until it has reached 400 steps.
- Once it has reached 400 steps, it should stop.
- I don't understand what you meant by: "stop my potentiometer as soon as its value is less than 0 or greater than 1023". Why would the potentiometer be less than 0 or greater than 1023? And why do you want to stop it when the potentiometer reaches above 1023? Is this a catch all just in case the poteniometer value gives some abnormal value?
I hope I captured that correctly, please let me know if I didn't understand it. The other thing that could be possible is that you mean:
SITUATION B:
- In one situation, I just want to have the motor keep spinning forever until I turn the potentiometer down to 0.
- In a different situation, I want the potentiometer to decide how many steps the motor should take. (e.g. if potValue = 400, then take 400 steps, if potValue = 1000 then take 1000 steps).
- In a completely different situation, I want the motor to keep spinning forever, and only if I bring turn the potentiometer such that potValue is less than 0 (I have no idea how that would be possibe, though) or such that potValue is greater than 1023 (I have no idea how that would be possible, either), I want the motor to stop.
I am going to assume what you want is SITUATION A, and I will provide an explanation below accordingly. If you really wanted SITUATION B (or something else entirely), then the solution would be different. Just reply back and we can go from there.
SITUATION A:
Ok!
-
You didn't specify the type of stepper motor you're using, but I'm going to assume you decided to use a stepper motor with 4 wires (black, green, red, blue). Please make sure you have correctly connected these wires to your stepper motor driver, in that order. (e.g. black, green, red, blue; OR blue, red, green, black). If you need more information on how to connect your stepper motor and use the driver, please watch this video: Stepper Motors with Arduino - Controlling Bipolar & Unipolar stepper motors - YouTube
-
Assuming you connected the 4 wire stepper motor to the driver correctly, and the driver's DIR pin is connected to arduino pin 8, and the STEP pin (also known as the PULSE pin) is connected to Arduino pin 9, then your initial code is fine:
#include <AccelStepper.h>
#define dirPin 8
#define stepPin 9
#define motorInterfaceType 1
const byte potPin = A0;
int setSpeedValue = 200;
// Create a new instance of the AccelStepper class:
AccelStepper stepper = AccelStepper(motorInterfaceType, stepPin, dirPin);
-
void setup() function looks fine, but if you are using a CNC shield, for example, make sure you aren't forgetting to set the ENABLE pin to LOW. If it's a standalone driver, you don't need to do that.
Arduino CNC Shield – 100% GRBL Compatable | Protoneer.co.nz
-
Now for the most important part, the loop() function.
Your task_1(), task_2(), and task_3() conflict with each other. Here is why:
The only way your motor will actually be told to make a step is if you use one of the following functions:
stepper.run() //runs to the target destination set by moveTo() using acceleration
or
stepper.runSpeed() //runs at a fixed SetSpeed() with no acceleration
task_1 starts off fine by setting the speed to setSpeedValue, and then it calls stepper.runSpeed().
So the first time your program loops, it will send a single pulse to your motor.
task_2 I don't fully understand, and doesn't seem necessary because task_1() is only going to make the motor move if the ppotValue is not 0, so I don't understand the purpose of task_2 since it's just going out of its way to set some additional conditions where the setSpeed value becomes 0.
I don't see when this first condition would ever be true:
if(potValue >=1023 && setSpeedValue < 0)
{
setSpeedValue=0;
}
And this second condition is already handled by task_1 in every realistic situation (from my understanding of the program). The reason is that if potValue equals 0, task_1 will already take care of it by making the setSpeedValue = 0.
So why do you need task_2 to try to issue that command again?
Additionally, I don't see when potValue will ever be less than or equal to 0 AND at the same time setSpeedValue will be greater than 0. task_1 will always prevent that situation from happening.
task_3 will sometimes work and will sometimes not.
If you launch this pprogram and your potValue is greater than 0, then task_1() will initiate one pulse to the motor at setSpeedVaalue = 200, and then task_3 will notice that the currentPostion == 0, which means currentPostion != 0, and therefore the "while" loop will begin indefinitely and it will make the motor move 400 steps.
BUT: the "while" loop makes it such your program will ignore every other function and poteniometer reading until that motor reaches 400 stepps. This is because a "while" loop keeps looping only within itself over and over again and does not have the program look at anything else UNTIl the "while" loop is finished.
BUT, if you launch this program while the potentiometer is already at "0", then..
task_1 will see the potentiometer is at 0, and it will make setSpeedValue = 0.
The problem is, even if you move the potentiometer to something above 0, nothing in your program tells it to update the setSpeedValue to be greater than 0. So when the program reaches task_3,
the "while" loop will see "hey! I haven't reached 400 steps yet, so let's enter the while loop!"
But then the stepper's speed is set to setSpeedValue, which is currently at 0 because your task_1 said that if the potentiometer ever reaches 0, make setSpeedValue 0. Nothing ever tells your program to change setSpeedValue back to 200! So task_3 will forever be stuck in that "while" loop because the motor will never spin because it's being told to spin at a speed of setSpeedValue == 0 and yet the program is also being told to forever stay in that "while" loop until the motor reaches 400 steps, which it will never reach because the motor is moving at setSpeedValue == 0 which means it will never move!
So, I would recommend a few key things:
- Remove task 2, it seems redundant
- Add something that tells your program to constantly update the setSpeedValue of your motor based on the potentiometer reading
- instead of putting the runSpeed() inside each task, put a single command at the end of the loop. This way, your program will decide what the motor needs to be, and then a single stepper.run() command will decide to move the motor if it determines that a step is due.
If you really want to do a fixed speed instead of acceleration, we can do that, but I would recommend starting off by using stepper.run() which uses acceleration instead of stepper.runSpeed() which can sometimes cause issues if you run too fast etc. depending on the situation. Unlikely, but it can happen. Plus, stepper.run() is easier to use. We can change back to runSpeed() if desired.
This code should do what I believe you were trying to achieve, but can be easily adjusted if not
#include <AccelStepper.h>
#define dirPin 8
#define stepPin 9
#define motorInterfaceType 1
const byte potPin = A0;
int maximumSpeed = 0; //we will adjust this dynamically according to the potentiometer
// Create a new instance of the AccelStepper class:
AccelStepper stepper = AccelStepper(motorInterfaceType, stepPin, dirPin);
void setup() {
Serial.begin(9600); //Set the serial communication speed
stepper.setMaxSpeed(0); // Let's have the default max speed be 0, and let it change based on the potentiometer reading. Arduino's CPU speed can handle up 4000.
stepper.setAcceleration(10000); //yes I wrote 10,000, which is fast but fine. Feel free to play around with it.
stepper.setCurrentPosition(0); // Set the current position to 0
}
void loop()
{
//The program needs to read and update these values at the beginning of each loop cycle.
//You'll notice these can be consolidated into fewer lines of code, but I have left them like this in case each step is eaasier to understand
double potValue = analogRead(potPin); //at the beginning of each cyle, check the value of the potentiometer
maximumSpeed = map(potValue,0,1023,0,4000); //depending on how far you turn the potentiometer, the maxSpeed between 0 and 4000 pulses per second, so the motor will spin slower or faster
stepper.setMaxSpeed(maximumSpeed);
//Instead of the individual "task" functions, I'm moving the relevant code here so it is easier to see the flow of events
if(potValue !=0) //if the potentiometer is anything other than 0, in other words if it is between 1 and 1023, let's tell the motor that its destination should be 400 steps away from 0 (in the setup() function, you had setCurrentPosition(0), so it will want to move 400 steps from there).
{
stepper.moveTo(400); //the destination has been set to 400 steps from the setCurrentPosition set in the setup() function. The motor WILL NOT MOVE until stepper.run() is called
}
else
{
stepper.stop(); //tells the motor that it should just stay where it is. It will still remember how many steps it has traveled, but it will not move further until the moveTo() command is issued again.
}
stepper.run(); //if the program notices that the stepper is due a step, it will issue a pulse. So, if the potValue != 0, then the stepper will moveTo(400) and keep running there until it reaches 400. If the motor was last told to stop(), then the run() command will not issue any pulses.
/*
//FYI: Using the Serial.print() functions will cause Arduino to take longer to process the code each cycle, and you will notice your motor will not perform as fast
//So, ideally use it for debugging only.
//Also you should move the declaration of "double Voltage" to somewhere PRIOR to the void setup() function
double Voltage= (potValue*5)/1023; // potValue converted to voltage
Serial.print("Potentiometer at ");
Serial.println(potValue);
Serial.print("pot Voltage");
Serial.println(Voltage);
Serial.print("Stepper angle: ");
Serial.println(stepper.currentPosition()*1.8);
delay(1000);
*/
}
P.S. sorry if some of my letters are typing extraa likee thhiss. I need to clean my keyboard 