Flow meter and Water Pump keeps overfilling

Hello!
First of all I would like to apologize if there are spelling errors or if I don't make myself clear, English isn't my first language.

With a group of friends we made a project of a small conveyer belt that fills 500 ml bottles with water.
We are pretty pleased with how it turned out but we have a problem.
The programs work for the first 3-4 times it fills the bottle, but after that it overfills them, forcing us to turn off the project altoghether.
Other problem we have is that after the first time it fills the bottle and we put another one it seems to start with volume already (like 10 ml) and sometimes it just skips some volumes (for example it's consistently filling from 140 ml to 150 ml to 160 ml and suddenly it jumps to 200 ml in the serial monitor)
And another problem we have is that the flow meter in the serial monitor varies between like 90 rpm and 400 rpm which is a huge margin of error.
We copied and adapted the flow meter and rpm to volume calculations from a code we found on youtube so we don't really understand at 100% our programming and how the flowmeter and the "interrupts" work.
I'm gonna leave you the code and we hope you can help us understand and solve these problems, if there's any questions I will happily answer them the best I can.

Thank you so much for reading and taking your time!

`int MB = 4;
int MC = 6;
int sensor = A0;
int pin = 3; // sensor pin
int value;
volatile int rpmcont; 
float totalvolume;
float volume;
void rpm () { // interrupt function
  rpmcont = rpmcont + 1;
}
void setup() {
  value = 0;
  totalvolume = 0;
  volume = 0;
  rpmcont = 0;
  //pinMode (pin, INPUT); 
  Serial.begin (9600); 
  Serial.print ("CONVEYER BELT");
  pinMode(MB, OUTPUT);
  pinMode(MC, OUTPUT);
  pinMode(sensor, INPUT);
 
  attachInterrupt (1, rpm, RISING);//interupt function
}

void loop() {
  value = analogRead (sensor);
  if (value < 400) {
    Serial.println ("bottle in");
    Serial.println (rpmcont);
    digitalWrite(MB, HIGH);
    digitalWrite(MC, LOW);
    interrupts(); 
    attachInterrupt (1, rpm, RISING);
    volume  = (rpmcont/350);
    totalvolume = (totalvolume + volume);   
    Serial.print (totalvolume);
    Serial.print (" TOTAL LITERS");
    Serial.print (rpmcont);
    delay(500);
    if (totalvolume > 450) {
      Serial.println("STOP");
      digitalWrite(MB, LOW);
      digitalWrite(MC, HIGH);
      Serial.print(totalvolume);
      delay(3000);
      totalvolume = 0;
      volume = 0;
      rpmcont = 0;
    }
  }
  if (value > 400) {
    Serial.println ("no bottle");
    digitalWrite (MB, LOW);
    digitalWrite (MC, HIGH);
    noInterrupts();
    totalvolume = 0;
      volume = 0;
      rpmcont = 0;
  }
}`

You really don't want to turn off interrupts for extended periods of time like your code does. Interrupts are used to keep track of time, do the Serial communications, etc.

When you use rmpcont in your main code, you need to turn off interrupts, make a copy of the variable and then turn interrupts back on.

If you structure your code like a state machine, you only have to worry about certain things at certain times. Something like this:

const int MB = 4;
const int MC = 6;
const int sensor = A0;
const int flowPin = 3; // sensor pin
volatile int rpmcont;
float totalvolume;

void rpm () { // interrupt function
  rpmcont++;
}

void setup() {
  Serial.begin (9600);
  Serial.print ("CONVEYER BELT");
  pinMode(MB, OUTPUT);
  pinMode(MC, OUTPUT);
  pinMode(sensor, INPUT);
  attachInterrupt (digitalPinToInterrupt(flowPin), rpm, RISING);//interupt function
  Serial.println("Waiting for bottle");
}

enum { WAITING, FILLING, DONE };
int state;

void loop() {
  int value = analogRead (sensor);
  if ( state == WAITING ) {
    // check to see if bottle present
    // and if so, start filling

    if (value < 400) {
      Serial.println("bottle in");
      noInterrupts();
      rpmcont = 0;
      interrupts();
      digitalWrite(MB, HIGH);
      digitalWrite(MC, LOW);
      state = FILLING;
      totalvolume = 0;
    }
  }
  else if ( state == FILLING ) {
    noInterrupts();
    int tempcont = rpmcont;
    interrupts();
    float volume  = (tempcont / 350.0);
    totalvolume += volume;
    Serial.print (totalvolume);
    Serial.print (" TOTAL LITERS");
    Serial.print (tempcont);

    if (totalvolume > 450) {
      Serial.println("STOP");
      digitalWrite(MB, LOW);
      digitalWrite(MC, HIGH);
      Serial.print(totalvolume);
      state = DONE;
    }
    delay(500);
  }
  else if ( state == DONE ) {
    // done filling, wait for bottle to be removed
    if (value > 400) {
      Serial.println ("no bottle");
      state = WAITING;
      Serial.println("Waiting for bottle");
    }
  }
}
1 Like

Thank you so much for your answer and explanation! We will try this on the project now and hopefully it fixes the problem!

If you have additional problems please post an annotated schematic and a picture of how it is assembled.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.