Sorry for that, I could have explained up front. This is a nutrient mixing machine that waters deep water culture hydroponics plants. It has several things it does, among them dosing and mixing nutrients into a bucket and also pumping those nutrients into reservoirs to feed the plants and draining those out. It will/has cycles for cleaning itself and flushing the system. The capabilities are a work in progress.
Here's all of the code, which isn't ready for the machine yet at all. I do have functional code which does what I want, but it is not good and will evolve poorly.
class CA { // character array - "safe" featureless string replacement for comparison and printing
public:
char characters[20];
bool operator==(const CA& other) const {
for (int i = 0; i < 20; ++i) {
if (characters[i] != other.characters[i]) {
return false;
}
}
return true;
}
};
// valves control the output line for the main pump
struct Valve {
CA name;
int pin;
};
Valve Valves[4];
Valve VALVE_INPUT = {CA{"INPUT VALVE"}, 11};
Valve VALVE_MIX = {CA{"MIXING VALVE"}, 11};
Valve VALVE_RES_1 = {CA{"RES 1 VALVE"}, 11};
Valve VALVE_RES_2 = {CA{"RES 2 VALVE"}, 11};
struct Sensor {
CA name;
int pin;
};
Sensor Sensors[9];
Sensor LEVEL_MIX_LOW = {CA{"MIX LOW"}, 11};
Sensor LEVEL_MIX_MID = {CA{"MIX MID"}, 11};
Sensor LEVEL_MIX_HIGH = {CA{"MIX HIGH"}, 11};
Sensor LEVEL_RES_1_LOW = {CA{"RES_1 LOW"}, 11};
Sensor LEVEL_RES_1_MID = {CA{"RES_1 MID"}, 11};
Sensor LEVEL_RES_1_HIGH = {CA{"RES_1 HIGHJ"}, 11};
Sensor LEVEL_RES_2_LOW = {CA{"RES_2 LOW"}, 11};
Sensor LEVEL_RES_2_MID = {CA{"RES_2 MID"}, 11};
Sensor LEVEL_RES_2_HIGH = {CA{"RES_2 HIGH"}, 11};
struct Pump {
CA name;
int pin;
};
Pump Pumps[8]; // DOSING PUMPS
Pump WaterPumps[3]; // WATER PUMPS
Pump PUMP_MAIN = {CA{"PUMP MAIN"}, 10};
Pump PUMP_DRAIN_1 = {CA{"PUMP DRAIN 1"}, 10};
Pump PUMP_DRAIN_2 = {CA{"PUMP DRAIN 2"}, 10};
Pump PUMP_SILICA = {CA{"SILICA"}, 11};
Pump PUMP_THRIVE = {CA{"SUPERTHRIVE"}, 12};
Pump PUMP_MICRO = {CA{"MICRO"}, 13};
Pump PUMP_BLOOM = {CA{"BLOOM"}, 14};
Pump PUMP_GROW = {CA{"GROW"}, 15};
Pump PUMP_NECTAR = {CA{"NECTAR"}, 16};
Pump PUMP_WET = {CA{"NATURAL WET"}, 17};
Pump PUMP_PEROXIDE = {CA{"PEROXIDE"}, 18};
// formula refers to a configuration of pump run, mix and rest times
struct Formula {
CA name;
int doses;
Pump pumps[8];
int run_times[8];
int mix_times[8];
int rest_times[8];
};
Formula Formulas[8];
Formula CurrentFormula;
Formula SEEDLING = {
CA{"SEEDLING"},
8,
{PUMP_SILICA, PUMP_THRIVE, PUMP_MICRO, PUMP_BLOOM, PUMP_GROW, PUMP_NECTAR, PUMP_WET, PUMP_PEROXIDE},
/*RUN*/ {11, 12, 13, 14, 15, 16, 17, 18},
/*MIX*/ {21, 22, 23, 24, 25, 26, 27, 28},
/*REST*/ {31, 32, 33, 34, 35, 36, 37, 38}
};
Formula GROW_MIN = {
CA{"GROW MIN"},
5,
{PUMP_SILICA, PUMP_THRIVE, PUMP_MICRO, PUMP_BLOOM, PUMP_GROW},
/*RUN*/ {11, 12, 13, 14, 15},
/*MIX*/ {21, 22, 23, 24, 25},
/*REST*/ {31, 32, 33, 34, 35}
};
Formula GROW_MAX = {
CA{"GROW MAX"},
5,
{PUMP_SILICA, PUMP_THRIVE, PUMP_MICRO, PUMP_BLOOM, PUMP_GROW},
/*RUN*/ {11, 12, 13, 14, 15},
/*MIX*/ {21, 22, 23, 24, 25},
/*REST*/ {31, 32, 33, 34, 35}
};
enum states {
MIX, // mix a formula
DOSE_START,
DOSE_END,
DELAY,
REST,
IDLE
} STATE;
unsigned long DELAY_START;
int DELAY_FOR;
void Delay(int dur) {
STATE = DELAY;
DELAY_START = millis();
DELAY_FOR = dur;
}
states NEXT_STATE;
int currentDelay;
int currentRest;
Pump currentPump;
int mixingIndex = 0;
void loop() {
switch (STATE) {
case MIX:
currentPump = CurrentFormula.pumps[mixingIndex];
currentDelay = CurrentFormula.mix_times[mixingIndex];
currentRest = CurrentFormula.rest_times[mixingIndex];
mixingIndex++;
if (mixingIndex < 7) {
STATE = IDLE;
} else {
STATE = DOSE_START;
}
break;
case DOSE_START:
digitalWrite(currentPump.pin, HIGH);
NEXT_STATE = DOSE_END;
Delay(currentDelay);
break;
case DOSE_END:
digitalWrite(currentPump.pin, LOW);
STATE = REST;
break;
case REST:
NEXT_STATE = MIX;
Delay(currentRest);
break;
case DELAY: // use Delay(duration)
if (millis() - DELAY_START < DELAY_FOR) {
STATE = NEXT_STATE;
}
break;
case IDLE: // waiting for a button to change the state
break;
}
}
void setup() {
Serial.begin(9600);
Serial.println("");
Formulas[0] = SEEDLING ;
Formulas[1] = GROW_MIN ;
Formulas[2] = GROW_MAX ;
Valves[0] = VALVE_INPUT ;
Valves[1] = VALVE_MIX ;
Valves[2] = VALVE_RES_1 ;
Valves[3] = VALVE_RES_2 ;
WaterPumps[0] = PUMP_MAIN ;
WaterPumps[1] = PUMP_DRAIN_1 ;
WaterPumps[2] = PUMP_DRAIN_2 ;
Pumps[0] = PUMP_SILICA ;
Pumps[1] = PUMP_THRIVE ;
Pumps[2] = PUMP_MICRO ;
Pumps[3] = PUMP_BLOOM ;
Pumps[4] = PUMP_GROW ;
Pumps[5] = PUMP_NECTAR ;
Pumps[6] = PUMP_WET ;
Pumps[7] = PUMP_PEROXIDE ;
Sensors[0] = LEVEL_MIX_LOW ;
Sensors[1] = LEVEL_MIX_MID ;
Sensors[2] = LEVEL_MIX_HIGH ;
Sensors[3] = LEVEL_RES_1_LOW ;
Sensors[4] = LEVEL_RES_1_MID ;
Sensors[5] = LEVEL_RES_1_HIGH ;
Sensors[6] = LEVEL_RES_2_LOW ;
Sensors[7] = LEVEL_RES_2_MID ;
Sensors[8] = LEVEL_RES_2_HIGH ;
Serial.println("CONFIGURED FORMULAS;");
for (int i = 0; i < 9; i++ ) {
if (Formulas[i].doses) {
Serial.print("FORMULA: "); Serial.println(Formulas[i].name.characters);
for (int j = 0; j < 7; j++) {
if (Formulas[i].pumps[j].pin) {
Serial.print("PUMP: "); Serial.print(Formulas[i].pumps[j].name.characters);
Serial.print(" ON PIN: "); Serial.print(Formulas[i].pumps[j].pin);
Serial.print(" DUR: "); Serial.print(Formulas[i].run_times[j]);
Serial.print(" MIX: "); Serial.print(Formulas[i].mix_times[j]);
Serial.print(" REST: "); Serial.println(Formulas[i].rest_times[j]);
}
}
}
}
}