As mentioned, problems like this are almost always solved using the state machine concept, millis() timing, and edge detection for your activation switch. You also need to be careful about disabling interrupts before accessing shared (volatile) variables and not trying to do too much while they are disabled.
Below is the framework for the code I’d use. You need to fill in your computation and printing details. Using enums and ‘switch()’ statements / ‘case’ clauses makes it very is to expand the state machine should more complex behavior be required in the future. I also personally find this framework format more aesthetically acceptable than the posted code.
const byte relayPin = 5;
const byte ledPin = 13;
const byte sensorPin = 2;
const byte sensorInterrupt = digitalPinToInterrupt(sensorPin);
const int startpin = 4;
const int totalFlowRequired = 1000;
const unsigned long samplePeriod = 1000;
byte lastButtonState;
unsigned long oldTime, totalMilliLitres;
volatile int pulseCount = 0;
enum machineState {waiting, dispensing};
machineState currentMachineState = waiting;
void setup() {
// Initialize a serial connection for reporting values to the host
Serial.begin(38400);
pinMode(startpin, INPUT_PULLUP);
pinMode(sensorPin, INPUT_PULLUP);
pinMode(ledPin, OUTPUT);
pinMode(relayPin, OUTPUT);
digitalWrite(relayPin, LOW);
digitalWrite(ledPin, HIGH); // Active-low LED
lastButtonState = digitalRead(startpin);
attachInterrupt(sensorInterrupt, pulseCounter, FALLING);
}
void loop()
{
byte currentButtonState;
int currentCount;
unsigned long period;
currentButtonState = digitalRead(startpin);
switch (currentMachineState) {
case waiting:
if (currentButtonState != lastButtonState) {
if (currentButtonState == 0) {
currentMachineState = dispensing;
totalMilliLitres = 0;
noInterrupts();
pulseCount = 0;
interrupts();
digitalWrite(relayPin, HIGH);
oldTime = millis();
digitalWrite(ledPin, LOW);
// Print "Start Up" message to Serial as desired
}
}
break;
case dispensing:
period = millis() - oldTime;
if (period >= samplePeriod) {
noInterrupts();
currentCount = pulseCount;
pulseCount = 0;
interrupts();
oldTime += samplePeriod;
//
// Here you should use 'currentCount' and 'period' to compute
// how many mL flowed during the last ~1 second period. Add this number
// to 'totalMilliLitres' which is the running total. Can also use
// 'currentCount' and 'period' to compute flow RATE during this time.
// Print results to Serial as desired
//
//
if (totalMilliLitres >= totalFlowRequired) {
// Enough fluid has been dispensed
digitalWrite(relayPin, LOW);
digitalWrite(ledPin, HIGH);
currentMachineState = waiting;
// Print "Flow Stopped" message to Serial as desired
}
}
break;
default:
break;
}
lastButtonState = currentButtonState;
}
/* Insterrupt
Service Routine
*/
void pulseCounter()
{
// Increment the pulse counter
pulseCount++;
}