/*
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--;
}
}