// dougp1
// From dougp, Introductory Tutorials: 'State machines', March 2019
// https://forum.arduino.cc/t/state-machines/580593
// Wokwi schematic, 16th September, Terry Pinnell
// The sketch simulates a simple motor-driven door opener/closer
// such as might be used on a garage, chicken coop, window blinds,
// etc. Starting from a known position a switch is pressed, the
// door opens, then stops. When the switch is pressed again the
// door closes, then stops.
//
// A timer is used to simulate the delay while the door is being
// driven to its new position and LEDs simulate the up/down
// forward/reverse action of the the motor.
// The sketch uses the following I/O
const unsigned char switchInput = 10; // +5V--| |--SW-- Arduino pin 10
const unsigned char openLED = 9; // +5V--/\/\/- 330Ω -->|-- Arduino pin 9
const unsigned char closeLED = 7; // +5V--/\/\/- 330Ω -->|-- Arduino pin 7
#define motorRun LOW
#define motorStop HIGH
#define accumulatedMillis millis() - timerMillis
const unsigned long motorTimerPreset = 2000; // two seconds
unsigned long timerMillis; // For counting time increments
// The door has four possible states it can be in
// Let's give the states descriptive names
enum {doorIsDown, doorIsUp, doorOpening, doorClosing};
unsigned char doorState; // What the door is doing at any given moment.
void setup() {
Serial.begin(115200);
pinMode(switchInput, INPUT_PULLUP);
pinMode(openLED, OUTPUT);
digitalWrite(openLED, HIGH);
pinMode(closeLED, OUTPUT);
digitalWrite(closeLED, HIGH);
// doorState = 6;
}
void loop() {
switch (doorState) {
case doorIsDown: // Nothing happening, waiting for switchInput
Serial.println("door down");
if (digitalRead(switchInput) == LOW) { // switchInput pressed
timerMillis = millis(); // reset the timer
doorState = doorOpening; // Advance to the next state
break;
}
else { // Switch not pressed
break; // State remains the same, continue with rest of the program
}
case doorOpening:
Serial.println("door opening");
digitalWrite(openLED, motorRun);
//
// The compare below would be replaced by a test of a limit
// switch, or other sensor, in a real application.
if (accumulatedMillis >= motorTimerPreset) { // Door up
digitalWrite( openLED, motorStop); // Stop the motor
doorState = doorIsUp; // The door is now open
break;
}
else {
break;
}
case doorIsUp:
Serial.println("door up");
if (digitalRead(switchInput) == LOW) { // switchInput pressed
timerMillis = millis(); // reset the timer
doorState = doorClosing; // Advance to the next state
break;
}
else { // switchInput was not pressed
break;
}
case doorClosing:
Serial.println("door closing");
digitalWrite(closeLED, motorRun); // Down LED on
if (accumulatedMillis >= motorTimerPreset) {
digitalWrite(closeLED, motorStop); // Stop the motor
doorState = doorIsDown; // Back to start point
break;
}
else {
break;
}
default:
Serial.println("\n We hit the default");
delay(3000);
doorState = doorIsDown;
break;
}
}