#include <Arduino.h>
const uint8_t N = 5;
const uint8_t PIN_PUMP[N] = {4, 5, 6, 7, 8};
const uint8_t PIN_VALVE[N] = {9, 10, 11, 12, 13};
const uint8_t PIN_FLOW[N] = {A0, A1, A2, A3, A4};
const uint8_t PIN_BTN_START = 2;
const uint8_t PIN_BTN_STOP = 3;
uint32_t Vi_set[N] = {5, 3, 4, 2, 6};
uint32_t Vi_cur[N] = {0, 0, 0, 0, 0};
bool flowLast[N] = {false, false, false, false, false};
uint32_t flowLastEdgeMs[N] = {0, 0, 0, 0, 0};
const uint16_t FLOW_DEBOUNCE_MS = 30;
enum State { IDLE, DOSING, DONE, ABORT };
State state = IDLE;
bool readButton(uint8_t pin) {
return digitalRead(pin) == LOW;
}
void setOutputs(bool pumpOn[N], bool valveOn[N]) {
for (uint8_t i = 0; i < N; i++) {
digitalWrite(PIN_PUMP[i], pumpOn[i] ? HIGH : LOW);
digitalWrite(PIN_VALVE[i], valveOn[i] ? HIGH : LOW);
}
}
bool allDone() {
for (uint8_t i = 0; i < N; i++) {
if (Vi_set[i] > 0 && Vi_cur[i] < Vi_set[i]) return false;
}
return true;
}
void flowPollAndCount() {
for (uint8_t i = 0; i < N; i++) {
bool now = digitalRead(PIN_FLOW[i]);
bool prev = flowLast[i];
flowLast[i] = now;
if (!prev && now) {
if (Vi_set[i] == 0) continue;
uint32_t t = millis();
if (t - flowLastEdgeMs[i] < FLOW_DEBOUNCE_MS) continue;
flowLastEdgeMs[i] = t;
uint32_t cur = Vi_cur[i];
if (cur < Vi_set[i]) {
cur++;
if (cur > Vi_set[i]) cur = Vi_set[i];
Vi_cur[i] = cur;
}
}
}
}
void applyState(State newState) {
state = newState;
bool pumpOff[N] = {false,false,false,false,false};
bool valveOff[N] = {false,false,false,false,false};
switch (state) {
case IDLE:
for (uint8_t i = 0; i < N; i++) Vi_cur[i] = 0;
setOutputs(pumpOff, valveOff);
break;
case DOSING:
setOutputs(pumpOff, valveOff);
break;
case DONE:
case ABORT:
setOutputs(pumpOff, valveOff);
break;
}
}
void setup() {
for (uint8_t i = 0; i < N; i++) {
pinMode(PIN_PUMP[i], OUTPUT);
pinMode(PIN_VALVE[i], OUTPUT);
pinMode(PIN_FLOW[i], INPUT);
}
pinMode(PIN_BTN_START, INPUT_PULLUP);
pinMode(PIN_BTN_STOP, INPUT_PULLUP);
applyState(IDLE);
}
void loop() {
static bool lastStart = HIGH;
static bool lastStop = HIGH;
bool startNow = digitalRead(PIN_BTN_START);
bool stopNow = digitalRead(PIN_BTN_STOP);
switch (state) {
case IDLE:
if (lastStart == HIGH && startNow == LOW) applyState(DOSING);
break;
case DOSING:
flowPollAndCount();
bool pumpOn[N], valveOn[N];
for (uint8_t i = 0; i < N; i++) {
bool active = (Vi_set[i] > 0 && Vi_cur[i] < Vi_set[i]);
pumpOn[i] = valveOn[i] = active;
}
setOutputs(pumpOn, valveOn);
if (allDone()) applyState(DONE);
if (lastStop == HIGH && stopNow == LOW) applyState(ABORT);
break;
case DONE:
if (lastStart == HIGH && startNow == LOW) applyState(DOSING);
if (lastStop == HIGH && stopNow == LOW) applyState(IDLE);
break;
case ABORT:
if (lastStart == HIGH && startNow == LOW) applyState(DOSING);
if (lastStop == HIGH && stopNow == LOW) applyState(IDLE);
break;
}
lastStart = startNow;
lastStop = stopNow;
}