📀

Monitoring Industries Using IoT

 
Monitoring Industries using the power of Internet and automation.

Story

The project aims to monitor the factories andgetting the information on your smartphone or other devices using IoT.

Background

The project aims in monitoring the gases, temperature, humidity, noise, barometric pressure, etc. and report the information on your smartphone. And also tells about the harmful conditions for the workers.
According to the most recent fire statistics from the National Fire Protection Association (NFPA), an average of 37, 000 fires occur at industrial and manufacturing properties every year. These incidents result in 18 civilian deaths, 279 civilian injuries, and $1 billion in direct property damage. - So, if we can detect flammable gases and chances of where fires and accidents can occur the project can save damage to life and property.
notion image
GOAL - To Prevent such Loses

About

This project is to monitor any manufacturing plant remotely for temperature, motion, humidity and carbon dioxide etc. The project has uses Arduino Mega and ESP8266 and various sensors. With the use of IoT, this project will send you the data remotely to your E-mail /SMS about the current weather and concentration of gases in the plant. The program has also set the parameters and if the results are not within the parameters it will notify the results with warning so that immediate action will be taken to prevent the fire... It can also take pictures while sending notification<by the use of ArduCam>. With the use of motion sensor it will help to monitor unauthorized entry after the office hours as set in parameters. This project uses Blynk as server and app to view your data. I planned to use Arduino Cloud but it is not available for ESP8266. This project will also expanded for monitoring the Health of each employees working in the plant by measuring their BP and heart rate with a future wearable device in the safety jacket...

Components

notion image
1 / 5 • BMP280 and ESP8266

Arduino Stuff

  • First gather all the components.
  • You need to upload the sketch “Calibrate_MQ2”and keep the MQ2 connected to Arduino on A0 in Fresh Air. The Serial Monitor will show the Ro value which needs to be replaced in the Final Sketch!
  • Download the Blynk App
  • And scan the QR code <attached below> to duplicate the project
notion image
Scan QR Code below with Blynk!
  • It will send the auth token to your email address you signed up with
  • Change the SSID, password, auth token and Ro value in the Industries_Monitor sketch!
  • After that upload the “Industries_Monitor” to your Arduino Mega and connect the ESP8266 and other sensors according to the schematics
notion image
Connect the devices and put it in the case like this!
  • <Schematics are attached below >
  • < Codeis attached below >
  • The Project IS COMPLETE!

Server Side

  • The server side of the project is managed by Blynk, a free application/host.
  • The sending and receiving of data is being handled by POST, PUT, GET, etc. ; on the phone and esp8266.
  • You can also setup your own server. Help here:
https://github.com/blynkkk/blynk-server

View Data

  • Install Blynk on your smartphone from the App Store/Play Store
  • Open the project which you had made before by scanning the QR code!
  • Edit the email address and other thing which you want to
  • Press the play button to get live feed from your device!
  • You can see the temperature, humidity, air pressure, motion, gas readings...
  • You can also see a chart with history for weather readings <***SuperChartWidget Required>
  • If the gas readings (CO, LPG, Smoke) have increased then, the server will tell the device to turn on the exhaust or crank up its speed if connected to it and turn on a loud siren to inform management about the increase in the readings..
  • <**Details about this are in Eventor Widget of Blynk>
notion image
1 / 4 • Weather Data on Blynk!

Working

I used an Arduino Mega to make the project! The project does not require lots of pins but boards with more memory will only work.
The Arduino Mega is connected to ESP8266 board to connect to Wi-Fi. The ESP8266 will be used to connect to Wi-Fi and the server and communicate with it through MQTT Protocol. The ESP8266 is connected via serial interface.
The system I made will monitor the temperature and pressure (using BMP280) and the humidity (using DHT11)!
Since the modern factories/industries use fossil fuel or other gases; The system also monitors gases like carbon monoxide (silent killer), LPG and smoke using MQ2 gas sensor. It also has a PIR motion sensor to detect humans and motion activity.
Most of the work of analyzing the data the data will be done on the server side. Here the server is Blynk. The server is hosting the web page and managing the entry of data and its analysis which has to be done. It uses and event-or widget to give notifications and other stuff based on the information sent by the device.
You will understand the working of the server if you see the code and Blynk interface!
 

Scematics(png)

This is the Scematic of the Project in PNG!Attach MQ2 to the board with Power Pins and Analog Pin(A) connected to pin A0 of Arduino Mega...Also connect Data pin of PIR Sensor to pin 7 of Arduino mega //Configurable in Blynk!
 
notion image

The QR code for Blynk Project

Download Blynk AppScan It!
notion image
 
 
 

Code

 

Industries_Monitor.ino

#define BLYNK_PRINT Serial

#include <Adafruit_BMP280.h>
#include <Adafruit_Sensor.h>
#include <Wire.h>
#include <ESP8266_Lib.h>
#include <BlynkSimpleShieldEsp8266.h>
#include <DHT.h>

// You should get Auth Token in the Blynk App.
// Go to the Project Settings (nut icon).
char auth[] = "Auth_Token";

// Your WiFi credentials.
// Set password to "" for open networks.
char ssid[] = "SSID";
char pass[] = "Watever";

// Hardware Serial on Mega, Leonardo, Micro...
#define EspSerial Serial3

// or Software Serial on Uno, Nano...
//#include <SoftwareSerial.h>
//SoftwareSerial EspSerial(2, 3); // RX, TX

// Your ESP8266 baud rate:
#define ESP8266_BAUD 115200

ESP8266 wifi(&EspSerial);

#define DHTPIN 4          // What digital pin we're connected to

// Uncomment whatever type you're using!
#define DHTTYPE DHT11     // DHT 11
//#define DHTTYPE DHT22   // DHT 22, AM2302, AM2321
//#define DHTTYPE DHT21   // DHT 21, AM2301

DHT dht(DHTPIN, DHTTYPE);
Adafruit_BMP280 bmp;//creating object for bmp280
BlynkTimer timer_dht;
BlynkTimer timer_bmp;
BlynkTimer timer_mq2;

///////////////STUFF fOR mq2 sENSOR???>>)////////////////////////////////////
/************************Hardware Related Macros for MQ2************************************/

const int calibrationLed = 13;                      //when the calibration start , LED pin 13 will light up , off when finish calibrating
const int MQ_PIN = A0;                              //define which analog input channel you are going to use
const int MQ_power = 45;
int RL_VALUE = 1;                                   //define the load resistance on the board, in kilo ohms
float RO_CLEAN_AIR_FACTOR = 9.83;                   //RO_CLEAR_AIR_FACTOR=(Sensor resistance in clean air)/RO,
//which is derived from the chart in datasheet
#define MQ_powerPin 8

/***********************Software Related Macros for MQ2************************************/
int CALIBARAION_SAMPLE_TIMES = 50;                  //define how many samples you are going to take in the calibration phase
int CALIBRATION_SAMPLE_INTERVAL = 500;              //define the time interal(in milisecond) between each samples in the
//cablibration phase
int READ_SAMPLE_INTERVAL = 50;                      //define how many samples you are going to take in normal operation
int READ_SAMPLE_TIMES = 5;                          //define the time interal(in milisecond) between each samples in
//normal operation

/**********************Application Related Macro for MQ2s**********************************/
#define         GAS_LPG             0
#define         GAS_CO              1
#define         GAS_SMOKE           2

/*****************************Globals for Gas Detection***********************************************/
float           LPGCurve[3]  =  {2.3, 0.21, -0.47};
//two points are taken from the curve.
//with these two points, a line is formed which is "approximately equivalent"
//to the original curve.
//data format:{ x, y, slope}; point1: (lg200, 0.21), point2: (lg10000, -0.59)

float           COCurve[3]  =  {2.3, 0.72, -0.34};
//two points are taken from the curve.
//with these two points, a line is formed which is "approximately equivalent"
//to the original curve.
//data format:{ x, y, slope}; point1: (lg200, 0.72), point2: (lg10000,  0.15)

float           SmokeCurve[3] = {2.3, 0.53, -0.44};
//two points are taken from the curve.
//with these two points, a line is formed which is "approximately equivalent"
//to the original curve.
//data format:{ x, y, slope}; point1: (lg200, 0.53), point2: (lg10000,  -0.22)

/**********REPLACE THIS**************/
float           Ro           =  0.35;                 //Ro is initialized REPLACE YOUR Val after Calibration here!


void sendDHT()
{
  float h = dht.readHumidity();
  float t2 = dht.readTemperature(); // or dht.readTemperature(true) for Fahrenheit

  if (isnan(h) || isnan(t2)) {
    Serial.println("Failed to read from DHT sensor!");
    return;
  }
  // You can send any value at any time.
  // Please don't send more that 10 values per second.
  Blynk.virtualWrite(V4, h);
  //  Blynk.virtualWrite(V6, t2);
}

void sendBMP() {
  float t = bmp.readTemperature();
  float p = bmp.readPressure();

  if (isnan(p) || isnan(t)) {
    Serial.println("Failed to read from BMP sensor!");
    return;
  }
  p *= 0.00750062;
  Blynk.virtualWrite(V6, t);
  Blynk.virtualWrite(V5, p);
  // Read data from the sensor and send it to the virtual channel here.
  // You can write data using virtualWrite or other Cayenne write functions.
  // For example, to send a temperature in Celsius you can use the following:
  // Cayenne.virtualWrite(VIRTUAL_PIN, 25.5, TEMPERATURE, CELSIUS);
  Serial.println(t);
  Serial.println(p);
}

void sendMQ2() {
  digitalWrite(MQ_power,HIGH);
  delay(500);
  long iPPM_LPG = 0;
  long iPPM_CO = 0;
  long iPPM_Smoke = 0;

  iPPM_LPG = MQGetGasPercentage(MQRead(MQ_PIN) / Ro, GAS_LPG);
  iPPM_CO = MQGetGasPercentage(MQRead(MQ_PIN) / Ro, GAS_CO);
  iPPM_Smoke = MQGetGasPercentage(MQRead(MQ_PIN) / Ro, GAS_SMOKE);


  Serial.println("Concentration of gas ");
  Serial.print("LPG: ");
  Serial.print(iPPM_LPG);
  Serial.println(" ppm");
  Serial.print("CO: ");
  Serial.print(iPPM_CO);
  Serial.println(" ppm");
  Serial.print("Smoke: ");
  Serial.print(iPPM_Smoke);
  Serial.println(" ppm");
  
  Blynk.virtualWrite(V8, iPPM_CO);
  Blynk.virtualWrite(V7, iPPM_LPG);
  Blynk.virtualWrite(V9, iPPM_Smoke);
  
  digitalWrite(MQ_power,LOW);
  delay(200);
}

void setup()
{
  // Debug console
  Serial.begin(9600);

  // Set ESP8266 baud rate
  EspSerial.begin(ESP8266_BAUD);
  delay(10);

  Blynk.begin(auth, wifi, ssid, pass);
  // You can also specify server:
  //Blynk.begin(auth, wifi, ssid, pass, "blynk-cloud.com", 80);
  //Blynk.begin(auth, wifi, ssid, pass, IPAddress(192,168,1,100), 8080);
  pinMode(MQ_PIN, INPUT);
  pinMode(MQ_power, OUTPUT);
  dht.begin();
  bmp.begin();
  // Setup a function to be called every second
  timer_dht.setInterval(15000L, sendDHT);
  timer_bmp.setInterval(9000L, sendBMP);
  timer_mq2.setInterval(12000L, sendMQ2);
}

void loop()
{
  Blynk.run();
  timer_dht.run();
  timer_bmp.run();
  timer_mq2.run();
}

/****************** MQResistanceCalculation ****************************************
  Input:   raw_adc - raw value read from adc, which represents the voltage
  Output:  the calculated sensor resistance
  Remarks: The sensor and the load resistor forms a voltage divider. Given the voltage
         across the load resistor and its resistance, the resistance of the sensor
         could be derived.
************************************************************************************/
float MQResistanceCalculation(int raw_adc)
{
  return ( ((float)RL_VALUE * (1023 - raw_adc) / raw_adc));
}

/***************************** MQCalibration ****************************************
  Input:   mq_pin - analog channel
  Output:  Ro of the sensor
  Remarks: This function assumes that the sensor is in clean air. It use
         MQResistanceCalculation to calculates the sensor resistance in clean air
         and then divides it with RO_CLEAN_AIR_FACTOR. RO_CLEAN_AIR_FACTOR is about
         10, which differs slightly between different sensors.
************************************************************************************/
float MQCalibration(int mq_pin)
{
  int i;
  float val = 0;

  for (i = 0; i < CALIBARAION_SAMPLE_TIMES; i++) {      //take multiple samples
    val += MQResistanceCalculation(analogRead(mq_pin));
    delay(CALIBRATION_SAMPLE_INTERVAL);
  }
  val = val / CALIBARAION_SAMPLE_TIMES;                 //calculate the average value
  val = val / RO_CLEAN_AIR_FACTOR;                      //divided by RO_CLEAN_AIR_FACTOR yields the Ro
  return val;                                                      //according to the chart in the datasheet

}

/*****************************  MQRead *********************************************
  Input:   mq_pin - analog channel
  Output:  Rs of the sensor
  Remarks: This function use MQResistanceCalculation to caculate the sensor resistenc (Rs).
         The Rs changes as the sensor is in the different consentration of the target
         gas. The sample times and the time interval between samples could be configured
         by changing the definition of the macros.
************************************************************************************/
float MQRead(int mq_pin)
{
  int i;
  float rs = 0;

  for (i = 0; i < READ_SAMPLE_TIMES; i++) {
    rs += MQResistanceCalculation(analogRead(mq_pin));
    delay(READ_SAMPLE_INTERVAL);
  }

  rs = rs / READ_SAMPLE_TIMES;

  return rs;
}

/*****************************  MQGetGasPercentage **********************************
  Input:   rs_ro_ratio - Rs divided by Ro
         gas_id      - target gas type
  Output:  ppm of the target gas
  Remarks: This function passes different curves to the MQGetPercentage function which
         calculates the ppm (parts per million) of the target gas.
************************************************************************************/
long MQGetGasPercentage(float rs_ro_ratio, int gas_id)
{
  if ( gas_id == GAS_LPG ) {
    return MQGetPercentage(rs_ro_ratio, LPGCurve);
  } else if ( gas_id == GAS_CO ) {
    return MQGetPercentage(rs_ro_ratio, COCurve);
  } else if ( gas_id == GAS_SMOKE ) {
    return MQGetPercentage(rs_ro_ratio, SmokeCurve);
  }

  return 0;
}

/*****************************  MQGetPercentage **********************************
  Input:   rs_ro_ratio - Rs divided by Ro
         pcurve      - pointer to the curve of the target gas
  Output:  ppm of the target gas
  Remarks: By using the slope and a point of the line. The x(logarithmic value of ppm)
         of the line could be derived if y(rs_ro_ratio) is provided. As it is a
         logarithmic coordinate, power of 10 is used to convert the result to non-logarithmic
         value.
************************************************************************************/
long  MQGetPercentage(float rs_ro_ratio, float *pcurve)
{
  return (pow(10, ( ((log(rs_ro_ratio) - pcurve[1]) / pcurve[2]) + pcurve[0])));
}

 
 

Calibrate_MQ2 Sensor

Code to get Ro Val for MQ2 Connect MQ2 to A0
/**************************************************************************** 
  Author : Andy @ MYBOTIC www.mybotic.com.my
  Date:5/7/2016 
  Project: How to detect the concentration of gas by using MQ2 sensor
****************************************************************************/


/************************Hardware Related Macros************************************/

const int calibrationLed = 13;                      //when the calibration start , LED pin 13 will light up , off when finish calibrating
const int MQ_PIN=A0;                                //define which analog input channel you are going to use
int RL_VALUE=1;                                     //define the load resistance on the board, in kilo ohms
float RO_CLEAN_AIR_FACTOR=9.83;                     //RO_CLEAR_AIR_FACTOR=(Sensor resistance in clean air)/RO,
                                                    //which is derived from the chart in datasheet
 
/***********************Software Related Macros************************************/
int CALIBARAION_SAMPLE_TIMES=50;                    //define how many samples you are going to take in the calibration phase
int CALIBRATION_SAMPLE_INTERVAL=500;                //define the time interal(in milisecond) between each samples in the
                                                    //cablibration phase
int READ_SAMPLE_INTERVAL=50;                        //define how many samples you are going to take in normal operation
int READ_SAMPLE_TIMES=5;                            //define the time interal(in milisecond) between each samples in 
                                                    //normal operation
 
/**********************Application Related Macros**********************************/
#define         GAS_LPG             0   
#define         GAS_CO              1   
#define         GAS_SMOKE           2    
 
/*****************************Globals***********************************************/
float           LPGCurve[3]  =  {2.3,0.21,-0.47};   //two points are taken from the curve. 
                                                    //with these two points, a line is formed which is "approximately equivalent"
                                                    //to the original curve. 
                                                    //data format:{ x, y, slope}; point1: (lg200, 0.21), point2: (lg10000, -0.59) 
float           COCurve[3]  =  {2.3,0.72,-0.34};    //two points are taken from the curve. 
                                                    //with these two points, a line is formed which is "approximately equivalent" 
                                                    //to the original curve.
                                                    //data format:{ x, y, slope}; point1: (lg200, 0.72), point2: (lg10000,  0.15) 
float           SmokeCurve[3] ={2.3,0.53,-0.44};    //two points are taken from the curve. 
                                                    //with these two points, a line is formed which is "approximately equivalent" 
                                                    //to the original curve.
                                                    //data format:{ x, y, slope}; point1: (lg200, 0.53), point2: (lg10000,  -0.22)                                                     
float           Ro           =  10;                 //Ro is initialized to 10 kilo ohms


void setup()
{ 
  
  Serial.begin(115200);
  pinMode(calibrationLed,OUTPUT);
  digitalWrite(calibrationLed,HIGH);
  Serial.println("Calibrating...");                        //LCD display

  
  Ro = MQCalibration(MQ_PIN);                         //Calibrating the sensor. Please make sure the sensor is in clean air         
  digitalWrite(calibrationLed,LOW);              
  
  Serial.println("done!");                                 //LCD display

  Serial.print("Ro= ");
  Serial.print(Ro);
  Serial.println("kohm");
  delay(3000);
}
 
void loop(){  
}
 
/****************** MQResistanceCalculation ****************************************
Input:   raw_adc - raw value read from adc, which represents the voltage
Output:  the calculated sensor resistance
Remarks: The sensor and the load resistor forms a voltage divider. Given the voltage
         across the load resistor and its resistance, the resistance of the sensor
         could be derived.
************************************************************************************/ 
float MQResistanceCalculation(int raw_adc)
{
  return ( ((float)RL_VALUE*(1023-raw_adc)/raw_adc));
}
 
/***************************** MQCalibration ****************************************
Input:   mq_pin - analog channel
Output:  Ro of the sensor
Remarks: This function assumes that the sensor is in clean air. It use  
         MQResistanceCalculation to calculates the sensor resistance in clean air 
         and then divides it with RO_CLEAN_AIR_FACTOR. RO_CLEAN_AIR_FACTOR is about 
         10, which differs slightly between different sensors.
************************************************************************************/ 
float MQCalibration(int mq_pin)
{
  int i;
  float val=0;

  for (i=0;i<CALIBARAION_SAMPLE_TIMES;i++) {            //take multiple samples
    val += MQResistanceCalculation(analogRead(mq_pin));
    delay(CALIBRATION_SAMPLE_INTERVAL);
  }
  val = val/CALIBARAION_SAMPLE_TIMES;                   //calculate the average value
  val = val/RO_CLEAN_AIR_FACTOR;                        //divided by RO_CLEAN_AIR_FACTOR yields the Ro                                        
  return val;                                                      //according to the chart in the datasheet 

}
 
/*****************************  MQRead *********************************************
Input:   mq_pin - analog channel
Output:  Rs of the sensor
Remarks: This function use MQResistanceCalculation to caculate the sensor resistenc (Rs).
         The Rs changes as the sensor is in the different consentration of the target
         gas. The sample times and the time interval between samples could be configured
         by changing the definition of the macros.
************************************************************************************/ 
float MQRead(int mq_pin)
{
  int i;
  float rs=0;
 
  for (i=0;i<READ_SAMPLE_TIMES;i++) {
    rs += MQResistanceCalculation(analogRead(mq_pin));
    delay(READ_SAMPLE_INTERVAL);
  }
 
  rs = rs/READ_SAMPLE_TIMES;
 
  return rs;  
}
 
/*****************************  MQGetGasPercentage **********************************
Input:   rs_ro_ratio - Rs divided by Ro
         gas_id      - target gas type
Output:  ppm of the target gas
Remarks: This function passes different curves to the MQGetPercentage function which 
         calculates the ppm (parts per million) of the target gas.
************************************************************************************/ 
long MQGetGasPercentage(float rs_ro_ratio, int gas_id)
{
  if ( gas_id == GAS_LPG ) {
     return MQGetPercentage(rs_ro_ratio,LPGCurve);
  } else if ( gas_id == GAS_CO ) {
     return MQGetPercentage(rs_ro_ratio,COCurve);
  } else if ( gas_id == GAS_SMOKE ) {
     return MQGetPercentage(rs_ro_ratio,SmokeCurve);
  }    
 
  return 0;
}
 
/*****************************  MQGetPercentage **********************************
Input:   rs_ro_ratio - Rs divided by Ro
         pcurve      - pointer to the curve of the target gas
Output:  ppm of the target gas
Remarks: By using the slope and a point of the line. The x(logarithmic value of ppm) 
         of the line could be derived if y(rs_ro_ratio) is provided. As it is a 
         logarithmic coordinate, power of 10 is used to convert the result to non-logarithmic 
         value.
************************************************************************************/ 
long  MQGetPercentage(float rs_ro_ratio, float *pcurve)
{
  return (pow(10,( ((log(rs_ro_ratio)-pcurve[1])/pcurve[2]) + pcurve[0])));
}