Okay the entire code is a bit long but here it goes. it's a 4 stage dosing system. with currently two push buttons. There is a state machine and flag system tied in with a debouncer library. It essentially allows me to go from an IS_OPEN state to a IS_FALLING when the signal is low (reverse clause).
I use this to drive my flags as a button pressed, true or false for my main state machine. I got the example of this from here.
#include <Adafruit_MotorShield.h>
#include <EdgeDebounceLite.h>
//to do figure out timing intervals and whether or not you will remove the delay
EdgeDebounceLite debounce;
Adafruit_MotorShield AFMS = Adafruit_MotorShield();
Adafruit_DCMotor *Dose1 = AFMS.getMotor(1); //pump 1
Adafruit_DCMotor *Dose2 = AFMS.getMotor(2); //pump 2
Adafruit_DCMotor *Dose3 = AFMS.getMotor(3); //pump 3
Adafruit_DCMotor *Dose4 = AFMS.getMotor(4);//pump 4
/*GLOBAL VARIABLES */
//PINS & BUTTONS//
byte routinePin[2] = {3, 4}; //push buttons to be used with debounce
#define Gledstatus 6
#define Bledstatus 7
#define Rledstatus 8
/*ROUTINE 1 TIMING VARIABLES*/
//Global to routine 1 and 2 maybe?? as time tracking variables//
unsigned long mDc_on; // similar to how previousMillis= currentmillis, a variable for how long a dose has run for
unsigned long Routine1Millis; //how long since routine 1 button was pressed
//Changing timwe intervals//
//I have left them all the same value for now for my brain
unsigned long mD1wait_interval = 2500; // Pump off time
unsigned long mD1run_interval = 5000; // Pump on time
//dose 2 with motor 2
unsigned long mD2wait_interval = 500; //
unsigned long mD2run_interval = 15000; //
// dose 3 with motor 3
unsigned long mD3wait_interval = 500; //
unsigned long mD3run_interval = 15000; //
//dose 4 with motor 4
unsigned long mD4wait_interval = 500; //
unsigned long mD4run_interval = 15000; //
/*ROUTINE 2 TIMING VARIABLES*/
//routine 2 as time tracking variables unsure if I need these//
unsigned long mDc2_on; // similar to how previousMillis= currentmillis, a variable for how long a dose has run for
unsigned long Routine2Millis; //how long since routine 2 button was pressed
//Changing time intervals//
//I have left them all the same value for now for my brain
unsigned long mD1bwait_interval = 2500; // Pump off time
unsigned long mD1brun_interval = 5000; // Pump on time
//dose 2 with motor 2
unsigned long mD2bwait_interval = 500; //
unsigned long mD2brun_interval = 15000; //
// dose 3 with motor 3
unsigned long mD3bwait_interval = 500; //
unsigned long mD3brun_interval = 15000; //
//dose 4 with motor 4
unsigned long mD4bwait_interval = 500; //
unsigned long mD4brun_interval = 15000; //
/*MAIN STATE MACHINE STATES*/
enum DosingSystemStates{idle, DOSINGA, DOSINGB, DOSEFINISH };
DosingSystemStates dosingSystemState = idle;
// Switch states
enum SwitchStates {IS_OPEN, IS_RISING, IS_CLOSED, IS_FALLING };
SwitchStates switchState[2] = {IS_OPEN, IS_OPEN }; // both switches are in is open
//
enum SwitchModes {PULLUP, PULLDOWN}; //the two possible modes the pins could be in
SwitchModes switchMode[2] = {PULLUP, PULLUP}; // I am focused on states where both switches are in pullup mode.
//FLAGS
bool hasRout1_strtd() { //Routine 1 active?
switchMachine(0); //Read switch 0
if (switchState[0] == IS_FALLING) //If it is in the state IS_FALLING
return true; //R1 started, return true
else //If not
return false; //return false
}
bool hasRout2_strtd() { //Routine 2 active?
switchMachine(1); //Read switch 1
if (switchState[1] == IS_FALLING) //If it is in the state IS_FALLING
return true; //R2 started, return true
else //If not
return false; //return false
}
void switchMachine(byte i) {
byte pinIs = debounce.pin(routinePin[i]);
if (switchMode[i]) == INPUT_PULLUP)
switch (switchState[i]) {
case IS_OPEN: { //State is IS_OPEN
if(pinIs == HIGH) //If the pin is HIGH
switchState[i] = IS_RISING; //We just changed form LOW to HIGH: State is now IS_RISING
break; //Get out of switch
}
case IS_RISING: { //State is IS_RISING
switchState[i] = IS_CLOSED; //It is not rising anymore, State is now IS_CLOSED
break; //Get out of switch
}
case IS_CLOSED: { //State is IS_CLOSED
if(pinIs == LOW) //If the pin is LOW
switchState[i] = IS_FALLING; //We just changed from HIGH to LOW: State is now IS_FALLING
break; //Get out of switch
}
case IS_FALLING: { //State is IS_FALLING
switchState[i] = IS_OPEN; //It is not falling anymore, State is now IS_OPEN
break;
}
}
}
void DosingSystem(){
switch(dosingSystemState) {
case idle:
//check the time, I'm not sure yet whether this is logically illegal
//but I think if it is global to the case/state then it applies to all
//aspects of the if statement within it, please correct otherwise
unsigned long currentMillis = millis(); //
if (hasRout1_strtd())
Routine1Millis = currentMillis; //if routine 1 button is pressed/TRUE start routine 1 timer/ get a snapshot of the time for void DoseR1()
dosingSystemState = DOSINGA; // go to dosing state A
if (hasRout2_strtd()) //if routine 2 button is pressed/TRUE same for the above
Routine2Millis = currentMillis;
dosingSystemState = DOSINGB;// go to dosing state B
//might add connection to https server here, depends on my ESP32 abilities
//might be my 2nd forum post when I break it :3
break;
case DOSINGA:
DoseR1(); /// dose r2 is idential for now for simplicity, but essentially, r1 is the concept I am going for
// How do we link/track the execution of this function
// and the main stateso that the main state machine progresses
// when DoseR1(); is completed, how does the below line execute?
dosingSystemState = DOSEFINISH;
break;
case DOSINGB:
DoseR2();
dosingSystemState = DOSEFINISH;
break;
case DOSEFINISH:
//do somethinggggggg then return to idle I guess
dosingSystemState = idle;
break;
}
}
// put your setup code here, to run once:
void setup() {
// put your setup code here, to run once:
Serial.begin(9600); // Serial connection for Debug
Serial.println("Starting Unity");
// put your setup code here, to run once:
if (!AFMS.begin()) { // create with the default frequency 1.6KHz
// if (!AFMS.begin(1000)) { // OR with a different frequency, say 1KHz
Serial.println("MDriver not working");
while (1);
}
Serial.println("MDriver working.");
//Setting buttons as pull ups
for (int i = 0 ; i < 2 ; i++) //For each switch
pinMode(RoutinePin[i], INPUT_PULLUP);
}
void loop() {
// put your main code here, to run repeatedly:
void DosingSystem()
}
void DoseR1()
{
static enum {DOSE1ra, DOSE1a, DOSE2ra, DOSE2a, DOSE3ra,
DOSE3a, DOSE4ra, DOSE4a, DOSEr1CMP} pumpR1State = DOSE1ra;
//1ra wait state
//1a dose state
switch (pumpR1State)
{
case DOSE1ra:
//Serial.println("pump1 should have been on after .5 seconds");
if (currentMillis - Routine1Millis >= mD1wait_interval)
{
Dose1->setSpeed(150);
Dose1->run(FORWARD);
mDc_on = currentMillis;
pumpR1State = DOSE1a;
}
break;
case DOSE1a:
if (currentMillis - mDc_on >= mD1run_interval) //will shut down after the run interval is met
{
Dose1->fullOff();
mDc_on = currentMillis;//resetting the difference everytime
pumpR1State = DOSE2ra;
}
break;
case DOSE2ra:
if (currentMillis - mDc_on >= mD2wait_interval) //wait then run
{
Dose2->setSpeed(150);
Dose2->run(FORWARD);
mDc_on = currentMillis; //resetting the difference everytime
pumpR1State = DOSE2a;
}
break;
case DOSE2a:
if (currentMillis - mDc_on >= mD2run_interval) //will shut down after the run interval is met
{
Dose2->fullOff();
mDc_on = currentMillis; //resetting the difference everytime
pumpR1State = DOSE3ra;
}
break;
case DOSE3ra:
if (currentMillis - mDc_on >= mD3wait_interval) //wait then run
{
Dose3->setSpeed(150);
Dose3->run(FORWARD);
mDc_on = currentMillis;
pumpR1State = DOSE3a;
}
break;
case DOSE3a:
if (currentMillis - mDc_on >= mD3run_interval) //will shut down after the run interval is met
{
Dose3->fullOff();
mDc_on = currentMillis; //resetting the difference everytime
pumpR1State = DOSE4ra;
}
break;
case DOSE4ra:
if (currentMillis - mDc_on >= mD4wait_interval) //wait then run
{
Dose4->setSpeed(150);
Dose4->run(FORWARD);
mDc_on = currentMillis;
pumpR1State = DOSE4a;
}
break;
case DOSE4a:
if (currentMillis - mDc_on >= mD4run_interval) //will shut down after the run interval is met
{
Dose4->fullOff();
mDc_on = currentMillis; //resetting the difference everytime
pumpR1State = DOSEr1CMP;
}
case DOSEr1CMP:
// DO something with the web interface probably a data logging or function tracking statement, some led's, some buzzer, still thinking for now.
mDc_on = currentMillis; //resetting the difference everytime
pumpR1State = DOSE1ra;
}
}
void DoseR2(){
}