For this tutorial, you will need: A water level sensor, Wires, Arduino, Short cup
The wiring of this sensor is straightforward with only three pins to connect. On the left is the signal pin which will connect to an analog input in the Arduino. The middle pin is for power, recommended between 3.3V and 5V. This wire goes into 7 digital pin on the Arduino. The right pin is the ground.
The top of the sensor is not designed to be submerged in water, only the bottom of it. Due to this constraint, the cup that holds this sensor will be only 1.5 inches. If water fills to that point, the rainwater will spill over the sides of the cup and not submerge the top of the sensor. Additionally, to drain the rainwater slowly, there will a needle size pin hole in the side of the cup. This is to allow water to slowly drain away, but also allow water to fill the cup quickly enough to get a decent estimate of the rainfall intensity. A plastic water bottle is a great option for this!
The water level sensor uses water as a kind of resistor. The more water the sensor is immersed in, the better the conductivity, and the lower the resistance. The less water the sensor is immersed in, the poorer the conductivity, and the higher the resistance. The sensor produces an output voltage according to the resistance, which can determine the water level. If we place this sensor in a cup on its own, we can determine if it is raining or not. If it is raining or if it just recently rained, there will be water in the cup that the sensor will detect. A reading of 0 means no rain, a reading of 420 means the cup is filled half-way, and a reading of 500 means the sensor is fully submerged. These values will depend on your sensor, and therefore you will need to calibrate your sensor first. To do this, use a ruler and a cup. Submerge your sensor at known heights (using the ruler) and read the outputs on the serial monitor. The code to do this is below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
/* Water Sensor Reading * Saffron Livaccari * April 1st, 2022 * CPLN571 Sensing the City * University of Pennsylvania * * Original code from: https://lastminuteengineers.com/water-level-sensor-arduino-tutorial/ */ // Sensor pins #define sensorPower 7 #define sensorPin A0 // Value for storing water level int val = 0; void setup() { // Set D7 as an OUTPUT pinMode(sensorPower, OUTPUT); // Set to LOW so no power flows through the sensor digitalWrite(sensorPower, LOW); Serial.begin(9600); } void loop() { //get the reading from the function below and print it int level = readSensor(); Serial.print("Water level: "); Serial.println(level); delay(1000); } //This is a function used to get the reading int readSensor() { digitalWrite(sensorPower, HIGH); // Turn the sensor ON delay(10); // wait 10 milliseconds val = analogRead(sensorPin); // Read the analog value form sensor digitalWrite(sensorPower, LOW); // Turn the sensor OFF return val; // send current reading } |
This code reads the voltage output from the water level sensor in the line val = analogRead(sensorPin);. The output is written to the serial monitor. Submerge the sensor all the way to determine the output value.
Once you know what output is given for when the sensor is fully emerged, the code for reading the rainfall can be ran below. Make sure to change the value (variable “one_half_Inches”) for what your sensor states when the water is 1.5 inches high.
This code reads the water level every 15 minutes. If there is water detected, the code will determine if the water is rising quick enough to send a flood warning. The flood warning is based on the criteria for ‘heavy rain’: rainfall intensity greater than 0.3 inches per hour. Heavy rain is one factor that may cause flooding, but it should be noted that it isn’t the only factor. Rather, heavy rain is the one factor that this sensor can detect.
Within the loop, the code reads the level from the sensor. If the sensor reads 0, then there is no water detected and the code will only print “Water Level: None”. If the sensor reads anything above 0, the code will first start a timer (millis()) and will print the current water level. The code will continue doing this in 15-minute increments until the water level reaches 1.5 inches. This value for 1.5 inches is what we calibrated earlier and stored in the variable one_half_Inches. Once this value is reached, the code will calculate the intensity of how quickly the water rose to 1.5 inches using the time stored in the timer. If the rain was faster than .3 inches per hour, then the code will send a flood warning message and reset the timer back to 0. If the intensity was not reached, the code will reset the timer back to zero.
There is a third if statement included within the loop in case there is any other reading the sensor produced. Each if statement includes a 15-minute delay as well.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 |
/* Water Sensor Reading * April 1st, 2022 * CPLN571 Sensing the City * University of Pennsylvania * Original code from: https://lastminuteengineers.com/water-level-sensor-arduino-tutorial/ */ //Start by defining the pins #define sensorPower 7 #define sensorPin A0 // Defining the variables int val = 0; float heavyRain = 8.33; //0.0000000833 inches per milliseconds * 100000000 // Since the float value only stores 6 decimals, and 0.0000000833 is longer than 6 decimals, // multiply this value by "100000000" to get a value that can be stored as a float float intensity_converted; int one_half_Inches = 500; // Change this value to whatever value sensor reads when it is fully submerged! extern volatile unsigned long timer0_millis; // to reset the timer back to 0 void setup() { pinMode(sensorPower, OUTPUT); digitalWrite(sensorPower, LOW); // Set to LOW so no power flows through the sensor Serial.begin(9600); // For the serial monitor } void loop() { int level = readSensor(); // function is below // first if statement if (level == 0) { // if no water is detected // if there is no water detected, do nothing Serial.println("Water Level: None"); delay(900000); //only read sensor every 15 minutes } // second if statement else if (level > 0) { // if water is detected //if water is detected, start timer noInterrupts (); timer0_millis = 0; // reset the timer back to 0 interrupts (); timer0_millis = millis(); // start the timer Serial.print("Water Level: "); Serial.println(level); // if water level hits >= 1.5 inches, get the time and calculate speed if (level >= one_half_Inches){ // if the sensor is fully submerged level = readSensor(); Serial.print("Water Level: "); Serial.println(level); intensity = level/timer0_millis; // Rainfall intensity is .3 inches per hour for Heavy Rainfall // This equation has '1.5' because the sensor is fully submerged at 1.5 inches // Rainfall intensity is measured as inches per hour, which was converted to inches per milliseconds // Heavy rainfall is equal to anything greater than 0.0000000833 inches per milliseconds intensity_converted = ((1.5/(timer0_millis)* 100000000)); // calculate the intensity of the rainfall event // using 1.5 inches over the time since water was detected on the sensor Serial.print("Intensity (in/millis): "); Serial.println(intensity_converted); Serial.print("Heavy Rain: "); Serial.println(heavyRain); // If the intensity of the rainfall is greater than 0.0000000833 inches per milliseconds // State that there is a flood warning if (intensity_converted >= heavyRain){ Serial.print("The rainfall intensity is: "); Serial.println(intensity_converted); Serial.println("The rainfall is very heavy! Flood Warning!"); } else { // If not intense enough, reset the timer noInterrupts (); timer0_millis = 0; interrupts (); } } delay(900000); // only read sensor every 15 minutes } // third if statement else { // catch all else statement for any other readings Serial.print("Water Level: "); level = readSensor(); Serial.println(level); delay(900000); // only read sensor every 15 minutes } Serial.println(""); } int readSensor() { digitalWrite(sensorPower, HIGH); delay(10); // wait 10 milliseconds val = analogRead(sensorPin); digitalWrite(sensorPower, LOW); return val; } |
REFERENCES
How the sensor works and the original code:
https://lastminuteengineers.com/water-level-sensor-arduino-tutorial/
Intensity of Rainfall:
https://www.baranidesign.com/faq-articles/2020/1/19/rain-rate-intensity-classification