Project tutorial

Portable Environment Monitor © GPL3+

A handheld monitor for young scientists to get familiar with various aspects of the surrounding environment.

  • 2,187 views
  • 2 comments
  • 6 respects

Components and supplies

Apps and online services

About this project

Background Story

Today we are in a world where we can see many forest cutting, water pollution and so many things that destroy our environment. Currently there are so many organizations to stand against them. But that's not enough. If we can make our young generation to stand against them, it will lead to a green future.

To make them environmental lovers, we should give them the opportunity to spend time with trees, lakes, birds etc. In the meantime if they can observe the things and changes in the environment, they will gain knowledge on analyzing the various facts that the environment depends on. With this intention, I started working on a portable device, which can be carried and monitor several aspects of the environment.

This device will make our young generation interested in getting readings at various places of the environment, analyze the data and make conclusions. As an example, water quality of a lake can be monitored at various places and identify if there are any toxic sources which add unnecessary things to water.

The very special thing about this device is even a small kid can make this device on his own as I have avoided soldering and other risky actions. Almost all things are in plug and play style to make it easy for our small generation to make their own experiment kits.

What powers this device?

I have chosen Arduino 101 board for this device as it contains an inbuilt IMU and Bluetooth Low Energy modules. The Intel Curie helps to process our data faster as we are going to use several sensors and filters.

Let's see what we need.

Basic Sensors and Modules

I have planned to develop this Portable Environment Monitor in two steps. At the initial steps some basic sensors are included to get various data from the environment.

The list of sensors is mentioned at the beginning.

Using these sensors we are going to measure following aspects of our environment.

  • Light Intensity
  • Humidity
  • Temperature
  • Sound Level
  • Soil Moisture Level
  • Ion Level in Water

Let's start plugin and coding.

Connect Sensors with Arduino 101

Before beginning, Arduino 101 plugin should be installed. After opening the Arduino IDE go to Tools > Boards > Board Manager and select "Genuino 101" from the list and install. Now the IDE is ready to work with the 101 board.

Plug the Grove base shield to the Arduino board to make it easy to connect sensor modules.

First we connect the RGB LCD screen. Connect the LCD module to an I2C port of the Base shield using a universal cable.

Download and extract the Arduino library for the RGB LCD to the Documents > Arduino > libraries folder.

Open the Arduino IDE and select Genuino 101 under "Tools > Boards". Go to File > Examples > Grove_RGB_LCD > HelloWorld. Plug the Arduino board to the computer and upload the code by clicking on the right arrow button.

Now the LCD displays text as follows.

You can change the backlight color by changing the following Red , Green and Blue values.

const int colorR = 255; 
const int colorG = 0; 
const int colorB = 0; 

Take DHT11 temperature and Humidity sensor and connect it as follows.

  • Vcc > D2
  • Gnd > D1
  • Data > D3

Add DHT library and Adafruit sensors library to the Arduino libraries.

Now test the sensor by uploading the DHTtester code under examples. Open the serial monitor by clicking on the magnifying glass icon at the top right corner to monitor the temperature and humidity readings.

Connect the Light sensor module to A1 port of the Base shield using a universal cable. For this, a library doesn't require. We just have to read the analog values to measure the light intensity.

According to my observations, the analog values from the light sensor are nearly equal to the actual light intensity in "lux". "lux" is a unit which is used to measure the light intensity. Here are some light intensity values.

Let's display the values from the DHT11 and light sensor on the LCD display. Find the code file "Display" from the code files at the end of this tutorial and upload it.

As we have limited number of 5V and Gnd pins, I have defined additional pins to power up the DHT11 module using the following code.

   pinMode (2,OUTPUT); 
   digitalWrite(2,HIGH);  // Make D2 a 5V pin
   pinMode (1,OUTPUT);    // Make D1 a Gnd pin

Now, you can notice that the temperature, humidity and light intensity values are displayed on the LCD. Try to cover the light sensor, blow air to the DHT 11 and observe the changes in readings.

Now we move into a bit hard level. Just connecting and reading values are not enough for remaining sensors. We have to map the readings to get values with standard units. For this we need to use mathematical functions.

Let's begin with the sound detector.

Connect the Sound detector module to the base shield using jumper wires.

  • Vcc > 5V
  • Gnd > Gnd
  • Envelop > A1

Open the AnalogReadSerial code from File > Examples > Basics. Change the pin number to A0 in the following code line.

int sensorValue = analogRead(A1); 

After uploading the code open the Serial Plotter from Tools menu. We can notice a graph is plotting according to the sound level. Make some noise and observe the changes in the graph.

We are getting a voltage level according to the sound level. But the standard unit to measure the sound level is decibel. Hence, the voltage value needs to convert to a decibel value, using a mathematical function. Following is the general formula to achieve this.

dB = 20*log(Vo/Vref)

Though this is the ideal formula, we have to adjust this a bit according to our sensor. Use this chart as a reference to adjust our mathematical function. Vo is the raw voltage value and Vref is the maximum voltage resolution which is 1023. Therefore Vo is multiplied by (1/1023). We can change this value in order to achieve the required sound levels according to the chart. For my sensor, the function is as follows.

double d = 20*(log10(10*v)) ; 

Now, we can measure the sound level in decibel scale using this function.

Connect the two probes to the soil moisture sensor module and connect the module to the base shield.

  • Vcc > A3
  • Gnd > Gnd
  • Signal/Data > A2

The sensor values can be read using the AnalogReadSerial code. But the readings must be mapped in order to get useful values. Mainly this sensor can be used to measure the moisture level in soil and to measure the ion levels in water.

I collected some soil samples with different moisture levels and dipped the probes into soil. After taking the readings 2 threshold values are made to identify 3 moisture stages as dry, medium and high. Repeated the same process by collecting some water samples (drinking water, clean lake, polluted water).

In soil, if the analog reading is

  • Greater than 900 - Dry,
  • Between 650 and 900 - Medium moisture
  • Below 650 - High moisture level

For water testing, if the reading is

  • Greater than 750 - Error
  • Between 600 and 750 - Distilled water
  • Between 500 and 600 - Drinking water
  • Between 350 and 500 - Good for fish but not for drinking
  • Below 350 - Polluted water with high ionic levels and toxic

Now the basic things are done. Let's put all these in to our code file and display on the LCD. But wait... LCD is not enough to display all these information at once. Several pages are needed to display them with clear labels. We can use our button module to move between pages.

Following is my arrangement.

  • 1st page - Temperature, Humidity and Light Intensity
  • 2nd page - Sound level
  • 3rd page - Water quality and Soil moisture level

Connect the button module to D8 port using a universal cable. A button can be read using the digitalRead function. I'm using the variable "page" to change between pages when the button is pressed.

int page = 0; 
void loop() {
   while (page == 0){ 
     first_page(); 
     if (digitalRead(button) == 1)  //Go to the second page when button is pressed
        page++; 
} 
   delay(500); 
   while (page == 1){ 
     second_page(); 
     if (digitalRead(button) == 1)  //Go to the third page when button is pressed
         page++; 
   } 
   delay(500); 
   while (page == 2){ 
     third_page(); 
     if (digitalRead(button) == 1) //Go to the first page when button is pressed
         page = 0; 
   } 
   delay(500); 
} 

Upload the "Basic_1.ino" code file to see how our device works.

Working with IMU

Arduino 101 board has an inbuilt IMU. We can get readings from the accelerometer and the gyroscope according to our needs. For our project I will use these values to calculate pitch and roll angles to measure the angle of surfaces.

Upload the Accelerometer and Gyro codes (Examples > CurieIMU ) and check how this inbuilt IMU works. Using acceleration values in x,y and z axes the roll and the pitch can be calculated according to following formulas.

Following code lines can be used in our Arduino code to calculate pitch and roll angles.

 CurieIMU.readAccelerometerScaled(accX, accY, accZ); 
 double roll  = atan2(accY,accZ) * RAD_TO_DEG; 
 double pitch = atan(-accX / sqrt(accY * accY + accZ * accZ)) * RAD_TO_DEG;  

Now, we need to display these angles on LCD. I'm using the second page for this as currently we planned only to display the noise level on second page.

Using Filters

When observing the light intensity, noise level and the roll and pitch angles you may notice that the values are changing rapidly. Sometimes it's hard to read an exact value because of this problem. Following image shows the light sensor readings with a constant light level.

To avoid this variation and stabilize readings up to some level, we need to use filters. But at the beginning, we can calculate an average value from several readings. The average gets stable with the number of samples. This is the most basic filter that we can use.

Following is the code to calculate the average value for the light intensity.

   int light_l = 0; 
   for (int x=0; x<50;x++){ 
     light_l = light_l + analogRead(light);  
   } 
   light_l = light_l/50; 

When it comes to IMU, we can use more advanced filters to stabilize roll and pitch angles. Kalman filter is one of the best filters which we can use to filter the noise and stabilize readings.

To understand this filter, we need good mathematical knowledge. Hence, I will not explain how this filter works but if you are interested you can refer online articles.

Following video shows how my Kalman filter works for the roll angle.

Observe the stability of the filtered values over raw readings.

Since this algorithm is quite complex and lengthy, I have attached a separate header and source files with my Arduino code. Following variables in the "Kalman.h" file, are need to be adjusted to stabilize the sensor readings. These values varies from sensor to sensor.

Q_angle = 0.01;
Q_bias = 0.0001;
R_measure = 0.11; 

I have tuned these values for Intel Curie IMU, which is in the Arduino 101 board as we are going to use it as our IMU. With this tuning, we can get the filtered values with the accuracy of 0.05 degress.

After uploading the "Final.ino" code our second page will look like this.

Experiments

There are many experiments which can perform using this "Portable Environment Monitor".

Unique Plants for Forests

There are various areas in forests which have unique conditions. According to these conditions the plants are unique for that place. If we consider the light intensity, sometimes the particular area might have low light intensity. Hence, we can say that the plants in that area prefer low light conditions.

Here I have demonstrated how we can take the readings to analyze about plants in forests.

Mountain Areas

The main problem in mountain areas is rock slipping. We can identify this earlier if we monitor the soil moisture level and incline of the tree trunks time to time. If the soil moisture level is high, there is a high possibility for rock slipping. At the initial stages we can observe that the incline of the tree trunks is changing a bit by bit. Hence, using this device we can identify a rock slipping situation and it will help us to take precautions.

Apart from these things, you can monitor noise levels in construction sites and decide it's good or bad for the surrounding trees and animals.

Try to make this device at your home and do various experiments. Ideas and Suggestions are welcome.

Hope you enjoyed this project.

Thank You.

Code

Basic_1.inoArduino
 #include <Adafruit_Sensor.h>
#include "DHT.h"         //include DHT library
#define DHTPIN 3         //define as DHTPIN the Pin 3 used to connect the Sensor
#define DHTTYPE DHT11    //define the sensor used(DHT11)
#define light A0
#define noise A1
#define moist A2
#define button 8
DHT dht(DHTPIN, DHTTYPE);//create an instance of DHT
#include <Wire.h>
#include "rgb_lcd.h"
#include "math.h"

rgb_lcd lcd;

const int colorR = 0;
const int colorG = 30;
const int colorB = 55;

int page = 0;

void setup() 
{
    // set up the LCD's number of columns and rows:
    Serial.begin(9600);
    lcd.begin(16, 2);
    dht.begin(); 
    lcd.setRGB(colorR, colorG, colorB);
    pinMode(light,INPUT);
    pinMode(noise,INPUT);
    pinMode(button,INPUT);
    pinMode (2,OUTPUT);
    pinMode (A3,OUTPUT);
    digitalWrite(2,HIGH);
    digitalWrite(A3,OUTPUT);
    pinMode (1,OUTPUT);
}

void loop() 
{
    while (page == 0){
      first_page();
      if (digitalRead(button) == 1)
         page++;
    }
    delay(500);
    while (page == 1){
      second_page();
      if (digitalRead(button) == 1)
          page++;
    }
    delay(500);

    while (page == 2){
      third_page();
      if (digitalRead(button) == 1)
          page = 0;
    }

    delay(500);

}

void first_page(){

  int h = dht.readHumidity();    // reading Humidity 
    int t = dht.readTemperature();
    int light_l = 0;
    
    for (int x=0; x<50;x++){
      light_l = light_l + analogRead(light);
      delay(2);
    }

    light_l = light_l/50;
    lcd.setCursor(12, 1);
    lcd.print("  lx");
    lcd.setCursor(0, 0);
    lcd.print("Temp ");
    lcd.setCursor(0, 1);
    lcd.print(t);
    lcd.setCursor(2, 1);
    lcd.print("_C ");
    
    lcd.setCursor(5, 0);
    lcd.print("Humid");
    lcd.setCursor(6, 1);
    lcd.print(h);
    lcd.setCursor(8, 1);
    lcd.print("%");
    
    lcd.setCursor(11, 0);
    lcd.print("Light");
    lcd.setCursor(11, 1);
    lcd.print(light_l);
  
}
void second_page(){

    int sound = 0;
    for(int x = 0;x<10;x++){
          sound = sound + analogRead(noise);
    }
    sound = sound/10;
    double dB = 20*(log10(10*sound)) ;
    lcd.setCursor(0, 0);
    lcd.print("Noise           ");
    lcd.setCursor(0, 1);
    lcd.print(dB);
    lcd.setCursor(5, 1);
    lcd.print("            ");
    delay(100);
  
}

void third_page(){
  int moist_s = 0;

  for (int y = 0; y<100 ; y++){
    moist_s = moist_s + analogRead(moist);
    delay(2);
  }

  moist_s = moist_s/100;
  lcd.setCursor(0,0);
  lcd.print("Water- ");
  lcd.setCursor(0,1);
  lcd.print("Soil- ");

  lcd.setCursor(6,1);
  if(moist_s>900) lcd.print("Dry    ");
  else if(moist_s>650) lcd.print("Medium");
  else lcd.print("High   ");

  lcd.setCursor(7,0);
  if(moist_s>750) lcd.print("No      ");
  else if(moist_s>600) lcd.print("Distill ");
  else if(moist_s>500) lcd.print("Drinking");
  else if(moist_s>350) lcd.print("Fish    ");
  else lcd.print("Polluted");

}
DHT11.inoArduino
// DHT11 Temperature and Humidity Sensors Example
 #include <Adafruit_Sensor.h>
#include "DHT.h"         //include DHT library
#define DHTPIN 3         //define as DHTPIN the Pin 3 used to connect the Sensor
#define DHTTYPE DHT11    //define the sensor used(DHT11)
DHT dht(DHTPIN, DHTTYPE);//create an instance of DHT
/*setup*/
void setup() {
  Serial.begin(9600);    //initialize the Serial communication
  delay(6000);           //wait 6 seconds
  Serial.println("Temperature and Humidity test!");//print on Serial monitor
  Serial.println("T(C) \tH(%)");                   //print on Serial monitor
  dht.begin();           //initialize the Serial communication
}
/*loop*/
void loop() {
 
  float h = dht.readHumidity();    // reading Humidity 
  float t = dht.readTemperature(); // read Temperature as Celsius (the default)
  // check if any reads failed and exit early (to try again).
    if (isnan(h) || isnan(t)) {    
    Serial.println("Failed to read from DHT sensor!");
    return;
  }
  Serial.print(t, 2);    //print the temperature
  Serial.print("\t");
  Serial.println(h, 2);  //print the humidity
  delay(500);           //wait 2 seconds
}
Kalman.hC/C++
/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.

 This software may be distributed and modified under the terms of the GNU
 General Public License version 2 (GPL2) as published by the Free Software
 Foundation and appearing in the file GPL2.TXT included in the packaging of
 this file. Please note that GPL2 Section 2[b] requires that all works based
 on this software must also be made publicly available under the terms of
 the GPL2 ("Copyleft").

 Contact information
 -------------------

 Kristian Lauszus, TKJ Electronics
 Web      :  http://www.tkjelectronics.com
 e-mail   :  kristianl@tkjelectronics.com
 */

#ifndef _Kalman_h
#define _Kalman_h

class Kalman {
public:
    Kalman() {
        /* We will set the variables like so, these can also be tuned by the user */
        Q_angle = 0.01;//0.001
        Q_bias = 0.0001;//0.003
        R_measure = 0.11;//0.03

        angle = 0; // Reset the angle
        bias = 0; // Reset bias

        P[0][0] = 0; // Since we assume that the bias is 0 and we know the starting angle (use setAngle), the error covariance matrix is set like so - see: http://en.wikipedia.org/wiki/Kalman_filter#Example_application.2C_technical
        P[0][1] = 0;
        P[1][0] = 0;
        P[1][1] = 0;
    };
    // The angle should be in degrees and the rate should be in degrees per second and the delta time in seconds
    double getAngle(double newAngle, double newRate, double dt) {
        // KasBot V2  -  Kalman filter module - http://www.x-firm.com/?page_id=145
        // Modified by Kristian Lauszus
        // See my blog post for more information: http://blog.tkjelectronics.dk/2012/09/a-practical-approach-to-kalman-filter-and-how-to-implement-it

        // Discrete Kalman filter time update equations - Time Update ("Predict")
        // Update xhat - Project the state ahead
        /* Step 1 */
        rate = newRate - bias;
        angle += dt * rate;

        // Update estimation error covariance - Project the error covariance ahead
        /* Step 2 */
        P[0][0] += dt * (dt*P[1][1] - P[0][1] - P[1][0] + Q_angle);
        P[0][1] -= dt * P[1][1];
        P[1][0] -= dt * P[1][1];
        P[1][1] += Q_bias * dt;

        // Discrete Kalman filter measurement update equations - Measurement Update ("Correct")
        // Calculate Kalman gain - Compute the Kalman gain
        /* Step 4 */
        S = P[0][0] + R_measure;
        /* Step 5 */
        K[0] = P[0][0] / S;
        K[1] = P[1][0] / S;

        // Calculate angle and bias - Update estimate with measurement zk (newAngle)
        /* Step 3 */
        y = newAngle - angle;
        /* Step 6 */
        angle += K[0] * y;
        bias += K[1] * y;

        // Calculate estimation error covariance - Update the error covariance
        /* Step 7 */
        P[0][0] -= K[0] * P[0][0];
        P[0][1] -= K[0] * P[0][1];
        P[1][0] -= K[1] * P[0][0];
        P[1][1] -= K[1] * P[0][1];

        return angle;
    };
    void setAngle(double newAngle) { angle = newAngle; }; // Used to set angle, this should be set as the starting angle
    double getRate() { return rate; }; // Return the unbiased rate

    /* These are used to tune the Kalman filter */
    void setQangle(double newQ_angle) { Q_angle = newQ_angle; };
    void setQbias(double newQ_bias) { Q_bias = newQ_bias; };
    void setRmeasure(double newR_measure) { R_measure = newR_measure; };

    double getQangle() { return Q_angle; };
    double getQbias() { return Q_bias; };
    double getRmeasure() { return R_measure; };

private:
    /* Kalman filter variables */
    double Q_angle; // Process noise variance for the accelerometer
    double Q_bias; // Process noise variance for the gyro bias
    double R_measure; // Measurement noise variance - this is actually the variance of the measurement noise

    double angle; // The angle calculated by the Kalman filter - part of the 2x1 state vector
    double bias; // The gyro bias calculated by the Kalman filter - part of the 2x1 state vector
    double rate; // Unbiased rate calculated from the rate and the calculated bias - you have to call getAngle to update the rate

    double P[2][2]; // Error covariance matrix - This is a 2x2 matrix
    double K[2]; // Kalman gain - This is a 2x1 vector
    double y; // Angle difference
    double S; // Estimate error
};

#endif
Final CodeArduino
#include <Adafruit_Sensor.h>
#include "DHT.h"         //include DHT library
#define DHTPIN 3         //define as DHTPIN the Pin 3 used to connect the Sensor
#define DHTTYPE DHT11    //define the sensor used(DHT11)
#define light A0
#define noise A1
#define moist A2
#define button 8
DHT dht(DHTPIN, DHTTYPE);//create an instance of DHT
#include <Wire.h>
#include "rgb_lcd.h"
#include "math.h"
#include <CurieIMU.h>
#include "Kalman.h"

Kalman kalmanX; // Create the Kalman instances
Kalman kalmanY;

float accX, accY, accZ;
float gyroX, gyroY, gyroZ;

double gyroXangle, gyroYangle; 
double compAngleX, compAngleY; 
double kalAngleX, kalAngleY; 

rgb_lcd lcd;
uint32_t timer;

const int colorR = 0;
const int colorG = 30;
const int colorB = 55;

int page = 0;

void setup() 
{
    // set up the LCD's number of columns and rows:
    Serial.begin(9600);
    lcd.begin(16, 2);
    dht.begin(); 
    lcd.setRGB(colorR, colorG, colorB);
    pinMode(light,INPUT);
    pinMode(noise,INPUT);
    pinMode(button,INPUT);
    pinMode (2,OUTPUT);
    pinMode (A3,OUTPUT);
    digitalWrite(2,HIGH);
    digitalWrite(A3,OUTPUT);
    pinMode (1,OUTPUT);
  CurieIMU.begin();
  CurieIMU.setAccelerometerRange(2);
  CurieIMU.setGyroRange(250);
  delay(100); // Wait for sensor to stabilize
  CurieIMU.readAccelerometerScaled(accX, accY, accZ);

  double roll  = atan2(accY,accZ) * RAD_TO_DEG;
  double pitch = atan(-accX / sqrt(accY * accY + accZ * accZ)) * RAD_TO_DEG;
  //double yaw = atan (accZ/sqrt(accX*accX + accZ*accZ)) * RAD_TO_DEG;
  kalmanX.setAngle(roll); // Set starting angle
  kalmanY.setAngle(pitch);
  gyroXangle = roll;
  gyroYangle = pitch;
}

void loop() 
{
    while (page == 0){
      first_page();
      if (digitalRead(button) == 1)
         page++;
    }
    delay(500);
    while (page == 1){
      second_page();
      if (digitalRead(button) == 1)
          page++;
    }
    delay(500);

    while (page == 2){
      third_page();
      if (digitalRead(button) == 1)
          page = 0;
    }

    delay(500);

}

void first_page(){

  int h = dht.readHumidity();    // reading Humidity 
    int t = dht.readTemperature();
    int light_l = 0;
    
    for (int x=0; x<50;x++){
      light_l = light_l + analogRead(light);
      delay(2);
    }

    light_l = light_l/50;
    lcd.setCursor(12, 1);
    lcd.print("  lx");
    lcd.setCursor(0, 0);
    lcd.print("Temp ");
    lcd.setCursor(0, 1);
    lcd.print(t);
    lcd.setCursor(2, 1);
    lcd.print("_C ");
    
    lcd.setCursor(5, 0);
    lcd.print("Humid");
    lcd.setCursor(6, 1);
    lcd.print(h);
    lcd.setCursor(8, 1);
    lcd.print("%");
    
    lcd.setCursor(11, 0);
    lcd.print("Light");
    lcd.setCursor(11, 1);
    lcd.print(light_l);
  
}
void second_page(){

    int sound = 0;
    for(int x = 0;x<10;x++){
          sound = sound + analogRead(noise);
    }
    sound = sound/10;
    double dB = 20*(log10(10*sound)) ;
    lcd.setCursor(0, 0);
    lcd.print("Noise ");
    lcd.setCursor(0, 1);
    lcd.print(dB,0);
    lcd.setCursor(2, 1);
    lcd.print("dB");
    lcd.setCursor(6, 0);
    lcd.print("Roll ");
    lcd.setCursor(11, 0);
    lcd.print("Pitch");
    
for (int z=0; z<10;z++){

CurieIMU.readAccelerometerScaled(accX, accY, accZ); 
CurieIMU.readGyroScaled(gyroX, gyroY, gyroZ);

double dt = (double)(micros() - timer) / 1000000; // Calculate delta time
timer = micros();
 

double roll  = atan2(accY,accZ) * RAD_TO_DEG;
double pitch = atan(-accX / sqrt(accY * accY + accZ * accZ)) * RAD_TO_DEG;
//double yaw = atan2(accZ,sqrt(accX*accX + accZ*accZ)) * RAD_TO_DEG;


  double gyroXrate = gyroX / 131.0; // Convert to deg/s
  double gyroYrate = gyroY / 131.0; // Convert to deg/s

  if ((roll < -90 && kalAngleX > 90) || (roll > 90 && kalAngleX < -90)) {
    kalmanX.setAngle(roll);
    compAngleX = roll;
    kalAngleX = roll;
    gyroXangle = roll;
  } else
    kalAngleX = kalmanX.getAngle(roll, gyroXrate, dt); // Calculate the angle using a Kalman filter

  if (abs(kalAngleX) > 90)
    gyroYrate = -gyroYrate; // Invert rate, so it fits the restriced accelerometer reading
  kalAngleY = kalmanY.getAngle(pitch, gyroYrate, dt);

    gyroXangle += gyroXrate * dt; // Calculate gyro angle without any filter
  gyroYangle += gyroYrate * dt;
  //gyroXangle += kalmanX.getRate() * dt; // Calculate gyro angle using the unbiased rate
  //gyroYangle += kalmanY.getRate() * dt;

  compAngleX = 0.93 * (compAngleX + gyroXrate * dt) + 0.07 * roll; // Calculate the angle using a Complimentary filter
  compAngleY = 0.93 * (compAngleY + gyroYrate * dt) + 0.07 * pitch;

  if (gyroXangle < -180 || gyroXangle > 180)
    gyroXangle = kalAngleX;
  if (gyroYangle < -180 || gyroYangle > 180)
    gyroYangle = kalAngleY;

   delay(10); 
}

    lcd.setCursor(10,1);
    lcd.print("  ");
    lcd.setCursor(6,1);
    lcd.print(kalAngleX,1);
    lcd.setCursor(15,1);
    lcd.print(" ");
    lcd.setCursor(12,1);
    lcd.print(kalAngleY,1);
    
  
}

void third_page(){
  int moist_s = 0;

  for (int y = 0; y<100 ; y++){
    moist_s = moist_s + analogRead(moist);
    delay(2);
  }

  moist_s = moist_s/100;
  lcd.setCursor(0,0);
  lcd.print("Water- ");
  lcd.setCursor(0,1);
  lcd.print("Soil- ");

  lcd.setCursor(6,1);
  if(moist_s>900) lcd.print("Dry       ");
  else if(moist_s>650) lcd.print("Medium");
  else lcd.print("High   ");

  lcd.setCursor(7,0);
  if(moist_s>750) lcd.print("No       ");
  else if(moist_s>600) lcd.print("Distill ");
  else if(moist_s>500) lcd.print("Drinking");
  else if(moist_s>350) lcd.print("Fish    ");
  else lcd.print("Polluted");

}

Comments

Similar projects you might like

The Environment Cube! Know the Land Beneath You using Sigfox

Project tutorial by Dhairya Parikh

  • 1,663 views
  • 0 comments
  • 4 respects

Workspace Environment Monitor - enVMon

Project showcase by comcrazy

  • 3,506 views
  • 3 comments
  • 15 respects

An Urban Garden Monitor

Project tutorial by James Yu

  • 1,628 views
  • 0 comments
  • 4 respects

Save Your Life with the Building Collapse Monitor

Project tutorial by Tharindu Suraj

  • 2,662 views
  • 2 comments
  • 24 respects

Water Waste Monitor

Project tutorial by MD R. Islam

  • 853 views
  • 1 comment
  • 4 respects
Add projectSign up / Login