// For:
// https://forum.arduino.cc/t/arduino-photo-interrupter-stepper-motor-project/1040942
//
// Using the "StepperOneStepAtATime" from:
// https://docs.arduino.cc/learn/electronics/stepper-motor
//
//
// Something bad happened here. I started coding and coding and coding,
// but in the end there was no real plan for the structure or a full safety check.
// That's just wrong. This is a beginners sketch.
//
#include <Stepper.h>
const int stepsPerRevolution = 200; // depends on the stepper motor
Stepper myStepper(stepsPerRevolution, 11, 12, 10, 9);
const int ledPin = 3; // A PWM pin for the LED
const int buttonPin = 5; // HIGH if pressed
const int photoUpperPin = 6; // Upper photointerrupter, active LOW
const int photoLowerPin = 4; // Lower photointerrupter, active LOW
int state; // +1 is up, -1 is down, 0 is not moving
int count; // counts the number of steps
int lastButtonState; // for the State Change Detection for the button
const int safetyDistancePhoto = 200; // steps to be sure that photointerruptor is released
void setup()
{
Serial.begin(115200);
Serial.println( F("Hello, the sketch is running."));
Serial.println( F("Slide the switches to the left to for the upper and lower signals."));
pinMode(ledPin, OUTPUT);
pinMode(buttonPin, INPUT);
pinMode(photoUpperPin, INPUT_PULLUP);
pinMode(photoLowerPin, INPUT_PULLUP);
myStepper.setSpeed(20); // This also works with single steps
// Initialize variables.
// Normally, the stepper motor should go to the default position if it is in the middel.
// Check if it is already in a position.
state = 0; // default, not moving
count = 0;
lastButtonState = LOW; // active HIGH, assuming button is not pressed.
// Blink the led, just for fun.
for( int i=0; i<5; i++)
{
digitalWrite( ledPin, HIGH);
delay( 200);
digitalWrite( ledPin, LOW);
delay( 200);
}
Serial.println( F("Press the button to move up."));
}
void loop()
{
if( state == 0) // not moving ?
{
// The stepper motor is not moving.
// The position should be in the upper or lower position.
// Check if the button is pressed.
int buttonState = digitalRead( buttonPin); // debouncing later on with delay
if( buttonState == HIGH and lastButtonState == LOW) // button was just pressed ?
{
// Check the photointerruptors to see where it is
int photoUp = digitalRead( photoUpperPin); // upper photointerruptor
int photoDown = digitalRead( photoLowerPin); // lower photointerruptor
if( photoUp == LOW and photoDown == HIGH) // in highest position ?
{
state = -1; // going down
count = 0; // count the steps
Serial.println( F("Going down..."));
}
else if( photoUp == HIGH and photoDown == LOW) // in lowest position ?
{
state = +1; // going up
count = 0; // count the steps
Serial.println( F("Going up..."));
}
else if( photoUp == LOW and photoDown == LOW)
{
Serial.println( F("Error, both photointerruptors are active."));
Serial.println( F("Not moving for safety."));
}
else if( photoUp == HIGH and photoDown == HIGH)
{
Serial.println( F("Error, position unknown."));
Serial.println( F("No photointerruptor is active."));
Serial.println( F("Not moving for safety."));
}
}
lastButtonState = buttonState;
delay( 20); // an ugly way to debounce the button
}
else
{
// The stepper is moving, check the photointerruptors after each step.
myStepper.step( state); // make one step
count++; // increment number of steps
int photoUp = digitalRead( photoUpperPin); // upper photointerruptor
int photoDown = digitalRead( photoLowerPin); // lower photointerruptor
if( state == +1 and photoUp == LOW) // reached the upper limit ?
{
state = 0; // stop the stepper
Serial.print( F("Reached Upper after "));
Serial.print( count);
Serial.println( F(" steps."));
Serial.println( F("Press the button to move down."));
}
else if( state == -1 and photoDown == LOW) // reached the lower limit ?
{
state = 0;
Serial.print( F("Reached Lower after "));
Serial.print( count);
Serial.println( F(" steps."));
Serial.println( F("Press the button to move up."));
}
else if( state == +1 and photoDown == LOW and count > safetyDistancePhoto)
{
Serial.println( F("Error, lower switch did not release while going up."));
Serial.println( F("Stopped for safety."));
state = 0;
}
else if( state == -1 and photoUp == LOW and count > safetyDistancePhoto)
{
Serial.println( F("Error, upper switch did not release while going down."));
Serial.println( F("Stopped for safety."));
state = 0;
}
else if( photoUp == LOW and photoDown == LOW)
{
Serial.println( F("Error, both photointerruptors activated."));
Serial.println( F("Stopped for safety."));
state = 0;
}
}
}