Community project

Generate A Clean High-resolution Technical Engin

ESP32
Photo of Generate A Clean High-resolution Technical Engin
Generated with AI

Yashas, G

Published August 23, 2026

This project builds a wearable gas detection and environmental monitoring system using an ESP32 microcontroller. It combines temperature and humidity sensing with gas detection to create a personal safety device that alerts the wearer to hazardous conditions through both visual and audio feedback.

The guide provides a complete wiring diagram, parts list, and step-by-step assembly instructions for integrating the 16x2 LCD display, DHT11 climate sensor, MQ-2 gas sensor, piezo buzzer alarm, push button, and HC-05 Bluetooth module. The included firmware handles sensor reading, alarm triggering, display management, and wireless communication, allowing real-time monitoring and remote data access from a paired mobile device.

Wiring diagram

Wiring diagram for Generate A Clean High-resolution Technical Engin

Gather all the parts

QtyComponent
1

16x2 I2C LCD, 3.3 V compatible

16x2 I2C, 3.3 V

A two-line, sixteen-character display module that shows the vest sensor readings.

1

DHT11

DHT11

Digital temperature and humidity sensor (lower accuracy than DHT22)

1

Piezo Buzzer

3.3 V piezo

Passive piezo buzzer element driven by a 3–30 V peak-to-peak square wave; loudest around 4 kHz, usable from 2–10 kHz. Differential drive (swapping which pin is high/low each half-cycle) doubles the volume.

1

Hc 05 Bluetooth Module

HC-05

Serial Bluetooth module for wireless communication using UART interface. Operates at 9600 baud (Data Mode) or 38400 baud (AT Command Mode). Supports two-way full-duplex wireless functionality with range up to 100m.

1

MQ-2 Gas Sensor

MQ-2 module

Analog combustible-gas and smoke sensor module. Detects LPG, propane, methane, hydrogen, alcohol, and smoke using a heated tin-dioxide (SnO2) sensing element whose resistance falls as gas concentration rises. The breakout board provides an analog output (AO) proportional to concentration plus a digital output (DO) that trips when concentration crosses an onboard potentiometer threshold. Requires a 5 V supply for the internal heater and a 20-30 s warm-up before readings stabilise; the AO voltage is relative, so the sensor needs a clean-air baseline calibration rather than reporting an absolute ppm value.

1

Push Button

Momentary

Momentary push button switch

1

10 kΩ Resistor

10 kΩ

The upper resistor in the MQ-2 output divider that lowers the sensor voltage before it reaches A0.

1

10 kΩ Resistor

10 kΩ

The lower resistor in the MQ-2 output divider that keeps the ESP8266 analog input safely below its limit.

Assemble it in 5 steps

1. Place the controller and make power rails

Place the NodeMCU ESP8266 in the middle of the breadboard. Run one red wire from its 3V3 pin to a positive rail and one black wire from GND to a ground rail. Run a second red wire from VIN (5 V while USB powered) to a separate 5 V rail; do not join the 5 V and 3.3 V rails.

  • Keeping 3.3 V and 5 V on different breadboard rails prevents accidental damage to the ESP8266 inputs.
  • Do not connect the 5 V rail to any NodeMCU signal pin — ESP8266 pins can be damaged by 5 V.

2. Wire the LCD and climate sensor

Connect lcd_16x2 VCC to 3V3 (power), lcd_16x2 GND to GND (ground), lcd_16x2 SDA to NodeMCU D2 / GPIO4 (data), and lcd_16x2 SCL to NodeMCU D1 / GPIO5 (clock). Connect dht11_1 VCC to 3V3 (power), dht11_1 GND to GND (ground), and dht11_1 DATA to D3 / GPIO0 (signal).

  • If the DHT11 is a bare four-pin sensor rather than a small three-pin module, add a 10 kΩ pull-up resistor from DATA to 3V3.
  • The display may use address 0x27; if it stays blank after deployment, its board may instead use 0x3F.
  • Make sure VCC and GND are not swapped on either module — swapped power can damage the parts.

3. Wire the alarm, button, and Bluetooth module

Connect piezo_1 Lead 1 to D5 / GPIO14 (alarm signal) and Lead 2 to GND (ground). Connect button_1 SIGNAL to D0 / GPIO16 (signal) and button_1 GND to GND (ground). Connect hc05_1 Vcc to VIN / 5 V (power), hc05_1 GND to GND (ground), hc05_1 TX to D6 / GPIO12 (Bluetooth data into the board), and hc05_1 RX to D7 / GPIO13 (Bluetooth data out of the board).

  • The button uses the board's built-in pull-up, so it should read as a press only when it connects D0 to ground.
  • Follow the labels printed on the HC-05 breakout board; TX and RX cross between the module and controller.
  • Do not use an unregulated battery or supply on the HC-05 Vcc pin; use the board's USB-powered 5 V rail for this version.

4. Add the protected gas-sensor connection

Connect mq2_1 VCC to VIN / 5 V (heater power) and mq2_1 GND to GND (ground). Connect mq2_1 AO to one end of r_mq2_top. Join the other end of r_mq2_top to one end of r_mq2_bottom and to NodeMCU A0 (gas-level signal). Connect the remaining end of r_mq2_bottom to GND (ground). Use the two 10 kΩ resistors exactly as this divider.

  • The joined resistor ends and A0 are one shared row on a breadboard.
  • Let the MQ-2 warm up for several minutes before treating its reading as meaningful.
  • Never connect MQ-2 AO straight to A0 — its 5 V output can damage the ESP8266 analog input.

5. Fit the electronics into the vest

After checking every wire, mount the board and modules inside a non-conductive pouch on the vest. Keep the MQ-2 sensor exposed to air and away from fabric, and route wires so they cannot pull loose when the wearer moves. Power the NodeMCU from USB for this design.

  • Use strain relief such as tape or small cable ties near each module so a tug does not bend its pins.
  • Place the buzzer opening and LCD where they can be heard and read.
  • The MQ-2 heater gets warm during use; keep it away from skin, loose fabric, and anything flammable.

Review all connections

1. Connections between "lcd_16x2" and "ESP32"

Functionlcd_16x2ESP32
powerVCC3V3
groundGNDGND
i2cSDAGPIO 4
i2cSCLGPIO 5

2. Connections between "dht11_1" and "ESP32"

Functiondht11_1ESP32
powerVCC3V3
groundGNDGND
dataDATAGPIO 0

3. Connections between "piezo_1" and "ESP32"

Functionpiezo_1ESP32
digitalLead 1GPIO 14
groundLead 2GND

4. Connections between "hc05_1" and "ESP32"

Functionhc05_1ESP32
powerVccVIN
groundGNDGND
dataTXGPIO 12
dataRXGPIO 13

5. Connections between "mq2_1" and "ESP32"

Functionmq2_1ESP32
powerVCCVIN
groundGNDGND
analogAO10 kΩ Resistor End 1EXT

6. Connections between "r_mq2_top" and "ESP32"

Functionr_mq2_topESP32
analogEnd 2GPIO 17

7. Connections between "r_mq2_bottom" and "ESP32"

Functionr_mq2_bottomESP32
groundEnd 2GND
analogEnd 110 kΩ Resistor End 2EXT

8. Connections between "button_1" and "ESP32"

Functionbutton_1ESP32
groundGNDGND
digitalSIGNALGPIO 16

Deploy the firmware

#include <HardwareSerial.h>
#include <Arduino.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <DHT.h>

// Forward declarations
String fit16(String text);
void showStatus(const String &line1, const String &line2);
bool readAcknowledgePress();

constexpr uint8_t LCD_SDA_PIN = 4;   // NodeMCU D2
constexpr uint8_t LCD_SCL_PIN = 5;   // NodeMCU D1
constexpr uint8_t DHT_PIN = 0;       // NodeMCU D3
constexpr uint8_t BUZZER_PIN = 14;   // NodeMCU D5
constexpr uint8_t BT_RX_PIN = 12;    // NodeMCU D6, receives HC-05 TX
constexpr uint8_t BT_TX_PIN = 13;    // NodeMCU D7, sends HC-05 RX
constexpr uint8_t MQ2_PIN = A0;
constexpr uint8_t BUTTON_PIN = 16;   // NodeMCU D0

constexpr int GAS_ALARM_LEVEL = 650;
constexpr unsigned long SAMPLE_INTERVAL_MS = 2000;
constexpr unsigned long DEBOUNCE_MS = 40;

LiquidCrystal_I2C lcd(0x27, 16, 2);
DHT dht(DHT_PIN, DHT11);
HardwareSerial bluetooth(2);

bool alarmAcknowledged = false;
bool previousButtonReading = HIGH;
bool stableButtonState = HIGH;
unsigned long lastButtonChangeMs = 0;
unsigned long lastSampleMs = 0;
String lastLine1;
String lastLine2;

String fit16(String text) {
  if (text.length() > 16) return text.substring(0, 16);
  while (text.length() < 16) text += ' ';
  return text;
}

void showStatus(const String &line1, const String &line2) {
  if (line1 != lastLine1) {
    lcd.setCursor(0, 0);
    lcd.print(fit16(line1));
    lastLine1 = line1;
  }
  if (line2 != lastLine2) {
    lcd.setCursor(0, 1);
    lcd.print(fit16(line2));
    lastLine2 = line2;
  }
}

bool readAcknowledgePress() {
  bool reading = digitalRead(BUTTON_PIN);
  if (reading != previousButtonReading) lastButtonChangeMs = millis();

  if ((millis() - lastButtonChangeMs) > DEBOUNCE_MS && reading != stableButtonState) {
    stableButtonState = reading;
    if (stableButtonState == LOW) {
      previousButtonReading = reading;
      return true;
    }
  }
  previousButtonReading = reading;
  return false;
}

void setup() {
  pinMode(BUZZER_PIN, OUTPUT);
  pinMode(BUTTON_PIN, INPUT_PULLUP);
  digitalWrite(BUZZER_PIN, LOW);

  Wire.begin(LCD_SDA_PIN, LCD_SCL_PIN);
  lcd.init();
  lcd.backlight();
  dht.begin();
  bluetooth.begin(9600, SERIAL_8N1, BT_RX_PIN, BT_TX_PIN);

  showStatus("Safety Vest", "Starting sensor");
  delay(1200);
}

void loop() {
  if (readAcknowledgePress()) {
    alarmAcknowledged = true;
  }

  if (millis() - lastSampleMs < SAMPLE_INTERVAL_MS) return;
  lastSampleMs = millis();

  float humidity = dht.readHumidity();
  float temperatureC = dht.readTemperature();
  int gasRaw = analogRead(MQ2_PIN);
  bool gasAlarm = gasRaw >= GAS_ALARM_LEVEL;
  bool dhtValid = !isnan(humidity) && !isnan(temperatureC);

  if (!gasAlarm) alarmAcknowledged = false;
  bool soundAlarm = gasAlarm && !alarmAcknowledged;
  digitalWrite(BUZZER_PIN, soundAlarm ? HIGH : LOW);

  String line1;
  if (dhtValid) {
    line1 = "T:" + String(temperatureC, 1) + "C H:" + String((int)humidity) + "%";
  } else {
    line1 = "DHT11 check";
  }

  String line2 = "Gas:" + String(gasRaw);
  if (gasAlarm) line2 += alarmAcknowledged ? " ACK" : " ALERT";
  showStatus(line1, line2);

  bluetooth.print("TEMP=");
  if (dhtValid) bluetooth.print(temperatureC, 1); else bluetooth.print("NA");
  bluetooth.print(",HUM=");
  if (dhtValid) bluetooth.print(humidity, 0); else bluetooth.print("NA");
  bluetooth.print(",MQ2=");
  bluetooth.print(gasRaw);
  bluetooth.print(",ALARM=");
  bluetooth.println(gasAlarm ? "1" : "0");
}

Remix this project

Make it yours in one click

Open a full copy of this project in your own Schematik workspace — diagram, code, parts, and assembly steps included. Swap the sensor, add features, or redesign the whole thing with AI. The author's original stays untouched.

Open in Schematik