How to Stop Ultrasonic Sensor From reading Value when condition Met

Hello, Im in confuse about my code.

So the goal is to open the Solenoid valve when the distance is under 20cm, While solenoid opens, the waterflow sensor read the flow until 2000mL reached, then the solenoid valve closed and ultrasonic sensor continue to read the distance.

the problem is whenever the distance is under 20cm the valve opens but ultrasonic sensor keeps reading distance so whenever the waterflow reached 2000mL, the valve wont close. Or if the object moved to the distance more than 20cm the valve immidiately closed. Even though the waterflow is not reading 2000mL yet.

Here's my code:

#include <ezButton.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd = LiquidCrystal_I2C(0x27, 16, 2); 
ezButton button (7);// Flush Button
#define echoPin 4 //Pin echo ultrasonic
#define trigPin 5 //Pin trigger ultrasonic

long duration, cm; //variabel untuk durasi ultrasonic
int distance; //variabel untuk pengukuran jarak 
int inPin = 10; // pin Flush Button
int buttonVal = 0; // Value Flush Button

//int i=0;


/////////////////////PARAMETER FLOW METER///////////////////////
byte statusLed    = 13;
byte sensorInterrupt = 0;  // 0 = digital pin 2
byte sensorPin       = 2;

// The hall-effect flow sensor outputs approximately 4.5 pulses per second per
// litre/minute of flow.
float calibrationFactor = 4.5;

volatile byte pulseCount;  

float flowRate;
unsigned int flowMilliLitres;
unsigned long totalMilliLitres;

unsigned long oldTime;

//////////////////////////////////////////////////////////////

void setup() {
  // INIT LCD
  lcd.init();
  lcd.backlight();
  lcd.clear();

  // Initiate Ultra Sonic
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
  Serial.begin(38400);

  // INIT RELAY
  pinMode (8, OUTPUT);

  //INIT FLUSH BUTTON
  pinMode(inPin, INPUT);
/*
  lcd.print("LOADING...");
  delay (3000);
  lcd.setCursor (0,0);
  lcd.print("AUTO VALVE");
  lcd.setCursor (0,1);
  lcd.print("BY:DEYAPARINATA");
  delay(3000);
  lcd.clear();
*/
  //INIT FLOW METER
   pinMode (8, OUTPUT);
   digitalWrite(8,LOW);
   Serial.println ("Low");
   
  // Initialize a serial connection for reporting values to the host
   Serial.begin(38400);
   
  // Set up the status LED line as an output
   pinMode(statusLed, OUTPUT);
   digitalWrite(statusLed, HIGH);  // We have an active-low LED attached
  
   pinMode(sensorPin, INPUT);
   digitalWrite(sensorPin, HIGH);

  pulseCount        = 0;
  flowRate          = 0.0;
  flowMilliLitres   = 0;
  totalMilliLitres  = 0;
  oldTime           = 0;

  attachInterrupt(sensorInterrupt, pulseCounter, FALLING);
}

void pulseCounter()
{
  // Increment the pulse counter
  pulseCount++;
}

void ultraSonic()
{
  digitalWrite(trigPin, LOW);
  delayMicroseconds(5);
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);
  pinMode(echoPin, INPUT);
  duration = pulseIn(echoPin, HIGH);
  cm = (duration/2) / 29.1;
  Serial.println(cm);
  lcd.setCursor(0,0);
}


void flowMeter()
{
  ///////////////////////////////////////FLOWMETER/////////////////////////////////
    if((millis() - oldTime) > 1000)    // Only process counters once per second
  { 
      detachInterrupt(sensorInterrupt);
        
      
      flowRate = ((1000.0 / (millis() - oldTime)) * pulseCount) / calibrationFactor;
    
      oldTime = millis();
    
     flowMilliLitres = (flowRate / 60) * 1000;
    
     // Add the millilitres passed in this second to the cumulative total
     totalMilliLitres += flowMilliLitres;
      
      unsigned int frac;
    
      // Print the flow rate for this second in litres / minute
      Serial.print("Flow rate: ");
      Serial.print(int(flowRate));  
      Serial.print(".");             // Print the decimal point
      // Determine the fractional part. The 10 multiplier gives us 1 decimal place.
      frac = (flowRate - int(flowRate)) * 10;
      Serial.print(frac, DEC) ;      // Print the fractional part of the variable
      Serial.print("L/min");
      // Print the number of litres flowed in this second
      Serial.print("  Current Liquid Flowing: ");
      Serial.print(flowMilliLitres);
      Serial.print("mL/Sec");

      // Print the cumulative total of litres flowed since starting
      Serial.print("  Output Liquid Quantity: ");
      Serial.print(totalMilliLitres);
      Serial.println("mL"); 

      // Reset the pulse counter so we can start incrementing again
      pulseCount = 0;
    
      // Enable the interrupt again now that we have finished sending output
      attachInterrupt(sensorInterrupt, pulseCounter, FALLING);
  }
}



void loop() {
  
//////////////////////////////////////FLUSH/////////////////////////////////

  button.loop(); //EZButton Library
  //Jika Tombol ditekan, maka relay (pin 10) terbuka selama flow > 0
  if (button.isReleased()){
    flowMeter();
    lcd.println("Button Pressed");
    if (flowMilliLitres < 5){
      digitalWrite(8,LOW);
    }else {
    digitalWrite(8,HIGH);
    } 
  }
//////////////////////////////////////////////////////////////////////////
 
  if (cm<20){
    digitalWrite(8, HIGH);
   flowMeter();
  } else {
    digitalWrite(8, LOW);
    ultraSonic();
  }
}

programming is a repeated two-step-process:

step 1: write down in normal words what shall happen in sequence by hand on a sheet of paper

step 2: translate normal words into code

repeat.

2000 mL sounds like pouring water to wash hands.
please describe what your project is doing.
The solution will depend on what you are doing.

The code will look different between filling a bottle of 2 Liter or washing hands.
That is the reason why it is important to know the complete project.

So please write down the steps in normal words.
Include conditions like "once valve is opened keep valve opened until 2000 mL have flown even if measuring distance results in measuring more than 20cm.

Though if you are filling a bottle that has to stand right in place it would be better to stop pouring the water if the bottle is taken away.

best regards Stefan

Hi, @dionzarek
Welcome to the forum.

You only need to detect the occurrence of the measured distance GOING under 20cm, not being under 20cm.
When you have the pump running, just look at the flow sensor, and ignore the ultrasonic reading.

Make a flag variable that shows if the pump is ON or OFF.
Then put the reading of the distance in an if statement that will only run the read code when the pump is OFF.

Tom.. :grinning: :+1: :coffee: :australia:

thanks @StefanL38 for quick reply

I'm making a tank with automatic valve under the tank, the steps will be:

  1. Ultrasonic will detect whether there is a bottle under the valve or not by measuring the distance.
  2. when the bottle put under the valve (distance <20cm) the valve will automatically open and fill the bottle for 2000mL.
  3. If the bottle have filled 2000mL, the valve will automatically close, and let the ultrasonic read the distance for the next bottle
  4. I'm also making a button for flushing the tank. If the button pressed, the valve will open until there is no water in the tank (waterflow sensor flow rate is 0)

I agree with you, this is also a nice idea, it would be better to stop pouring the water if the bottle is taken away.

I Think because the ultrasonic sensor always reading the distance, so the valve keep opening even when water flowing more than 2000mL because the distance is always <20 cm

You program can be expanded to do a lot of things.
It is just a matter of programming.

So if a bottle is detected you can set a variable acting as a boolean marker
that a bottle has been placed.

Fill bottle
after filing the bottle your program has to wait until the filled bottle is taken away.
Taking away the bottle results in a distance bigger than 20 cm.
This measuring resets your boolean variable "bottle placed"
and only after this reset your program goes back to
"waiting for new bottle" i.e. distance smaller than 20 cm.

This is a classical thing for a software-technique called state- machine.
As you want to do something more complicated than
LED light up if distance is smaller than 20cm
LED switched off if distance is bigger than 20cm

You have to learn a bit more about programming.

There are a lot of tutorials about state machines or finite stae machines that claim to explain how it works.
99% of these turorials are not beginner-friendly. I define beginnerfriendy if a tutorial takes a allday common description to give an overview of the softwares functionality - Or staying very very basic in what it does in programming.

I haven't found yet a tutorial that would come near to my high-level expectations about understandability but this one is quite good
The Finite State Machine | Majenko Technologies.

If somebody knows of other easy to understand state-machine tutorials please post them here. Collecting links of the really good toturials is my hobby.

To give you some additional hints about a state-machine for your project

something similar to this is required

state 1 wait for distance smaller than 20 cm
if yes switch to state 2

state 2
open valve
immitiately switch to state 3

state 3
measure volume until 2000 mL are reached
if 2000 mL switch to state 4

state 4
close valve
immitialy switch to state 5

state 5
wait for distance to become bigger than 20 cm
if distance bigger than 20cm
switch to state 1

switch to state means a variable gets assigned a correlating value that represents the state

example
myState = ....

So give it a try and write a first attempt with using a state-machine.
Whatever questions comes up totally regardless what it is post your complete sketch and ask.

best regards Stefan

Hi @TomGeorge Thanks for replying

ill try to put the ultrasonic on IF and put flag in it to print on serial.

Thanks :laughing: :coffee:

Thank you so much for this reply,

I'll try to understand it since I just knew this kind of programming (The state-machine).
perhaps this kind of programming I'm searching for this project.

I'll keep it update here
Thanks! :laughing: :coffee: :coffee:

You want to dispense 2 liters when anything is within 20 cm. But when you are done dispensing, the thing is probably still within 20 cm so it dispenses again.

After dispensing 2 liters, wait until the distance goes well above 20 cm (maybe 30?) before looking for it to be below 20 again.

  ultraSonic();
  if (cm < 20)
  {
    digitalWrite(8, HIGH);  // Open valve
    flowMeter();
    digitalWrite(8, LOW);  // Close valve
    while (cm < 30)
    {
      ultraSonic();
    }
  }