// inputmode INPUT_PULLUP inverts logic states of the IO-pins
const byte pressed = LOW;
const byte released = HIGH;
const byte myStartButtonPin = 3;
const byte myPumpPin = 4;
unsigned long doseTimer;
const unsigned long dosing_ms = 6000;
unsigned long delayTimer;
const unsigned long delay_ms = 10000;
// very CONCIOUS use of bytes to reduce the number of new things (no enum)
const byte sm_waitForButton = 0;
const byte sm_startDosing = 1;
const byte sm_waitForDosingEnd = 2;
const byte sm_waitForDelayToEnd = 3;
byte STATE;
// array of chars so called "c_string" the second index must be bigger than the longest string
const char myStateNames[][24] = {
//234567901234567901234567890
"wait for button",
"start dosing",
"wait for dosing to end",
//2345679012345679012345
"wait for resting to end"
};
// easy to use helper-function for non-blocking timing
boolean TimePeriodIsOver (unsigned long &startOfPeriod, unsigned long TimePeriod) {
unsigned long currentMillis = millis();
if ( currentMillis - startOfPeriod >= TimePeriod ) {
// more time than TimePeriod has elapsed since last time if-condition was true
startOfPeriod = currentMillis; // a new period starts right here so set new starttime
return true;
}
else return false; // actual TimePeriod is NOT yet over
}
void setup() {
Serial.begin(115200);
Serial.println("Setup-Start");
Serial.println("press the button to start the process");
pinMode(myStartButtonPin, INPUT_PULLUP);
digitalWrite(myPumpPin, LOW);
pinMode(myPumpPin, OUTPUT);
STATE = sm_waitForButton;
}
void loop() {
printStateIfStateChanged();
myDemoStateMachine();
}
void myDemoStateMachine() {
switch (STATE) {
case sm_waitForButton:
if (digitalRead(myStartButtonPin) == pressed) {
Serial.println("Button pressed start mixing");
STATE = sm_startDosing;
}
break; // IMMIDIATELY jump down to END-OF-SWITCH
// which means skip the rest of the code inside the switch-statement
case sm_startDosing:
digitalWrite(myPumpPin, HIGH);
doseTimer = millis();
Serial.println("dosing started pump switched ON");
Serial.println("waiting for dosing to end");
STATE = sm_waitForDosingEnd;
break; // IMMIDIATELY jump down to END-OF-SWITCH
// which means skip the rest of the code inside the switch-statement
case sm_waitForDosingEnd:
if ( TimePeriodIsOver(doseTimer, dosing_ms) ) {
Serial.println("dosing time over switching pump off change to state Resting");
digitalWrite(myPumpPin, LOW);
delayTimer = millis();
STATE = sm_waitForDelayToEnd;
}
break; // IMMIDIATELY jump down to END-OF-SWITCH
// which means skip the rest of the code inside the switch-statement
case sm_waitForDelayToEnd:
if ( TimePeriodIsOver(delayTimer, delay_ms) ) {
Serial.println("resting time over change to state sm_waitForButton");
STATE = sm_waitForButton;
}
break; // IMMIDIATELY jump down to END-OF-SWITCH
// which means skip the rest of the code inside the switch-statement
} // END-OF-SWITCH
}
void printStateIfStateChanged() {
static byte lastState;
if (lastState != STATE) { // check if variable STATE has changed since last time printing
Serial.print(" ##State changed from ");
Serial.print(myStateNames[lastState]);
Serial.print(" to ");
Serial.print(myStateNames[STATE]);
Serial.println("##");
lastState = STATE; // update variable lastState
}
}