Guidance concerning low water level water indication project using Ultrasonic sensor HC-SR04

Hi,
In my quality lab, there's a small water tub (length 8 cm) fixed on hydrolysis oven (for fabric testing). the water should always be present in tub at a certain level (4 cm from bottom). I need to install ultrasonic sensor within tub so that whenever water will be below 4cm, a 220V AC bulb will be turned on. And upon refilling the water, sensor will detect the water level and will turn off the bulb.
For this, I have used 5V relay, arduino UNO and ultrasonic sensor HC-SR04. Let me know, If any additional component is required.

How I'll use new ping library of HC-SR04 in programming to get better and long lasting results.

// Define the pins for the ultrasonic sensor and relay
#define TRIG_PIN 8   // Pin connected to Trig of the ultrasonic sensor
#define ECHO_PIN 7   // Pin connected to Echo of the ultrasonic sensor
#define RELAY_PIN 9  // Pin connected to the relay module

// Variables for ultrasonic sensor readings
long duration;   // To store the time of the echo pulse
float distance;  // To store the calculated distance in cm

// Threshold levels in cm
const float GOOD_LEVEL = 4.0;       // Normal water level (good level)
const float LOW_LEVEL_THRESHOLD = 3.5;  // Below this level, the light will turn on

void setup() {
  // Initialize serial communication for debugging
  Serial.begin(9600);
  
  // Set the ultrasonic sensor pins
  pinMode(TRIG_PIN, OUTPUT);
  pinMode(ECHO_PIN, INPUT);
  
  // Set the relay pin
  pinMode(RELAY_PIN, OUTPUT);
  digitalWrite(RELAY_PIN, LOW);  // Initially turn off the relay
}

void loop() {
  // Measure the distance using the ultrasonic sensor
  distance = measureDistance();
  
  // Debugging: Print the distance
  Serial.print("Distance: ");
  Serial.print(distance);
  Serial.println(" cm");

  // Logic to control the relay based on water level
  if (distance >= 0 && distance <= LOW_LEVEL_THRESHOLD) {
    // If water level is below or equal to 3.5 cm, turn on the light
    digitalWrite(RELAY_PIN, HIGH);
    Serial.println("Light ON: Water level is LOW.");
  } else if (distance >= 0 && distance > GOOD_LEVEL) {
    // If water level is at or above 4 cm, turn off the light
    digitalWrite(RELAY_PIN, LOW);
    Serial.println("Light OFF: Water level is GOOD.");
  }

  // Delay before the next measurement
  delay(1000);  // 1 second delay
}

// Function to measure the distance using the ultrasonic sensor
float measureDistance() {
  // Send a 10-microsecond pulse to the Trig pin
  digitalWrite(TRIG_PIN, LOW);
  delayMicroseconds(2);
  digitalWrite(TRIG_PIN, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIG_PIN, LOW);
  
  // Measure the time of the echo pulse
  duration = pulseIn(ECHO_PIN, HIGH);
  
  // Calculate the distance in cm
  float distance = (duration * 0.0343) / 2;  // Speed of sound: 343 m/s
  
  // Return the calculated distance
  return distance;
}

As, i'm a beginner in programming so please guide me in achieving my requirement.
Thankyou.

I would suggest you use a waterproof ultrasonic sensor like the JSN-SR04T Ultrasonic Sensor as the HC-SR04 is not waterproof and might get damaged.
The image below is an image of the Waterproof JSN-SR04T Ultrasonic Sensor

I’d be looking at your power supply.
Driving any significant load from an Arduino is not a great idea.

If this is really what you’re doing, replace the relay with an SSR, and either way, be careful of your mains wiring.

Thanks for your suggestion, Yes, It's waterproof but It's minimum range is 20-25cm, whereas my requirement is 4cm. I've already tested it.

Relay that I'm using has maximum current range upto 10A. Means It can bear arduino (20-40mA) can operate on it?

for detecting water levels in small containers I have used TOF sensors and capacitive sensors, e.g. Grove - Water Level Sensor
also used a JSN-SR04T waterproof ultrasonic sensor for checking river levels, however it's range is specified as 25-450 cm so may not be suitable for your application

10A is the current through the relay contacts on the load side. You need to look at what the relay coil needs. A 5V wall wart is a much smarter choice to power the relay. OR even better switch to a MOSFET to replace the relay.

I was so sure I'd have to say something about hysteresis.

// Threshold levels in cm
const float GOOD_LEVEL = 4.0;       // Normal water level (good level)
const float LOW_LEVEL_THRESHOLD = 3.5;  // Below this level, the light will turn on

Nope!

a7

Can I use BC547 Transistor for Arduino to safely control the relay, instead of MOSFET.

Yes, I've implemented hysteresis in my code with a 0.5cm buffer. The light activates when water drops below 3.5cm and turns off when it rises above 4.0cm. This prevents rapid switching from small water movements or sensor fluctuations. Is there anything else I should consider in my implementation?

I did fly fairly low about your code and I don't have but one suggestion.

I did not build the project or run the sketch, both of which would be fairly straightforward using the wokwi simulator, which I mention merely to bring it to your attention.

It is very faithful and usually I am able to get the logic of a program perfected before ever introducing (or even buying) any hardware, and allows me to postpone the inevitable fun of dealing with real wires and parts and power supplies and you get the idea.

Oh, the suggestion: on further thought, it is unimportant. I make my code do quite a bit of talking through the serial monitor during development, and often just leave it in - most times, there is no trouble just letting those bits fly out and go nowhere. Never opening the serial monitor window is no problem. I only say most times because the Arduino is huge and I play over in the low end corner where this is no problem.

So even during development printing can be annoying and something frequently printed at like 100 Hz can make seeing something that happens once every so often scroll away too soon.

I employ a variety of patterns to reduce what is informally referred to as spam. In this sketch, for example, the code will turn on and print saying it has done once a second until the lower threshold is exceeded. Similarly it will turn off and say so until the measurement falls below the upper threshold.

Turning on something that is already on is no problem here, but might in some other case. Same with turning off. You could add a condition to each of the tests so the body of the if statements only run if necessary - a boolean variable that knows whether it is already on or off.

You could remove the else, I like to in the case of hysteresis.

if it is too cold turn on the heat

if it is warm enough turn off the heat

kinda thing.

As a relentless out-denter, I would rearrange the loop

void loop() {
  delay(1000);  // just once a second
  
  distance = measureDistance();
  
  Serial.print("Distance: ");
  Serial.print(distance);
  Serial.println(" cm");

  if (distance < 0) return;		// all done. Does this even happen?
  
  if (distance <= LOW_LEVEL_THRESHOLD) {
    digitalWrite(RELAY_PIN, HIGH);
    Serial.println("Light ON: Water level is LOW.");
  }
  
  if (distance > GOOD_LEVEL) {
    digitalWrite(RELAY_PIN, LOW);
    Serial.println("Light OFF: Water level is GOOD.");
  }
}

Later in your career if you make one here, you can run the thing that wants to be done once a second without using delay(); this will leave the 99.99 percent waste of a perfectly good microprocessor with plenty of time to do anything else. delay() is called blocking code - literally nothing else happens. If you have nothing else to do, no large deal, but if you wanted to add stuff to this or in another project it would be a problem.

You are off to a good start here.

a7

1 Like