I want to make my stepper revolve 3 or 4 times when the light sensor detects light intensity below 400, but with my code it runs continuously. If I put the step function in void setup instead of loop, it causes it to malfunction and not run properly.
#include <Stepper.h>
int StepsPerRevolution=2048;
int motSpeed=9;
int dt=500;
int lightPen=A0;
int lightVal;
int dv=500;
Stepper myStepper(StepsPerRevolution,9,11,10,12);
void setup() {
Serial.begin(9600);
myStepper.setSpeed (motSpeed);
pinMode(lightPen,INPUT);
}
void loop() {
lightVal=analogRead(lightPen);
Serial.println(lightVal);
delay(dv);
if(lightVal<400)
{
myStepper.step(StepsPerRevolution);
return 0;
}
}
That does not make sense. You can put that code in setup() and then it will only run one time. What stepper motor are you using and how are you powering it?
Also, you speed is really low (motSpeed=9). Try out the stepper OneRevolution example to see if it is your hardware or your code (File->examples->stepper->OneRevolution)
If i put the if condition outside void loop its not able to get the value of "lightVal" as its defined inside void loop. And I kind of want it to run only once but once the light intensity gets high again I want it to do it again when the lightval value decreses below threshold
Please explain exactly when your stepper should turn. Because loop() - as the name suggests - loops, it will start your motor with every loop() cycle again - as long as your light value is below 400.
You need to remember in a variable that it already has been started so you will not start it again with the next loop() cycle.
I suppose it should start again once your light value has increased above 400 and after that falls below again?
Here is a demo code that will have the stepper turn one revolution when the light to the LDR is blocked. If the light is unblocked it must be blocked again to get the motor to move. The code uses a variation of the state change detection method. Also hysteresis is used so the output will not chatter near the threshold. The MobaTools library can be installed using the IDE library manager. I use the internal pullup on the analog input as the load resistor for the LDR so an external resistor is not needed.
While @groundFungus has given you an example using the MobaTools here is one using the Stepper library:
/*
Forum: https://forum.arduino.cc/t/stepper-motor-runs-continuously/1183191
Wokwi: https://wokwi.com/projects/379848824166403073
*/
#include <Stepper.h>
/*
The Wokwi Simulation uses a stepper motor with 200 steps/revolution @ 100 rpm
Comment the line "#define SIMULATION" out to use 2048 steps/revolution @ 9 rpm instead
*/
//#define SIMULATION
#ifdef SIMULATION
constexpr int StepsPerRevolution = 200;
constexpr int motSpeed = 100; // rpm
#else
constexpr int StepsPerRevolution = 2048;
constexpr int motSpeed = 9;
#endif
// The sensor value must be below rotateThreshold to start rotation
constexpr int rotateThreshold = 400;
// The sensor must provide a value above the resumeThreshold
// before the next rotation may start (Hysteresis to avoid switching between
// both situations close around the value of rotateThreshold)
constexpr int resumeThreshold = 450;
constexpr byte lightPen = A0;
constexpr unsigned long measurementInterval = 500L;
// Define the no of rotations after rotation is triggered
constexpr unsigned long noOfRotations = 2L;
Stepper myStepper(StepsPerRevolution, 9, 11, 10, 12);
// Store the time in millis() when the measurement was done
// and use it to measure every measurementInterval [msec] only
unsigned long lastMeasurement = 0;
int lightVal;
// The variable triggerRotationAllowed is set to false in the beginning
// so that the motor will NOT rotate when the sketch starts with the
// light value below rotateThreshold! The light value has to exceed
// resumeThreshold once to allow to trigger rotations.
boolean triggerRotationAllowed = false;
// Holds the no of steps that the motor shall move
unsigned long noOfSteps = 0;
void setup() {
Serial.begin(9600);
myStepper.setSpeed (motSpeed);
}
void loop() {
checkLightSensor();
rotateIfRequired();
}
void checkLightSensor() {
// Does a measurement every measurementInterval [msec]
if (millis() - lastMeasurement >= measurementInterval) {
lastMeasurement = millis();
lightVal = analogRead(lightPen);
Serial.println(lightVal);
// If value below the threshold AND rotation is allowed)
if (lightVal < rotateThreshold && triggerRotationAllowed) {
// then set noOfSteps to the steps required von noOfRotation revolutions
noOfSteps = noOfRotations * StepsPerRevolution;
// Store that the rotation is triggered now
// to avoid running into this part of the code
// while lightVal stays below resumeThreshold
triggerRotationAllowed = false;
}
// In case that lightVal is above resumeThreshold
// and any earlier rotations are done (noOfSteps == 0)
// allow
if (lightVal > resumeThreshold && noOfSteps == 0) {
triggerRotationAllowed = true;
}
}
}
void rotateIfRequired() {
// If noOfSteps is greater than zero make one step
if (noOfSteps > 0 ) {
// Do one step
myStepper.step(1);
// Reduce the number of steps by 1 to get the remaining steps
noOfSteps--;
}
}
It includes a lot of comments to explain how it works.
The main problem with the Stepper lib used here is that the function myStepper.step(noOfSteps) blocks for the whole time it takes to move noOfSteps. The controller cannot do anything else during this time. In some applications you don't care but in a lot of application it matters ...
That's where the MobaTools come into play: They can handle stepper motors much better and "in the background" so that the functions are non blocking. And that's why it is usually recommended to use this really advanced library.
Hi @harkha
this is your code with better formatting and some comments
about what your code does
[code]
#include <Stepper.h>
int StepsPerRevolution = 2048;
int motSpeed = 9;
int dt = 500;
int lightPen = A0;
int lightVal;
int dv = 500;
Stepper myStepper(StepsPerRevolution, 9, 11, 10, 12);
void setup() {
Serial.begin(115200);
myStepper.setSpeed (motSpeed);
pinMode(lightPen, INPUT);
}
void loop() {
// TOP-OF-LOOP
// repeated code-execution starts here again and again and again
lightVal = analogRead(lightPen);
Serial.println(lightVal);
delay(dv);
if (lightVal < 400) {
myStepper.step(StepsPerRevolution);
// return 0; not nescessary to do a return because
// at the end of function loop() code-execution
// jumps up to TOP-OF-LOOP
}
} // if this line is reached code-execution jumps up to TOP-OF-LOOP
[/code]
Do you know the WOKWI-Simulator?
Often very helpful
Here is your code as WOKWI-simulation with additional printing to the serial monitor
The printing to the serial monitor makes visible what you code is really doing
Yes exactly! I want to do 2 rotation when light value falls below 400 and then stop, and once it gets above 400 it should do 2 rotation in negative direction and so on and so forth