Friday, August 23, 2019

BLYNK NODEMCU ULTRASONIC JSN-SR04T WATER LEVEL

nodemcu waterproof ultrasonic jsn-sr04t for water level using blynk

//****Virtual Pin Assignments****

// V0 - Blynk Version - labeled value
// V1 - ESP Version    - labeled value
// V2 - Millis Uptime  - labeled value
// V3 - Wifi RSSI        - labeled value
// V4 - Volume            - labeled value
// V8 - Terminal          - terminal
// V9 - Percent            - level V widget -- value 1 -10
//V10 - Numeric Widget - Level Alert
//V11 - Button Widget to cancel alert or turn alert (on or off) --button
//V12 - Distance - height from sensor to water level  -- labeled value

//#define BLYNK_PRINT Serial    // Comment this out to disable prints and save space

#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>

#include <ESP8266mDNS.h>  // For OTA w/ ESP8266
#include <WiFiUdp.h>  // For OTA
#include <ArduinoOTA.h>  // For OTA

char auth[] = "yourAuthCode";

char ssid[] = "changeto your ssid";
char pass[] = "yourpassword";

BlynkTimer timer;

WidgetTerminal terminal(V8);

#define echoPin 14// Echo Pin
#define trigPin 12  // Trigger Pin

#define filterSamples   3              // filterSamples should  be an odd number, no smaller than 3

int maximumRange = 450;
int minimumRange = 20;
int alertLevelCounter = 0; //Counter starts at zero
int volume;
int volume1; // for smoothing algorithum
int percent;
int percent1; // for smoothing algorithum
int levelAlert;
int wateralert = 0;
int sensSmoothArray1 [filterSamples];   // array for holding raw sensor values for sensor1 
int smoothDistance;                     // variables for sensor1 data

double alertInMin = 0.5;                //Alert time following alert water level being reached (0.5 = 30secs)

const int alertDuration = 2;            //Alert sent every 2 minutes

const int waterTankDia = 80;           //Water Tank Diameter (cm)
const int waterTankHt = 100;            //ie. Sensor Height (cm)

long jarak,jarak1;
long duration, distance, distance1;     // Duration used to calculate distance


BLYNK_CONNECTED() { // runs once at device startup, once connected to server.
  Blynk.syncVirtual(V10);
  Blynk.syncVirtual(V11);
}
void MeasureCm() {
 //  The following trigPin/echoPin cycle is used to determine the
 // distance of the nearest object by bouncing soundwaves off of it. 
 digitalWrite(trigPin, LOW); 
 delayMicroseconds(2); 

 digitalWrite(trigPin, HIGH);
 delayMicroseconds(10); 
 digitalWrite(trigPin, LOW);
 duration = pulseIn(echoPin, HIGH);
 //Calculate the distance (in cm) based on the speed of sound.
 distance = duration/58.2;
 if(distance >= 20 ){
 volume = ((waterTankHt*(PI*(sq(waterTankDia/2))))-(distance*(PI*(sq(waterTankDia/2)))))/1000;
 //percent = ((float)volume/9000)*100;
  //jarak = 1-(distance/100);
  //volume = ((0.4 * 0.4 * (1-(distance/100))) *(22/7))*1000;
  percent = (100 - distance);
  //percent = 100 - (distance/3);
   } 
 else{
     if(distance < 20 ){
       volume = 450;
       percent = 100;
     }
 }

  Blynk.virtualWrite(V9, percent); // virtual pin
  Blynk.virtualWrite(V12, distance); // virtual pin
  Blynk.virtualWrite(V4, volume); // virtual pin

void UpTime() {
  Blynk.virtualWrite(2, (millis() / 1000));
  Blynk.virtualWrite(3, WiFi.RSSI());
  //terminal.println(levelAlert);
}


BLYNK_WRITE(V10) {
  levelAlert = param.asInt();
  terminal.print("Water Level Alert: ");
  terminal.println(levelAlert);
  terminal.println();
  terminal.flush();
   
BLYNK_WRITE(V11) { 

  int alertOff = param.asInt();

  if(alertOff == 0) {
resetWaterLevelAlert();
wateralert = 1;
terminal.print("Level Alert is OFF");
terminal.println();
terminal.flush();
  }
  else {
resetWaterLevelAlert();
wateralert = 0;
terminal.print("Level Alert is ON");
terminal.println();
terminal.flush();
  }

}


void checkWaterLevel() {
  
  if(volume1 < levelAlert && wateralert == 0){
 alertLevelCounter += 1;
  }

  if(alertLevelCounter > alertInMin * 60 && wateralert == 0){
Blynk.notify("Water Tank Level Alert"); // send push notification to blynk app
wateralert = 1;
resetWaterLevelAlert();
  }
}

void resetWaterLevelAlert() {
  alertLevelCounter = 0;
  wateralert = 0;
}


void MeasureCmForSmoothing() {
  /* The following trigPin/echoPin cycle is used to determine the
 distance of the nearest object by bouncing soundwaves off of it. */ 

 digitalWrite(trigPin, LOW); 
 delayMicroseconds(2); 

 digitalWrite(trigPin, HIGH);
 delayMicroseconds(10); 
 digitalWrite(trigPin, LOW);
 duration = pulseIn(echoPin, HIGH);

 //Calculate the distance (in cm) based on the speed of sound.
 distance1 = duration/58.2; //for smoothing algorithim

 smoothDistance = digitalSmooth(distance1, sensSmoothArray1);

 {
 if(distance1 >= 20 ) {
   volume1 = ((waterTankHt*(PI*(sq(waterTankDia/2))))-(smoothDistance*(PI*(sq(waterTankDia/2)))))/1000;
   //volume1 = ((((0.4 * 0.4) * (1-(smoothDistance/100))) *(22/7))*1000);
  percent1 = (100 - smoothDistance);

   terminal.print("Uptime (secs): ");
   terminal.println((millis() / 1000));
   terminal.print("Distance: ");
   terminal.println(distance1);
   terminal.print("Smoothed Distance: ");
   terminal.println(smoothDistance);
   terminal.println();
      terminal.print("percent1: ");
   terminal.println(percent1);
   terminal.flush();
   //terminal.print("Percent: ");
   // terminal.println(percent1);
 } 
   else{
    if(distance1 < 20 ){
      volume1 = 450;
      percent1 = 100;
    }
   }  
 }

void UploadMeasureCmForSmoothing() {
Blynk.virtualWrite(V12, smoothDistance); // virtual pin
Blynk.virtualWrite(V4, volume1); // virtual pin
Blynk.virtualWrite(V9, percent1); // virtual pin
  
terminal.print("Uploaded Volume: ");
terminal.println(volume1);
terminal.print("Uploaded Smoothed Distance: ");
terminal.println(smoothDistance);
terminal.println();

terminal.flush();

}

  

void setup() {
 Serial.begin(115200);
 Blynk.begin(auth, ssid, pass, "blynk-cloud.com", 8080);

 ArduinoOTA.setHostname("Water_Tank");  // For OTA - Use your own device identifying name
 ArduinoOTA.begin();  // For OTA

 pinMode(trigPin, OUTPUT);
 pinMode(echoPin, INPUT);

 terminal.clear();
  timer.setTimeout(100, [](){
 timer.setInterval(5000L, UpTime);
 });

 timer.setTimeout(400, [](){
 timer.setInterval(300000L, UploadMeasureCmForSmoothing);  //get a measurement straight up if the device was reset for some reason
 });

 timer.setTimeout(600, [](){
 timer.setTimer(1000L, MeasureCm, 1);
 });
  
 timer.setTimeout(500, [](){
 timer.setInterval(1000L, checkWaterLevel);
 });

 timer.setTimeout(700, [](){
 timer.setInterval(15000L, MeasureCmForSmoothing);
 });

}
void loop() {
  Blynk.run(); // Initiates Blynk
  ArduinoOTA.handle();  // For OTA
  timer.run(); // Initiates SimpleTimer
}

int digitalSmooth(int rawIn, int *sensSmoothArray){     // "int *sensSmoothArray" passes an array to the function - the asterisk indicates the array name is a pointer
int j, k, temp, top, bottom;
long total;
static int i;
// static int raw[filterSamples];
static int sorted[filterSamples];
boolean done;

i = (i + 1) % filterSamples;    // increment counter and roll over if necc. -  % (modulo operator) rolls over variable
sensSmoothArray[i] = rawIn;                 // input new data into the oldest slot

// Serial.print("raw = ");

 for (j=0; j<filterSamples; j++){     // transfer data array into anther array for sorting and averaging
     sorted[j] = sensSmoothArray[j];
 }

   done = 0;                // flag to know when we're done sorting              
 while(done != 1){        // simple swap sort, sorts numbers from lowest to highest
      done = 1;
        for(j = 0; j < (filterSamples - 1); j++){
           if(sorted[j] > sorted[j + 1]){     // numbers are out of order - swap
             temp = sorted[j + 1];
             sorted [j+1] =  sorted[j] ;
             sorted [j] = temp;
             done = 0;
           }
        }
  }

/*
  for (j = 0; j < (filterSamples); j++){    // print the array to debug
Serial.print(sorted[j]); 
Serial.print("   "); 
  }
  Serial.println();
*/
   // throw out top and bottom 15% of samples - limit to throw out at least one from top and bottom
   //  bottom = max(((filterSamples * 15)  / 100), 1); 
   //  top = min((((filterSamples * 85) / 100) + 1  ), (filterSamples - 1));   // the + 1 is to make up for asymmetry caused by integer rounding
   bottom = max(((filterSamples * 20)  / 100), 1); 
   top = min((((filterSamples * 80) / 100) + 1  ), (filterSamples - 1));   // the + 1 is to make up for asymmetry caused by integer rounding
   k = 0;
   total = 0;
  for( j = bottom; j< top; j++){
 total += sorted[j];  // total remaining indices
 k++; 
 //Serial.print(sorted[j]); 
 //Serial.print("   "); 
 //terminal.print(sorted[j]); 
 //terminal.println("   ");
  
  }
   //terminal.print("average: ");
   //terminal.println(total/k);
   //terminal.flush();
   //Serial.println();
   //Serial.print("average = ");
   //Serial.println(total/k);
  return total / k;    // divide by number of samples
}

No comments:

Post a Comment