Hackster is hosting Hackster Holidays, Ep. 7: Livestream & Giveaway Drawing. Watch previous episodes or stream live on Friday!Stream Hackster Holidays, Ep. 7 on Friday!
Manusha_Ramanayake
Published © GPL3+

Wireless Water-Tank Level Meter with Alarm

This circuit measure the water level of a tank and wirelessly send it to a receiver where it is displayed using a LCD display and LEDs.

AdvancedShowcase (no instructions)32,125
Wireless Water-Tank Level Meter with Alarm

Things used in this project

Hardware components

Arduino Nano R3
Arduino Nano R3
×2
Ultrasonic Sensor - HC-SR04
SparkFun Ultrasonic Sensor - HC-SR04
×1
HC-12 Wireless Module
×2
5 mm LED: Red
5 mm LED: Red
×1
5 mm LED: Yellow
5 mm LED: Yellow
×1
5 mm LED: Green
5 mm LED: Green
×1
Buzzer
Buzzer
×1
Through Hole Resistor, 120 ohm
Through Hole Resistor, 120 ohm
×3
Resistor 220 ohm
Resistor 220 ohm
×4
Pushbutton Switch, Pushbutton
Pushbutton Switch, Pushbutton
×2
RGB Backlight LCD - 16x2
Adafruit RGB Backlight LCD - 16x2
×1

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)

Story

Read more

Schematics

Transmitter unit

Receiver unit

Code

Transmitter unit code

C/C++
//  Created and Designed by Manusha Ramanayake 
//  Email   : ramanayakemanusha@gmail.com


//Transmitter and Sensor Unit

# include <SoftwareSerial.h>
SoftwareSerial HC12(4, 5);

//Change the values below to calibrate the meter
int MinLevel = 24; //This is the sensor reading when the tank is empty
int MaxLevel = 102; //This is the sensor reading when the tank is full

int power = 6;
long dist_1 = 0;
long dist_2 = 0;
int Time = 0;
int trig = 3; //trigger pin of ultrasonic sensor
int echo = 2; //Echo pin of ultrasonic sensor

void setup() {
//To calibrate the sensor delete the comment symbols in the following code
	//Serial.begin(9600);
 HC12.begin(9600);
 pinMode(trig, OUTPUT);
 digitalWrite(trig, LOW);
 pinMode(echo, INPUT);
 pinMode(power, OUTPUT);
 digitalWrite(power, 1);
}


void loop() {
 
  Time++;
 // Standerd code for getting value from the ultrasonic sensor
  digitalWrite(trig, LOW); 
  delayMicroseconds(5);
  digitalWrite(trig, HIGH); 
  delayMicroseconds(10);
  digitalWrite(trig, LOW);
  
  dist_1 = ( pulseIn(echo, HIGH))*0.034/2;   //this gets the value in centimeters
  
  if (dist_1 < MaxLevel+100){  //change if needed
  Send_data(dist_1);}
  
 //debuging code
	//Serial.print(dist_1);
	//Serial.print('\n');
  delay(500);
  
} 
void Send_data(int dist_1){
//maps the sensor values to a number between 0 and 100
 int sent = map (dist_1, MinLevel, MaxLevel, 100, 0);

 //This sends data every 100 ms
 if (Time == 100) {  
  HC12.write(sent);
  Time = 0;
 }
 //This sends data instantly when tank water level is changing
 if (dist_1 != dist_2) {   
    HC12.write(sent);
    dist_2 = dist_1;
 }
 
 //To calibrate the sensor delete the comment symbols in the following code
 
 /*
 Serial.print("    sensor read- ");
 Serial.print(dist_1);
 Serial.print("    sent value - ");
 Serial.print(sent);
 Serial.print('\n');
 */
}

Receiver unit code

C/C++
//  Created and Designed by Manusha Ramanayake 
//  Email   : ramanayakemanusha@gmail.com
 
//        Reciver Unit

//Pins
/*  
 *   
 *   --LCD--
 *  RS: pin D12
 *  E: pin D11
 *  D4: pin D2
 *  D5: pin D3
 *  D6: pin D4
 *  D7: pin D5
 *  Vo: A4
 *  D13: gnd
 *  
 *  --HC 12--
 *  Tx: pin 7
 *  Rx: pin 8
 *  
 *  --Button--
 *  B1: pin 9
 *  B2: pin 10
 *  
 *  --LED pins--
 *  G_led: pin A1
 *  R_led: pin A0
 *  Y_led:pin A2
 *
 *  buzzer:A3
*/

// defining libraries
#include <LiquidCrystal.h>   //for LCD 
#include <SoftwareSerial.h>  //for HC-12 wireless module

SoftwareSerial HC12(7, 8);
LiquidCrystal lcd{12, 11, 2, 3, 4, 5};

int backlight_time = 30000;   //The time LCD backlight is turned on in miliseconds
int buzzer_freq = 1000;		//Frequenzy of the buzzer


int refill_time = 17000;    //delay time for the "refilling.." massege
int re_disp_time = 35000;   //"refilling.." massege display time


int refill_Maxtime = 0;
int button1 = 9;
boolean backlight_state = 0;
boolean button2_stat = 0;
boolean button_check = 0;
int button2_state[3] ={ 0, 0, 0};   // to check the button2 is pressed when level is low
int value1 =0;                     
int check1 = 0;
int value2 = 0;
boolean refill_check[3] = {0, 0, 0};  // to check the button2 is pressed when level is high
int data = 50;
int previous_data = 0;
int button2 = 10;
int red_led = A0;
int yellow_led = A2;
int green_led = A1;
int buzzer = A3;
int ground = 13;
int contrast = A4;
int backlight = A5;

// variablals for mult-tasking
long p3Mili = 0;    
long p1Mili = 0;
long p2Mili = 0;
long p4Mili = 0;
long p5Mili = 0;

//custom charachtors for the presantage bar
byte p10[8] = {B00000, B00000, B00000, B00000, B00000, B00000, B00000, B00000};
byte p20[8] = {B10000, B10000, B10000, B10000, B10000, B10000, B10000, B10000};
byte p40[8] = {B11000, B11000, B11000, B11000, B11000, B11000, B11000, B11000};
byte p60[8] = {B11100, B11100, B11100, B11100, B11100, B11100, B11100, B11100};
byte p80[8] = {B11110, B11110, B11110, B11110, B11110, B11110, B11110, B11110};
byte p100[8] = {B11111, B11111, B11111, B11111, B11111, B11111, B11111, B11111};

void setup() {
 //Serial.begin(9600);
  lcd.begin(16,2);
  HC12.begin(9600);

  pinMode(button1, INPUT);
  pinMode(button2, INPUT);
  pinMode(red_led, OUTPUT);
  pinMode(yellow_led, OUTPUT);
  pinMode(green_led, OUTPUT);
  pinMode(buzzer, OUTPUT);
  pinMode(contrast, OUTPUT);
  pinMode(ground, OUTPUT);
  pinMode(backlight, OUTPUT);

  lcd.createChar(0,p10);
  lcd.createChar(1,p20);
  lcd.createChar(2,p40);
  lcd.createChar(3,p60);
  lcd.createChar(4,p80);
  lcd.createChar(5,p100);

  
  analogWrite(contrast,10);
  digitalWrite(ground, 0);

  // Boot-up message
  lcd.setCursor(0,0);
  lcd.print("    WELCOME     ");
  lcd.setCursor(0,1);
  lcd.print("       -Manusha-");
  
}

void loop() {
  unsigned long currentMillis = millis();       // Getinng the current timer for multitasking
  boolean button1_state = digitalRead(button1); //button for backlight
  backlight_on(button1_state);
  while(HC12.available ()){
    lcd.clear();

    data = HC12.read();
    if ((data<104) or (data>=0)){
      previous_data = data;
    }
    if ((data>103) or (data<0)){
      data = previous_data;
    }
    display_bar(data);
    miniNote(data);
    display_present(data);
  }
    button2_stat = button2_check(data);     //Button for muting
    level_1(data);                           //led control and alarm
    
   refill(data);                            
    value1 = data;
    if(value2 < value1){
      refill_check[0] = 1;
    }
    if((value2 != value1)&(value2 != (value1 + 1))) {
      refill_Maxtime = 0;
    }
    value2 = value1;

    if( (data > 90) & (data <110)){         //for muting the refilling alarm
        if (button_check == 0){
             button_check = digitalRead(button2);
        }
    }else button_check = 0;

}

int refill(int data){
  unsigned long currentMillis = millis();
  if(refill_check[0] == 1){     //Starting the timer for check a seconadry value.
     if(refill_check[1] == 0){
       check1 = data;
       p4Mili = currentMillis ;
       refill_check[1] = 1;     //starts the second condition
    }
    }

    if(refill_check[1] == 1){
     if(currentMillis - p4Mili > refill_time){      
       if(check1 < data){
        refill_check[2] = 1;    //start to display refilling message
        refill_check[0] = 0;
        refill_check[1] = 0;
        p4Mili = currentMillis ;
        }else {
          refill_check[0] = 0;
          refill_check[1] = 0;
          
        }
        }}

        
        if (refill_check[2] == 1){
          if((currentMillis - p5Mili < re_disp_time)&((data>=0) & (data<100))&(refill_Maxtime<12000)){  
              refill_Maxtime++;
              lcd.setCursor(0,1);
              lcd.print("Refilling..."); 
                  boolean button1_state = 1;      //turn the backlight 
                  backlight_on(button1_state);
                  button1_state = 0; 
          }else{
            refill_Maxtime = 0;
            refill_check[2] = 0;}

       }else p5Mili = currentMillis ;


        
    if( (data > 90) & (data <100)){ 
       if (button_check == 0){ //check for button press
       if (refill_check[2] == 1){ //check whether refilling is started
              if(currentMillis - p3Mili < 300){ //buzzer delay time
                 tone(buzzer, buzzer_freq);}
  
              else if (currentMillis - p3Mili > (map(data, 90, 100, 700, 300))){    //for lowering effect
               p3Mili = currentMillis;
    }
              else  noTone(buzzer);
     
       }
    }else  noTone(buzzer);
    } else  noTone(buzzer); 
    
    return refill_check;
  }

int button2_check(int data){
	//first alarm starts when the level is below 16%
  if ((data < 16) || (data > 200)){   //for low level alarm
    if (button2_stat == 0){
       button2_stat = digitalRead(button2);
    if (button2_state[0] == 0){   //turn the backlight whenever button is pressed.
     button2_state[0] = 1;        //only run once when limit is below 15
     boolean button1_state = 1;
     backlight_on(button1_state);
     button1_state = 0;
    }
       
  }
 //Second alarm starts when the level is below 10%
   else if((button2_state[1] == 0) & (data < 10)){
     button2_state[1] = 1;      //run once when limit is below 10 
     boolean button1_state = 1; //turn the backlight
     backlight_on(button1_state);
     button1_state = 0;
      button2_stat = 0;
    }
//Third alarm starts when the level is below 5%
   else if((button2_state[2] == 0) & (data < 5)){
     button2_state[2] = 1;    //run once when limit is below 5
     boolean button1_state = 1; //turn the backlight
     backlight_on(button1_state);
     button1_state = 0;
      button2_stat = 0;
    } } 
    
  else {
    button2_state[0] = 0;
    button2_state[2] = 0;
    button2_state[1] = 0;
    button2_stat = 0;
    }
 return button2_stat;
  }

//This function displays a messages
void miniNote(int data){
	
   if ((data < 8) || (data > 200)){
      lcd.setCursor(0,1);
      lcd.print("Almost Empty    "); //Keep 16 charachtors between ""
   }
   else if( (data > 7) & (data < 15)){
      lcd.setCursor(0,1);
      lcd.print("Refill          ");    
   }
   else if ((data >14) & (data < 95)){
      lcd.setCursor(0,1);
      lcd.print("Normal          ");
   }
   else if ((data>94) & (data<101)){
      lcd.setCursor(0,1);
      lcd.print("Tank Full       ");
   }
    else if ((data>100) & (data<110)){
      lcd.setCursor(0,1);
      lcd.print("Overfolwing     ");
   }
}

//For the LEDs
int level_1(int data){
  unsigned long currentMillis = millis();
  //turn red led and buzzer when level is below 15
  if ((data < 16) || (data > 200)){
    digitalWrite(red_led, 1);   
    digitalWrite(green_led, 0);
    digitalWrite(yellow_led, 0);
	
	//for the buzzer
    if (button2_stat == 0){
     if(currentMillis - p3Mili < 300){
      tone(buzzer, buzzer_freq);}
  
    else if (currentMillis - p3Mili > 600){
      p3Mili = currentMillis;
    }
     else {
      noTone(buzzer);
     }
      }
    else noTone(buzzer);     
  }
 //turn yellow led when level is between 15 and 30
  else if ((data > 15) & (data < 31)){
    digitalWrite(yellow_led, 1);//turn yellow led
    digitalWrite(green_led, 0);
    digitalWrite(red_led, 0);
    noTone(buzzer);
  }

 //turn green led  when level is between 30 and 100
  else if ((data > 30) & (data < 110)){
    digitalWrite(green_led, 1);//turn green led
    digitalWrite(yellow_led, 0);
    digitalWrite(red_led, 0);
    
  }
  else {
    digitalWrite(red_led, 0);
    digitalWrite(yellow_led, 0);
    digitalWrite(green_led, 0);
    noTone(buzzer);
  }
  if ((data > 16)&(data<90)){
    noTone(buzzer);   
  }
}

//turns the backlight on
int backlight_on(int button1_state){    //for lcd backlight
  unsigned long currentMillis = millis();
  if (button1_state == 1){
    p2Mili = currentMillis;}
  if(currentMillis - p2Mili < backlight_time){
        digitalWrite(backlight, 1);
      }
  else digitalWrite(backlight, 0);
  }
  
// displays the presantage
void display_present(int data) {
  //Serial.print('\n');
  //Serial.print(data);
  //Serial.print('\n');
  if(data<10){
    lcd.setCursor(14, 1);}  //for one digit values
  if((data<100) & (data>9)){
    lcd.setCursor(13, 1);   //for two digit values
  }
  if((data<1000) & (data>99)){
    lcd.setCursor(12, 1); //for three digit values
  }
    lcd.print(data);
    lcd.print("%");
  
}

//displays the water level as a bar
void display_bar(int data){
  if((data >= 0) & (data < 110)){
    int dplay = map(data, 0, 100, 0, 80);   
    if( dplay > 80){
      dplay = 80;
    }
    int qution = dplay / 5;     //for full blocks
    int reminder = dplay % 5;   //for partial blocks
    
    for(int x=0;x<qution;x++){
    lcd.setCursor(x, 0);
    lcd.write(5);
    }
    lcd.setCursor(qution, 0);
    lcd.write(int(reminder));


  }
}

Credits

Manusha_Ramanayake
0 projects • 19 followers

Comments