Flow dispenser code

Hello,

I've attempted to implement code to do the following, but I think it could be much cleaner and simpler. Also, I'm not sure if the cycle start portion of the code will work as expected. Any advice would be much appreciated.

Here's what it's supposed to do, note I'm using the flowmeter and button libraries:

When the cycle start button is pressed (not held, just pressed once), the following should occur:

  1. Reset flowmeter totals.
  2. Read flowmeter to determine volume dispensed (CurrentVolume).
  3. If CurrentVolume is less than volumeTarget:
    Open water control valve and turn on LED (Fill() subroutine)
  4. If CurrentVolume is greater than volumeTarget:
    Close water control valve and turn off LED (FillStop() subroutine)
  5. The control valve should never be on for more than 10 seconds at a time to prevent flooding. I think this could be done at the cycle start or at the open water control valve part, but I am struggling to figure out how to put this in.
  6. Print total flow and flow rate to serial port for debugging.
  7. Note, volume target is hard coded currently, but I plan for it to be adjustable in the future.
#include <Button.h>
#include <FlowMeter.h>  // https://github.com/sekdiy/FlowMeter

// enter your own sensor properties here, including calibration points
FlowSensorProperties MySensor = {2.5f, 366.6f, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}};  // Max capacity: 2.5 LPM.  K Factor: 366.6 Hz/LPM
FlowMeter Meter = FlowMeter(2, MySensor);                                         // Define Arduino Pin

// Set control pins
int ledPin = 13;          //Pin of status LED for test
int valvePin = 10;        //Pin of solenoid valve control
Button cycleStart = Button(4, BUTTON_PULLUP_INTERNAL);  // Pin for switch to initiate cycle

// Set variable defaults
int volumeTarget = 1420;  // Default of 1420 mL (6 cups)

// timekeeping variables
long period = 100;          // .1 second (in milliseconds)
long lastTime = 0;

// define an 'interrupt service routine' (ISR)
void MeterISR() {
  // let our flow meter count the pulses
  Meter.count();
}

void setup() {
  // prepare serial communication
  Serial.begin(9600);

  //Initialize and turn off status LED
  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, LOW);

  //Initialize solenoid valve control to off
  pinMode(valvePin, OUTPUT);
  digitalWrite(valvePin, LOW);

  // enable a call to the 'interrupt service handler' (ISR) on every rising edge at the interrupt pin
  attachInterrupt(INT0, MeterISR, RISING);

  // sometimes initializing the gear generates some pulses that we should ignore
  Meter.reset();
}

void loop() {
  if (cycleStart.uniquePress()) {
    Meter.reset();    // Reset totalizer

    // do some timekeeping
    long currentTime = millis();
    long duration = currentTime - lastTime;

    // wait 0.1 seconds between display updates
    if (duration >= period) {

      // process the counted ticks
      Meter.tick(duration);
      if ( Meter.getCurrentVolume() * 1000 < volumeTarget) {
        fill();
      }
      else {
        fillstop();
      }

      // output data
      Serial.println("FlowMeter - current flow rate: " + String(Meter.getCurrentFlowrate()) + " l/min, " +
                     "nominal volume: " + String(Meter.getCurrentVolume()) + " l, ");

      // prepare for next cycle
      lastTime = currentTime;
    }
  }

}

void fill() {
  digitalWrite(ledPin, HIGH);
  digitalWrite(valvePin, HIGH);
}

void fillstop() {
  digitalWrite(ledPin, LOW);
  digitalWrite(valvePin, LOW);
}
}

Professional advice: if it works, don't touch it. If you think something is not working, then more testing is needed until you can be sure one way or the other. In your case, obviously more testing and debugging is required.

Paul

Thanks, I finally was able to test it after getting the correct drivers installed.

The loop runs only one time when the Cycle start is initiated. How would I keep this part running once the cycle start is depressed?

// do some timekeeping
    long currentTime = millis();
    long duration = currentTime - lastTime;

    // wait 0.1 seconds between display updates
    if (duration >= period) {

      // process the counted ticks
      Meter.tick(duration);
      if ( Meter.getCurrentVolume() * 1000 < volumeTarget) {
        fill();
      }
      else {
        fillstop();
      }

      // output data
      Serial.println("FlowMeter - current flow rate: " + String(Meter.getCurrentFlowrate()) + " l/min, " +
                     "nominal volume: " + String(Meter.getCurrentVolume()) + " l, ");

      // prepare for next cycle
      lastTime = currentTime;

Post the whole code, not just a snippet!

Paul

Whole code was in first post, so I just grabbed the relevant part. Here's the entire code again:

#include <Button.h>
#include <FlowMeter.h>  // https://github.com/sekdiy/FlowMeter

// enter your own sensor properties here, including calibration points
FlowSensorProperties MySensor = {2.5f, 366.6f, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}};  // Max capacity: 2.5 LPM.  K Factor: 366.6 Hz/LPM
FlowMeter Meter = FlowMeter(2, MySensor);                                         // Define Arduino Pin

// Set control pins
int ledPin = 13;          //Pin of status LED for test
int valvePin = 10;        //Pin of solenoid valve control
Button cycleStart = Button(4, BUTTON_PULLUP_INTERNAL);  // Pin for switch to initiate cycle

// Set variable defaults
int volumeTarget = 1420;  // Default of 1420 mL (6 cups)

// timekeeping variables
long period = 100;          // .1 second (in milliseconds)
long lastTime = 0;

// define an 'interrupt service routine' (ISR)
void MeterISR() {
  // let our flow meter count the pulses
  Meter.count();
}

void setup() {
  // prepare serial communication
  Serial.begin(9600);

  //Initialize and turn off status LED
  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, LOW);

  //Initialize solenoid valve control to off
  pinMode(valvePin, OUTPUT);
  digitalWrite(valvePin, LOW);

  // enable a call to the 'interrupt service handler' (ISR) on every rising edge at the interrupt pin
  attachInterrupt(INT0, MeterISR, RISING);

  // sometimes initializing the gear generates some pulses that we should ignore
  Meter.reset();
}

void loop() {
  if (cycleStart.uniquePress()) {
    Meter.reset();    // Reset totalizer

    // do some timekeeping
    long currentTime = millis();
    long duration = currentTime - lastTime;

    // wait 0.1 seconds between display updates
    if (duration >= period) {

      // process the counted ticks
      Meter.tick(duration);
      if ( Meter.getCurrentVolume() * 1000 < volumeTarget) {
        fill();
      }
      else {
        fillstop();
      }

      // output data
      Serial.println("FlowMeter - current flow rate: " + String(Meter.getCurrentFlowrate()) + " l/min, " +
                     "nominal volume: " + String(Meter.getCurrentVolume()) + " l, ");

      // prepare for next cycle
      lastTime = currentTime;
    }
  }

}

void fill() {
  digitalWrite(ledPin, HIGH);
  digitalWrite(valvePin, HIGH);
}

void fillstop() {
  digitalWrite(ledPin, LOW);
  digitalWrite(valvePin, LOW);
}
}

Change these lines:
long currentTime = millis();
long duration = currentTime - lastTime;

To: static long currentTime = millis();
static long duration = currentTime - lastTime;

The way you define them, they are new each time loop() is entered.

Or define them before setup().

Paul