JAmes Lam
Published © GPL3+

Wireless Monitoring System for GHGs emissions in Paddy Field

The monitoring system can help identify hotspots and provide data to study the effect of different parameters on the emission of GHGs.

IntermediateFull instructions provided8 hours648

Things used in this project

Hardware components

Wio Terminal
Seeed Studio Wio Terminal
×1
Grove - I2C High Accuracy Temp&Humi Sensor (SHT35)
Seeed Studio Grove - I2C High Accuracy Temp&Humi Sensor (SHT35)
×1
Gravity: Analog CH4 Gas Sensor (MQ4) For Arduino
DFRobot Gravity: Analog CH4 Gas Sensor (MQ4) For Arduino
×1
Solar Panel, 2.5 W
Solar Panel, 2.5 W
×1
Solar Power Manager (for 9V/12V/18V solar panel)
DFRobot Solar Power Manager (for 9V/12V/18V solar panel)
×1
Power Storage
×1
Waterproof Box
×1

Software apps and online services

Arduino IDE
Arduino IDE
Blynk
Blynk

Hand tools and fabrication machines

Jumper Wire Kit, Multicolor
Jumper Wire Kit, Multicolor
3D Printer (generic)
3D Printer (generic)
Hot glue gun (generic)
Hot glue gun (generic)

Story

Read more

Schematics

Schematic

Code

Arduino code for Methane Monitoring System

Arduino
// 18/9/2022 Arduino code for Methane Monitoring System by James Lam
// With help from Desmond Wong on CH4 concentration calculation
// WIth curtesy to the following authors on "uploading to Blynk" and "display layout"
/*
  Air Quality Terminal
  Author: Salman Faris
  Date: 01/09/2020
  Last Updates: 06/09/2020
  https://www.hackster.io/Salmanfarisvp/air-quality-monitoring-station-with-wio-terminal-6ef85f

  https://community.element14.com/challenges-projects/project14/sensors/b/blog/posts/wio-terminal-sensor-fusion---remote-data-display-and-control-using-blynk
  Wio Terminal Sensor Fusion - Remote Data Display and Control using Blynk
  by ralphjy 2020/11/9
*/
#define BLYNK_PRINT Serial

#define BLYNK_TEMPLATE_ID "your-blynk-template-id"
#define BLYNK_DEVICE_NAME "your-blynk-device-id"
#define BLYNK_AUTH_TOKEN "your-blynk-authentication-token"

#include <rpcWiFi.h>
#include <WiFiClient.h>
#include <BlynkSimpleWioTerminal.h>

#include <TFT_eSPI.h>
#include <Wire.h>
#include <SensirionI2CSht4x.h>
SensirionI2CSht4x sht4x;

#include <math.h>

#if defined(ARDUINO_ARCH_AVR)
    #define debug  Serial

#elif defined(ARDUINO_ARCH_SAMD) ||  defined(ARDUINO_ARCH_SAM)
    #define debug  SerialUSB
#else
    #define debug  Serial
#endif

// Your WiFi credentials.
const char* ssid = "your-wifi-ssid";
const char* pass = "your-wifi-password";

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

const int gasPin = A5;
const double C = 2.94336;
const double m = -1.94336;
double R0 = 58.91;  //should be calibrated in fresh air
double rawCH4;
double senVol;
double senRes;
double ratio;
double ppm_log;

TFT_eSPI tft;
TFT_eSprite spr = TFT_eSprite(&tft);  //sprite

BlynkTimer timer;

//Temp & humi
uint16_t error;
char errorMessage[256];
float temperature;
float humidity;

void setup() {
  Serial.begin(115200);
  tft.begin();
  tft.setRotation(3);

  //  initiate SHT40
  Wire.begin();

  uint16_t error;
  char errorMessage[256];

  sht4x.begin(Wire);

  uint32_t serialNumber;
  error = sht4x.serialNumber(serialNumber);
  if (error) {
    errorToString(error, errorMessage, 256);
    Blynk.notify(errorMessage);
  }

  //Head
  tft.fillScreen(TFT_BLACK);
  tft.setFreeFont(&FreeSansBoldOblique18pt7b);
  tft.setTextColor(TFT_WHITE);
  tft.drawString("Methane Monitor", 20, 10 , 1);

  //Line
  for (int8_t line_index = 0; line_index < 5 ; line_index++)
  {
    tft.drawLine(0, 50 + line_index, tft.width(), 50 + line_index, TFT_GREEN);
  }

  //CH4 Rect
  tft.drawRoundRect(5, 60, (tft.width() / 2) - 20 , tft.height() - 65 , 10, TFT_WHITE); // L1

  //R0 Text
  tft.setFreeFont(&FreeSansBoldOblique12pt7b);
  tft.setTextColor(TFT_RED);
  tft.drawString("R0", 7 , 65 , 1);

  //CH4 Text
  tft.setFreeFont(&FreeSansBoldOblique12pt7b);
  tft.setTextColor(TFT_RED);
  tft.drawString("CH4", 7 , 150 , 1);
  tft.setTextColor(TFT_GREEN);
  tft.drawString("ppm", 80, 193, 1);

  // Temp rect
  tft.drawRoundRect((tft.width() / 2) - 10  , 60, (tft.width() / 2) , (tft.height() - 65) / 2 , 10, TFT_BLUE); // s1

  tft.setFreeFont(&FreeSansBoldOblique9pt7b);
  tft.setTextColor(TFT_RED) ;
  tft.drawString("Temp", (tft.width() / 2) - 1  , 70 , 1); // Print the test text in the custom font
  tft.setTextColor(TFT_GREEN);
  tft.drawString("o", (tft.width() / 2) + 70, 95, 1);
  tft.drawString("C", (tft.width() / 2) + 80, 100, 1);

  //Humi Rect
  tft.drawRoundRect((tft.width() / 2) - 10 , (tft.height() / 2) + 30, (tft.width() / 2) , (tft.height() - 65) / 2 , 10, TFT_BLUE); // s3

  tft.setFreeFont(&FreeSansBoldOblique9pt7b);
  tft.setTextColor(TFT_RED) ;
  tft.drawString("Humi", (tft.width() / 2) - 1 , (tft.height() / 2) + 40 , 1); // Print the test text in the custom font
  tft.setTextColor(TFT_GREEN);
  tft.drawString("%", (tft.width() / 2) + 70, (tft.height() / 2) + 70, 1);

  Blynk.begin(auth, ssid, pass);
  timer.setInterval(1000L, takeMeasurement);
  timer.setInterval(1000L, Display);  
  timer.setInterval(1000L, sendtoBlynk);  
  
  //uncomment to calibrate R0, please calibrate in fresh air
  //  CH4_calib();
}

void loop() {
    
  Blynk.run();
  timer.run();
 
}

void CH4_calib ()
{
  double sensor_volt; //Define variable for sensor voltage
  double RS_air; //Define variable for sensor resistance
  double sensorValue; //Define variable for analog readings
  for (int x = 0 ; x < 500 ; x++) //Start for loop
  {
    sensorValue = sensorValue + analogRead(A5); //Add analog values of sensor 500 times
  }
  sensorValue = analogRead(A5); //sensorValue / 500.0; //Take average of readings
  sensor_volt = sensorValue * (5.0 / 1023.0); //Convert average to voltage
  RS_air = ((5.0 * 10.0) / sensor_volt) - 10.0; //Calculate RS in fresh air
  R0 = RS_air / 4.4; //Calculate R0
}

void sendtoBlynk()
{
    // Send to Blynk
  Blynk.virtualWrite(V0, temperature);
  Blynk.virtualWrite(V1, humidity);  
  Blynk.virtualWrite(V2, ppm_log);  
  Blynk.virtualWrite(V3, R0);
}

void takeMeasurement()
{
  //measure temperature and humidity
  error = sht4x.measureHighPrecision(temperature, humidity);
  if (error) {
    errorToString(error, errorMessage, 256);
    Blynk.notify(errorMessage);
  } 
  //measure CH4
  rawCH4 = analogRead(gasPin);
  senVol = rawCH4 * 5 / 1023.0;
  senRes = ((5.0 * 10.0) / senVol) - 10.0; //Calculate RS in fresh air
  ratio = senRes / R0;
  ppm_log = m * log10(ratio) + C;
}
  
void MeasureDisplay()
{
  error = sht4x.measureHighPrecision(temperature, humidity);
  if (error) {
    Serial.print("Error trying to execute measureHighPrecision(): ");
    errorToString(error, errorMessage, 256);
    Serial.println(errorMessage);
  } else {
    Serial.print("Temperature:");
    Serial.print(temperature);
    Serial.print("\t");
    Serial.print("Humidity:");
    Serial.println(humidity);
  }

  spr.createSprite(60, 30);
  spr.setFreeFont(&FreeSansBoldOblique12pt7b);
  spr.setTextColor(TFT_WHITE);
  spr.drawFloat(temperature, 2, 0, 0, 1);
  spr.setTextColor(TFT_GREEN);
  spr.pushSprite((tft.width() / 2) - 1, 100);
  spr.deleteSprite();

  spr.createSprite(60, 30);
  spr.setFreeFont(&FreeSansBoldOblique12pt7b);
  spr.setTextColor(TFT_WHITE);
  spr.drawFloat(humidity, 2, 0, 0, 1);
  spr.pushSprite((tft.width() / 2) - 1, (tft.height() / 2) + 67);
  spr.deleteSprite();

  //  R0
  spr.createSprite(70, 30);
  spr.fillSprite(TFT_BLACK);
  spr.setFreeFont(&FreeSansBoldOblique12pt7b);
  spr.setTextColor(TFT_WHITE);
  spr.drawFloat(R0, 2, 0, 0, 1);
  spr.pushSprite(15, 100);
  spr.deleteSprite();

  //  CH4
  spr.createSprite(60, 30);
  spr.setFreeFont(&FreeSansBoldOblique12pt7b);
  spr.setTextColor(TFT_WHITE);
  spr.drawFloat(ppm_log, 2, 0, 0, 1);
  spr.setTextColor(TFT_GREEN);
  spr.pushSprite(15, 185);
  spr.deleteSprite();
}

Credits

JAmes Lam

JAmes Lam

1 project • 2 followers
Engineer during weekdays, maker during weekends
Thanks to Desmond Wong, Ralphjy, Mithun Das, and Salman Faris.

Comments