/*
Forum:https://forum.arduino.cc/t/arduino-nano-code/1382277
Wokwi: https://wokwi.com/projects/431411551161475073
Simple State Machine
- MOVETOZERO: Move the stepper to zero position using the buttons
- WAITING: Wait for a given time in this position
- TURNING: Turn the stepper to position 180 degree or position 0 degree
- go on with WAITING if the respective target position has been reached
Buttons: Turn Left (yellow),
turn Right (white),
stop turning (black) or
accept position as Zero with Start (green)
Pressing Left or Right several times increases the turn rate
Pressing Stop resets the turn rate to minTurnRate again
Pressing Start sets the turn rate to maxTurnRate
Pressing Stop while in WAITING or TURNING state stops the stepper and changes state to MOVETOZERO again
ec2021
2025/05/19
*/
#include <MobaTools.h>
class buttonType {
private:
byte pin;
byte state = HIGH;
byte lastState = LOW;
unsigned long lastChange = 0;
public:
void init(byte aPin) {
pin = aPin;
pinMode(pin, INPUT_PULLUP);
};
boolean pressed() {
byte actState = digitalRead(pin);
if (actState != lastState) {
lastState = actState;
lastChange = millis();
}
if (state != actState && millis() - lastChange > 50) {
state = actState;
return !state;
}
return false;
};
};
constexpr byte btLeftPin {7};
constexpr byte btStopPin {6};
constexpr byte btRightPin {5};
constexpr byte btStartPin {4};
constexpr unsigned long totalSequenceTime {5000}; // 240 seconds => 240000;
constexpr long stepsPer360 {200};
constexpr int maxTurnSpeed {148};
constexpr int minTurnSpeed { 9};
MoToStepper myStepper(stepsPer360, FULLSTEP);
enum SandUhrStates {MOVETOZERO, WAITING, TURNING};
SandUhrStates state = MOVETOZERO;
long targetAngle = 0;
unsigned long startToWait = 0;
unsigned long startOfTurn = 0;
unsigned long lastTurnTime = 0;
unsigned long waitTimeCorrection = 0;
int actSpeed = 10;
buttonType btLeft, btRight, btStop, btStart;
void setup() {
myStepper.attach( 11, 9, 10, 8);
setSpeed(minTurnSpeed);
Serial.begin(115200);
btLeft.init(btLeftPin);
btRight.init(btRightPin);
btStop.init(btStopPin);
btStart.init(btStartPin);
Serial.println("Move to Zero");
state = MOVETOZERO;
}
void loop() {
sandUhr();
checkForButtons();
}
void sandUhr() {
switch (state) {
case MOVETOZERO:
if (btLeft.pressed()) {
myStepper.rotate(-1);
setSpeed(actSpeed + 1);
}
if (btRight.pressed()) {
myStepper.rotate(1);
setSpeed(actSpeed + 1);
}
if (btStop.pressed()) {
myStepper.stop();
setSpeed(minTurnSpeed);
}
if (btStart.pressed()) {
myStepper.stop();
myStepper.setZero();
setSpeed(maxTurnSpeed);
startToWait = millis();
lastTurnTime = 0;
state = WAITING;
targetAngle = 0;
Serial.println("Waiting ... ");
}
break;
case WAITING:
if (millis() - startToWait >= totalSequenceTime - lastTurnTime) {
targetAngle = (targetAngle == 0) ? 180 : 0;
myStepper.write(targetAngle);
startOfTurn = millis();
state = TURNING;
Serial.println("Turning");
}
break;
case TURNING:
if (myStepper.read() == targetAngle) {
startToWait = millis();
lastTurnTime = startToWait - startOfTurn;
state = WAITING;
Serial.print("Turn required ");
Serial.print(lastTurnTime);
Serial.println(" [ms]");
Serial.print("Waiting for ");
Serial.print(totalSequenceTime - lastTurnTime);
Serial.println(" [ms]");
}
break;
}
}
void checkForButtons() {
if (state != MOVETOZERO) {
if (btStop.pressed()) {
myStepper.stop();
setSpeed(minTurnSpeed);
Serial.println("Move to Zero");
state = MOVETOZERO;
}
}
}
void setSpeed(int speed) {
actSpeed = speed;
myStepper.setSpeed(actSpeed);
}