AI Intelligent Helmet for Mining Industry — Complete Project Documentation
This project can be implemented as an ESP32-based intelligent mining helmet that continuously monitors environmental and worker-condition parameters, detects abnormal patterns, estimates an accident-risk score, sends data to the cloud, and uses n8n + an AI agent + Telegram for intelligent notifications and voice alerts.
Important engineering note: this should be treated as a prototype/research safety system, not as the sole life-safety system in a real mine. Gas thresholds, sensor selection, enclosure, intrinsic-safety certification, radio operation, battery protection, and alarm behavior must be validated against the mine's applicable safety standards before deployment.
ESP32 is suitable for this type of prototype because it provides Wi-Fi, Bluetooth, GPIO, ADC, I²C and other peripherals. Espressif also documents ADC/GPIO restrictions; in particular, classic ESP32 ADC2 conflicts with Wi-Fi, so analog sensors should preferably be connected to ADC1 pins when Wi-Fi is active.
1. Project Title
AI Intelligent Helmet for Mining Industry with Accident Prediction, IoT Cloud Monitoring, n8n Automation, AI Agent and Telegram Voice Alerts
Short title
AI Mining Safety Helmet using ESP32 + IoT + AI Agent + n8n
2. Abstract
The proposed system is an intelligent wearable safety helmet designed to improve situational awareness for underground mining workers.
The helmet contains an ESP32 controller connected to environmental and motion sensors. The system measures parameters such as:
- Temperature
- Humidity
- Methane/gas level
- Carbon monoxide/gas level
- Worker motion
- Sudden impact
- Helmet orientation
- Optional heart-rate/SpO₂
- GPS/location where GPS reception is available
- Emergency/SOS button
- Battery voltage
The ESP32 processes the sensor information locally and transmits measurements through Wi-Fi to an n8n automation server.
n8n acts as the orchestration layer:
ESP32
↓
HTTP/Webhook
↓
n8n
↓
AI Agent
↓
Risk Assessment
├── Normal → Log data
├── Warning → Telegram text
├── High Risk → Telegram + voice alert
└── Emergency → Immediate emergency notification
↓
Google Sheets
↓
ThingSpeak Dashboard
The AI component does not simply look at one sensor threshold. It can evaluate multiple measurements and their trends together.
For example:
Methane increasing
+
Temperature increasing
+
Worker motion abnormal
+
Sudden acceleration
↓
AI Risk Analysis
↓
HIGH RISK
The system can then automatically generate a message such as:
HIGH RISK ALERT — Helmet H001
Methane level is increasing and abnormal motion was detected.
Risk score: 87/100.
Worker should move to a safer area and supervisor should investigate immediately.
The Telegram Bot API supports sending playable voice messages through sendVoice; current Telegram documentation specifies supported voice formats including OGG/Opus, MP3 and M4A.
3. Main Objectives
The project has seven major objectives.
Objective 1 — Environmental monitoring
Continuously monitor hazardous environmental conditions.
Objective 2 — Worker monitoring
Detect:
- Sudden fall
- Impact
- Unusual inactivity
- Abnormal movement
- Helmet removal, if a strap sensor is added
Objective 3 — Accident-risk prediction
Calculate a risk score based on:
Sensor values
+
Sensor trends
+
Motion patterns
+
Emergency button
+
Historical information
Objective 4 — Intelligent decision making
Use an n8n AI Agent to interpret the incoming information.
Objective 5 — Automated communication
Automatically notify supervisors through Telegram.
Objective 6 — Cloud data storage
Store measurements in:
- Google Sheets
- ThingSpeak
Objective 7 — Web dashboard
Provide a browser-based monitoring dashboard.
4. Complete System Architecture
┌─────────────────────────────┐
│ MINING WORKER │
│ │
│ AI SMART HELMET │
└──────────────┬──────────────┘
│
▼
┌─────────────────────────────┐
│ ESP32 │
│ │
│ Sensor acquisition │
│ Local filtering │
│ Fall detection │
│ Emergency detection │
│ Risk pre-processing │
│ Wi-Fi communication │
└──────────────┬──────────────┘
│
HTTPS/HTTP
│
▼
┌─────────────────────────────┐
│ n8n WEBHOOK │
└──────────────┬──────────────┘
│
┌──────────────────┼──────────────────┐
│ │ │
▼ ▼ ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ AI AGENT │ │ Google Sheets│ │ ThingSpeak │
│ │ │ │ │ │
│ Risk Score │ │ Historical │ │ Live Charts │
│ Reasoning │ │ Records │ │ Cloud Data │
│ Decision │ │ │ │ │
└──────┬───────┘ └──────────────┘ └──────────────┘
│
▼
┌────────────────┐
│ Risk Decision │
└───────┬────────┘
│
┌────────┼───────────┐
│ │ │
▼ ▼ ▼
NORMAL WARNING CRITICAL
│ │ │
│ ▼ ▼
│ Telegram Telegram
│ Text Text + Voice
│ │
└────────┬───────────┘
▼
Supervisor
5. Proposed Hardware
5.1 Controller
ESP32 DevKit
ESP32 provides Wi-Fi and Bluetooth connectivity and a large set of peripherals appropriate for an IoT prototype.
5.2 Sensors
A practical prototype can use:
| Component | Purpose |
|---|---|
| ESP32 | Main controller |
| MPU6050 | Accelerometer + gyroscope |
| MQ-4 | Methane indication |
| MQ-7 | Carbon monoxide indication |
| BME280 | Temperature + humidity + pressure |
| NEO-6M GPS | Location outdoors/surface |
| Push button | Emergency/SOS |
| Buzzer | Local alarm |
| Red LED | Critical warning |
| Green LED | Normal status |
| Vibration motor | Wearer alert |
| Battery voltage divider | Battery monitoring |
| Optional MAX30102 | Heart rate/SpO₂ prototype |
| Optional strap switch | Helmet-wear detection |
Important gas-sensor note
MQ-series sensors are useful for educational prototypes but should not be treated as certified mine gas detectors. Real mining applications require appropriate certified gas-sensing equipment.
6. Hardware Block Diagram
┌─────────────────┐
│ Li-ion Battery│
└────────┬────────┘
│
Power Regulation
│
▼
┌─────────────────┐
│ ESP32 │
└───────┬─────────┘
│
┌────────────────────┼─────────────────────┐
│ │ │
▼ ▼ ▼
MPU6050 BME280 GPS Module
Accel/Gyro Temp/Humidity NEO-6M
│ │ │
└──────────────┬─────┴──────────────┬──────┘
│ │
▼ ▼
I²C Bus UART GPS
│
┌──────────────┼───────────────┐
│ │ │
▼ ▼ ▼
MQ-4 MQ-7 SOS Button
Methane CO
│ │
└───────┬──────┘
▼
ESP32
│
┌────────┼─────────┐
│ │ │
▼ ▼ ▼
Buzzer LED Vibration
│
▼
Wi-Fi
│
▼
n8n
7. Example ESP32 Pin Assignment
For a classic ESP32 DevKit:
| Device | ESP32 pin |
|---|---|
| MPU6050 SDA | GPIO 21 |
| MPU6050 SCL | GPIO 22 |
| BME280 SDA | GPIO 21 |
| BME280 SCL | GPIO 22 |
| MQ-4 analog | GPIO 34 |
| MQ-7 analog | GPIO 35 |
| SOS button | GPIO 27 |
| Buzzer | GPIO 26 |
| Red LED | GPIO 25 |
| Green LED | GPIO 33 |
| Vibration motor driver | GPIO 32 |
| GPS RX/TX | GPIO 16/17 |
| Battery ADC | GPIO 36 |
GPIO34–39 on the classic ESP32 are input-only, which makes them useful for analog measurements. Espressif also notes that ADC2 cannot be used normally for ADC reads while Wi-Fi is operating, so the example deliberately uses ADC1-capable pins such as GPIO34/35/36.
8. Schematic-Level Connection
ESP32
┌────────────────┐
│ │
3.3V ───────┤3V3 │
GND ────────┤GND │
│ │
MPU6050 SDA ──────┤GPIO21 │
MPU6050 SCL ──────┤GPIO22 │
│ │
BME280 SDA ───────┤GPIO21 │
BME280 SCL ───────┤GPIO22 │
│ │
MQ4 AO ───────────┤GPIO34 │
MQ7 AO ───────────┤GPIO35 │
Battery divider ──┤GPIO36 │
│ │
SOS ──────────────┤GPIO27 │
Buzzer Driver ────┤GPIO26 │
Red LED ──────────┤GPIO25 │
Green LED ────────┤GPIO33 │
Vibration Driver ─┤GPIO32 │
│ │
GPS TX ───────────┤GPIO16 (RX2) │
GPS RX ───────────┤GPIO17 (TX2) │
└────────────────┘
Motor/buzzer driver
Do not drive a high-current vibration motor directly from an ESP32 GPIO.
Use:
ESP32 GPIO
│
R
│
▼
MOSFET
│
├──── Motor
│
GND
Flyback diode across inductive load where appropriate.
The same principle applies to a larger external buzzer.
9. Operating Principle
The helmet operates in several stages.
Stage 1 — Sensor acquisition
ESP32 reads the sensors periodically.
Example:
Every 1 second:
Temperature
Humidity
Methane
CO
Acceleration
Gyroscope
Battery
GPS
SOS
Stage 2 — Filtering
Raw readings are noisy.
Therefore:
Raw data
↓
Moving average
↓
Median/filter
↓
Validated data
Stage 3 — Local event detection
ESP32 immediately detects conditions that should not wait for an AI response.
Examples:
SOS button pressed
↓
Immediate emergency
Large acceleration spike
↓
Possible impact
No motion after impact
↓
Possible fall
Very high sensor reading
↓
Immediate local alarm
Stage 4 — Cloud transmission
ESP32 creates JSON:
{
"helmet_id": "H001",
"temperature": 32.4,
"humidity": 67.2,
"methane": 415,
"co": 82,
"accel": 1.24,
"gyro": 13.8,
"fall": false,
"sos": false,
"battery": 3.91,
"risk": 23
}
It sends the data to n8n.
10. Accident Prediction Concept
The term prediction should be implemented carefully.
Instead of claiming:
"The AI knows an accident will happen."
the system should calculate:
"The current sensor pattern indicates elevated accident risk."
This is much more technically defensible.
11. Risk Score
A simple prototype can use a 0–100 risk score.
Example:
Risk =
Gas Risk
+ Temperature Risk
+ Motion Risk
+ Fall Risk
+ Inactivity Risk
+ SOS Risk
Example weighting:
Gas 30%
Motion 25%
Fall 25%
Temperature 10%
Inactivity 5%
SOS 5%
But an actual deployed system should derive the weights from validated field data rather than arbitrary numbers.
12. Example Risk Levels
| Risk | Level | Action |
|---|---|---|
| 0–20 | NORMAL | Store data |
| 21–40 | LOW | Monitor |
| 41–60 | WARNING | Telegram notification |
| 61–80 | HIGH | Telegram + supervisor alert |
| 81–100 | CRITICAL | Local alarm + Telegram voice alert |
Example:
Risk = 18
NORMAL
Risk = 55
WARNING
Risk = 73
HIGH
Risk = 94
CRITICAL
13. Accident Detection Logic
One useful prototype algorithm is:
Acceleration > impact threshold
↓
Possible impact
↓
Start 10-second timer
↓
Motion detected?
/ \
YES NO
│ │
▼ ▼
Cancel alarm Possible fall
│
▼
Increase risk
│
▼
n8n / AI Agent
For example:
Before event:
acceleration ≈ 1 g
Impact:
acceleration = 5.8 g
After impact:
acceleration ≈ 1 g
+
worker remains almost stationary
This could be classified as a possible fall/impact event.
The threshold must be experimentally calibrated for the actual helmet, mounting position and worker activity.
14. AI Agent Architecture
The AI Agent sits in n8n.
n8n
│
▼
┌───────────────┐
│ Normalize Data│
└───────┬───────┘
│
▼
┌────────────┐
│ AI Agent │
└─────┬──────┘
│
┌──────────┼───────────┐
│ │ │
▼ ▼ ▼
Sensor data History Rules
│ │ │
└──────────┼───────────┘
▼
Risk Analysis
│
▼
Structured JSON
│
▼
Decision node
15. AI Agent Prompt
Use a structured prompt similar to:
You are a mining safety monitoring AI assistant.
You receive sensor information from an intelligent mining helmet.
Your task is to evaluate the current safety condition.
Do not claim that an accident is certain.
Classify the situation as:
NORMAL
LOW
WARNING
HIGH
CRITICAL
Consider:
1. Gas concentration and trend
2. Temperature
3. Worker movement
4. Sudden acceleration
5. Possible fall
6. Inactivity
7. SOS button
8. Battery condition
9. Previous sensor readings
Return JSON only:
{
"risk_score": 0,
"risk_level": "NORMAL",
"event": "NONE",
"reason": "Short explanation",
"recommended_action": "Recommended action",
"telegram_message": "Short alert message",
"voice_message": "Short spoken alert"
}
Do not invent sensor measurements.
If a measurement is missing, say so.
Treat this system as an advisory prototype and never state that it replaces certified mine safety equipment.
16. n8n Workflow
n8n provides built-in Telegram integration for automating Telegram operations.
The main workflow can be:
┌──────────────┐
│ Webhook │
│ ESP32 DATA │
└──────┬───────┘
│
▼
┌──────────────┐
│ JSON Validate│
└──────┬───────┘
│
▼
┌──────────────┐
│ Set / Code │
│ Normalize │
└──────┬───────┘
│
├──────────────────┐
│ │
▼ ▼
Google Sheets ThingSpeak
│ │
└────────┬─────────┘
▼
┌─────────────┐
│ AI Agent │
└──────┬──────┘
│
▼
Structured Output
│
▼
┌─────────────┐
│ IF / Switch │
└──────┬──────┘
│
┌─────────┼───────────┐
│ │ │
▼ ▼ ▼
NORMAL WARNING CRITICAL
│ │ │
│ ▼ ▼
│ Telegram Telegram
│ Text Text + Voice
│ │
└─────────┬───────────┘
▼
Log event
17. n8n Node-by-Node Configuration
Node 1 — Webhook
Create:
Method: POST
Path: mining-helmet
The resulting endpoint is conceptually:
https://YOUR-N8N-SERVER/webhook/mining-helmet
ESP32 sends JSON to this endpoint.
18. Node 2 — Data Validation
Validate:
helmet_id
temperature
humidity
methane
co
accel
gyro
fall
sos
battery
timestamp
Reject malformed packets.
19. Node 3 — Data Normalization
Convert everything into a standard structure:
{
"helmet_id": "H001",
"timestamp": "2026-08-22T22:25:00+05:30",
"temperature": 32.4,
"humidity": 67.2,
"methane": 415,
"co": 82,
"accel": 1.24,
"gyro": 13.8,
"fall": false,
"sos": false,
"battery": 3.91
}
20. Node 4 — Google Sheets
Create columns:
Timestamp
Helmet ID
Temperature
Humidity
Methane
CO
Acceleration
Gyroscope
Fall
SOS
Battery
Risk Score
Risk Level
AI Reason
Action
Example:
| Timestamp | Helmet | Temp | CH4 | CO | Fall | Risk |
|---|---|---|---|---|---|---|
| 22:25 | H001 | 32.4 | 415 | 82 | No | 23 |
| 22:26 | H001 | 32.6 | 460 | 91 | No | 38 |
| 22:27 | H001 | 33.1 | 580 | 103 | Yes | 82 |
This historical data can later become training data for a real machine-learning model.
21. Node 5 — ThingSpeak
ThingSpeak can provide charts and cloud visualization of sensor fields. Existing ThingSpeak channels expose field charts and feeds through the service.
Suggested channel:
Field 1 = Temperature
Field 2 = Humidity
Field 3 = Methane
Field 4 = CO
Field 5 = Acceleration
Field 6 = Risk Score
Field 7 = Battery
Field 8 = Fall/SOS status
The update concept is:
https://api.thingspeak.com/update
with parameters such as:
api_key
field1
field2
field3
...
Do not place a real ThingSpeak write API key in a public webpage or public GitHub repository.
22. Node 6 — AI Agent
Input:
{
"helmet_id": "H001",
"temperature": 33.1,
"humidity": 68,
"methane": 580,
"co": 103,
"accel": 7.2,
"fall": true,
"sos": false
}
AI returns:
{
"risk_score": 86,
"risk_level": "CRITICAL",
"event": "POSSIBLE_FALL",
"reason": "Sudden impact followed by abnormal motion combined with elevated gas readings.",
"recommended_action": "Notify supervisor and check worker condition immediately.",
"telegram_message": "CRITICAL: H001 possible fall with elevated gas readings.",
"voice_message": "Critical alert. Helmet H001 detected a possible fall and elevated hazardous gas readings. Check the worker immediately."
}
23. Node 7 — Switch/IF
Conditions:
risk_score < 40
↓
NORMAL
40–60
↓
WARNING
61–80
↓
HIGH
>80
↓
CRITICAL
For a real deployment, gas alarm logic should also include independent hard thresholds, rather than relying exclusively on an LLM.
24. Telegram Alert
For normal conditions:
No Telegram alert.
For warning:
⚠️ MINING HELMET WARNING
Helmet: H001
Risk: 55/100
Methane trend increasing.
Temperature: 33.1°C
Please monitor worker condition.
For critical:
🚨 CRITICAL MINING SAFETY ALERT
Helmet: H001
Possible fall detected.
Hazardous gas readings elevated.
Risk Score: 86/100
Immediate supervisor investigation required.
25. Telegram Voice Alert
The architecture is:
AI Agent
│
▼
Voice message text
│
▼
TTS service
│
▼
OGG/Opus audio
│
▼
Telegram Bot API
│
▼
Supervisor's Telegram
Telegram's sendVoice API is specifically intended for playable voice messages.
Example voice text:
Critical mining safety alert.
Helmet H001 has detected a possible worker fall and elevated hazardous gas readings.
Please check the worker immediately.
26. n8n Telegram Voice Workflow
AI Agent
│
▼
Extract voice_message
│
▼
HTTP Request — TTS
│
▼
Binary audio
│
▼
Telegram sendVoice
│
▼
Supervisor
If the selected TTS service returns a format unsuitable for Telegram voice messages, convert it to an appropriate supported format before sending. Telegram documents supported voice-message formats and file constraints.
27. ESP32 Arduino Software
The following is a prototype reference implementation, not production-certified safety firmware.
Install these Arduino libraries:
WiFi
HTTPClient
Wire
ArduinoJson
Adafruit MPU6050
Adafruit BME280
TinyGPSPlus
Example firmware:
#include <WiFi.h>
#include <HTTPClient.h>
#include <Wire.h>
#include <ArduinoJson.h>
#include <Adafruit_MPU6050.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
#include <TinyGPSPlus.h>
// -----------------------------
// Wi-Fi
// -----------------------------
const char* WIFI_SSID = "YOUR_WIFI";
const char* WIFI_PASSWORD = "YOUR_PASSWORD";
// n8n webhook
const char* N8N_URL =
"https://YOUR-N8N-SERVER/webhook/mining-helmet";
// -----------------------------
// Helmet ID
// -----------------------------
const char* HELMET_ID = "H001";
// -----------------------------
// Pins
// -----------------------------
#define MQ4_PIN 34
#define MQ7_PIN 35
#define BATTERY_PIN 36
#define SOS_PIN 27
#define BUZZER_PIN 26
#define RED_LED_PIN 25
#define GREEN_LED_PIN 33
#define VIBRATION_PIN 32
// GPS
#define GPS_RX 16
#define GPS_TX 17
// -----------------------------
// Sensors
// -----------------------------
Adafruit_MPU6050 mpu;
Adafruit_BME280 bme;
TinyGPSPlus gps;
HardwareSerial GPSSerial(2);
// -----------------------------
// Timing
// -----------------------------
unsigned long lastSend = 0;
const unsigned long SEND_INTERVAL = 5000;
// -----------------------------
// Fall detection
// -----------------------------
bool possibleFall = false;
unsigned long impactTime = 0;
const float IMPACT_THRESHOLD_G = 4.0;
const float INACTIVITY_THRESHOLD_G = 0.25;
// -----------------------------
// Read acceleration magnitude
// -----------------------------
float readAccelerationG() {
sensors_event_t accel;
sensors_event_t gyro;
sensors_event_t temp;
mpu.getEvent(&accel, &gyro, &temp);
float ax = accel.acceleration.x;
float ay = accel.acceleration.y;
float az = accel.acceleration.z;
float magnitude =
sqrt(ax * ax + ay * ay + az * az);
return magnitude / 9.80665;
}
// -----------------------------
// Detect possible fall
// -----------------------------
void updateFallDetection(float accelG) {
if (accelG >= IMPACT_THRESHOLD_G) {
possibleFall = true;
impactTime = millis();
digitalWrite(BUZZER_PIN, HIGH);
digitalWrite(VIBRATION_PIN, HIGH);
digitalWrite(RED_LED_PIN, HIGH);
}
// If possible fall remains active for 10 sec,
// the system continues reporting it.
if (possibleFall &&
millis() - impactTime > 10000) {
digitalWrite(BUZZER_PIN, LOW);
digitalWrite(VIBRATION_PIN, LOW);
}
}
// -----------------------------
// Battery voltage
// -----------------------------
float readBatteryVoltage() {
int raw = analogRead(BATTERY_PIN);
float voltage =
((float)raw / 4095.0) * 3.3;
// Example 100k/100k divider.
voltage *= 2.0;
return voltage;
}
// -----------------------------
// Simple prototype risk score
// -----------------------------
int calculateRisk(
int methane,
int co,
float temperature,
float accelG,
bool fall,
bool sos
) {
int risk = 0;
// These are prototype/example values.
// They MUST NOT be treated as certified
// mine alarm limits.
if (methane > 300)
risk += 15;
if (methane > 500)
risk += 20;
if (co > 100)
risk += 15;
if (co > 200)
risk += 20;
if (temperature > 35)
risk += 10;
if (temperature > 40)
risk += 10;
if (accelG > 4)
risk += 25;
if (fall)
risk += 30;
if (sos)
risk += 50;
if (risk > 100)
risk = 100;
return risk;
}
// -----------------------------
// Send data to n8n
// -----------------------------
void sendToN8N() {
sensors_event_t accel;
sensors_event_t gyro;
sensors_event_t tempEvent;
mpu.getEvent(
&accel,
&gyro,
&tempEvent
);
float ax = accel.acceleration.x;
float ay = accel.acceleration.y;
float az = accel.acceleration.z;
float accelG =
sqrt(
ax * ax +
ay * ay +
az * az
) / 9.80665;
float temperature =
bme.readTemperature();
float humidity =
bme.readHumidity();
int methane =
analogRead(MQ4_PIN);
int co =
analogRead(MQ7_PIN);
bool sos =
digitalRead(SOS_PIN) == LOW;
float battery =
readBatteryVoltage();
updateFallDetection(accelG);
int risk = calculateRisk(
methane,
co,
temperature,
accelG,
possibleFall,
sos
);
StaticJsonDocument<1024> doc;
doc["helmet_id"] = HELMET_ID;
doc["temperature"] = temperature;
doc["humidity"] = humidity;
doc["methane_raw"] = methane;
doc["co_raw"] = co;
doc["acceleration_g"] = accelG;
doc["gyro_x"] = gyro.gyro.x;
doc["gyro_y"] = gyro.gyro.y;
doc["gyro_z"] = gyro.gyro.z;
doc["fall"] = possibleFall;
doc["sos"] = sos;
doc["battery"] = battery;
doc["risk_score"] = risk;
if (gps.location.isValid()) {
doc["latitude"] =
gps.location.lat();
doc["longitude"] =
gps.location.lng();
}
String json;
serializeJson(doc, json);
Serial.println(json);
if (WiFi.status() == WL_CONNECTED) {
HTTPClient http;
http.begin(N8N_URL);
http.addHeader(
"Content-Type",
"application/json"
);
int responseCode =
http.POST(json);
Serial.print("n8n response: ");
Serial.println(responseCode);
http.end();
}
// Local alarm
if (risk >= 70 || sos) {
digitalWrite(
RED_LED_PIN,
HIGH
);
digitalWrite(
BUZZER_PIN,
HIGH
);
digitalWrite(
VIBRATION_PIN,
HIGH
);
} else {
digitalWrite(
RED_LED_PIN,
LOW
);
digitalWrite(
BUZZER_PIN,
LOW
);
digitalWrite(
VIBRATION_PIN,
LOW
);
}
}
// -----------------------------
// Setup
// -----------------------------
void setup() {
Serial.begin(115200);
pinMode(
SOS_PIN,
INPUT_PULLUP
);
pinMode(
BUZZER_PIN,
OUTPUT
);
pinMode(
RED_LED_PIN,
OUTPUT
);
pinMode(
GREEN_LED_PIN,
OUTPUT
);
pinMode(
VIBRATION_PIN,
OUTPUT
);
Wire.begin(
21,
22
);
// MPU6050
if (!mpu.begin()) {
Serial.println(
"MPU6050 not found"
);
while (1) {
delay(1000);
}
}
// BME280
if (!bme.begin(0x76)) {
Serial.println(
"BME280 not found"
);
while (1) {
delay(1000);
}
}
// GPS
GPSSerial.begin(
9600,
SERIAL_8N1,
GPS_RX,
GPS_TX
);
// Wi-Fi
WiFi.begin(
WIFI_SSID,
WIFI_PASSWORD
);
Serial.print(
"Connecting to Wi-Fi"
);
while (
WiFi.status() != WL_CONNECTED
) {
delay(500);
Serial.print(".");
}
Serial.println();
Serial.println(
"Wi-Fi connected"
);
digitalWrite(
GREEN_LED_PIN,
HIGH
);
}
// -----------------------------
// Main loop
// -----------------------------
void loop() {
// Read GPS continuously
while (GPSSerial.available()) {
gps.encode(
GPSSerial.read()
);
}
if (
millis() - lastSend
>= SEND_INTERVAL
) {
lastSend = millis();
sendToN8N();
}
delay(10);
}
28. Important Improvement to the ESP32 Code
The MQ values in the example are intentionally named:
methane_raw
co_raw
rather than:
methane_ppm
co_ppm
because a raw ESP32 ADC value is not automatically a gas concentration in ppm.
For a serious prototype, you need:
Sensor calibration
↓
ADC voltage
↓
Sensor resistance
↓
Calibration curve
↓
Estimated concentration
And for a real mine:
Certified sensor
+
Certified electronics
+
Calibration procedure
+
Safety certification
29. Better Accident-Prediction Algorithm
The next version should not depend solely on fixed thresholds.
Collect historical data:
Timestamp
Acceleration
Gyroscope
Gas
Temperature
Humidity
Worker activity
Fall event
SOS
Outcome
Then construct a dataset:
INPUT
│
┌──────────────┼──────────────┐
│ │ │
▼ ▼ ▼
Gas Motion Environment
│ │ │
└──────────────┼──────────────┘
▼
ML MODEL
│
▼
Accident Risk
0–100%
Possible models:
Logistic Regression
Random Forest
XGBoost
SVM
LSTM
1D CNN
Isolation Forest
For a student project, I recommend beginning with:
Random Forest + anomaly detection
rather than immediately implementing an LSTM.
30. Two-Level AI Architecture
A stronger design is:
ESP32
│
▼
Immediate Safety Logic
│
┌───────────┴────────────┐
│ │
▼ ▼
Local Alarm n8n Cloud
│
▼
AI Agent
│
▼
Historical Context
│
▼
Risk Assessment
This is important because the ESP32 should not have to wait for:
Wi-Fi
↓
Internet
↓
n8n
↓
AI model
↓
response
before sounding a local emergency alarm.
31. IoT Web Dashboard
The web dashboard can show:
┌───────────────────────────────────────────┐
│ AI MINING HELMET MONITOR │
├───────────────────────────────────────────┤
│ │
│ Helmet: H001 Status: 🟢 NORMAL │
│ │
│ Temperature 32.4 °C │
│ Humidity 67.2 % │
│ Methane 415 │
│ CO 82 │
│ Battery 3.91 V │
│ Risk 23 / 100 │
│ │
├───────────────────────────────────────────┤
│ SENSOR GRAPHS │
│ │
│ Temperature ─────────╮ │
│ ╰────── │
│ Methane ────╮ │
│ ╰──────── │
│ │
├───────────────────────────────────────────┤
│ AI STATUS │
│ NORMAL │
│ No abnormal event detected. │
└───────────────────────────────────────────┘
32. Example Webpage
For a public ThingSpeak channel, the dashboard can read the channel's JSON feed.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, initial-scale=1.0">
<title>AI Mining Helmet Dashboard</title>
<style>
body {
margin: 0;
font-family: Arial, sans-serif;
background: #101820;
color: white;
}
header {
background: #182b3a;
padding: 20px;
text-align: center;
}
.dashboard {
display: grid;
grid-template-columns:
repeat(auto-fit, minmax(200px, 1fr));
gap: 20px;
padding: 25px;
}
.card {
background: #1d303f;
padding: 20px;
border-radius: 15px;
box-shadow: 0 5px 20px #0005;
}
.value {
font-size: 32px;
font-weight: bold;
}
.normal {
color: #00ff88;
}
.warning {
color: #ffcc00;
}
.critical {
color: #ff3333;
}
canvas {
max-width: 100%;
}
</style>
</head>
<body>
<header>
<h1>⛑ AI Mining Helmet</h1>
<p>ESP32 + n8n + AI Agent + ThingSpeak</p>
</header>
<div class="dashboard">
<div class="card">
<h3>Temperature</h3>
<div id="temperature"
class="value">--</div>
</div>
<div class="card">
<h3>Humidity</h3>
<div id="humidity"
class="value">--</div>
</div>
<div class="card">
<h3>Methane</h3>
<div id="methane"
class="value">--</div>
</div>
<div class="card">
<h3>CO</h3>
<div id="co"
class="value">--</div>
</div>
<div class="card">
<h3>Risk Score</h3>
<div id="risk"
class="value">--</div>
</div>
<div class="card">
<h3>System Status</h3>
<div id="status"
class="value normal">
NORMAL
</div>
</div>
</div>
<script>
const CHANNEL_ID = "YOUR_CHANNEL_ID";
async function updateDashboard() {
const url =
`https://api.thingspeak.com/channels/` +
`${CHANNEL_ID}/feeds.json?results=1`;
try {
const response =
await fetch(url);
const data =
await response.json();
const feed =
data.feeds[0];
document.getElementById(
"temperature"
).textContent =
feed.field1 ?? "--";
document.getElementById(
"humidity"
).textContent =
feed.field2 ?? "--";
document.getElementById(
"methane"
).textContent =
feed.field3 ?? "--";
document.getElementById(
"co"
).textContent =
feed.field4 ?? "--";
const risk =
Number(feed.field6 || 0);
document.getElementById(
"risk"
).textContent =
risk + " / 100";
const status =
document.getElementById(
"status"
);
if (risk >= 80) {
status.textContent =
"CRITICAL";
status.className =
"value critical";
} else if (risk >= 40) {
status.textContent =
"WARNING";
status.className =
"value warning";
} else {
status.textContent =
"NORMAL";
status.className =
"value normal";
}
} catch (error) {
console.error(error);
}
}
updateDashboard();
setInterval(
updateDashboard,
15000
);
</script>
</body>
</html>
33. Dashboard Data Flow
ESP32
│
▼
n8n
│
├───────────────► Google Sheets
│
└───────────────► ThingSpeak
│
▼
Web Dashboard
│
▼
Supervisor
34. Google Sheets Data Flow
ESP32
│
▼
n8n Webhook
│
▼
Data validation
│
▼
Google Sheets node
│
▼
Spreadsheet
Example spreadsheet:
+----------+------+-------+------+-----+------+------+
| Time | ID | Temp | CH4 | CO | Fall | Risk |
+----------+------+-------+------+-----+------+------+
| 10:00:01 | H001 | 31.2 | 320 | 60 | No | 12 |
| 10:00:06 | H001 | 31.4 | 340 | 65 | No | 16 |
| 10:00:11 | H001 | 32.0 | 410 | 72 | No | 28 |
| 10:00:16 | H001 | 33.1 | 580 | 103 | Yes | 86 |
+----------+------+-------+------+-----+------+------+
35. Complete n8n Automation
A practical workflow can contain:
01 Webhook
↓
02 Code / Validate JSON
↓
03 Set Helmet ID
↓
04 Google Sheets — Log raw data
↓
05 HTTP Request — ThingSpeak
↓
06 AI Agent
↓
07 Structured Output Parser
↓
08 Switch Risk Level
│
├── NORMAL
│ ↓
│ Log only
│
├── WARNING
│ ↓
│ Telegram message
│
├── HIGH
│ ↓
│ Telegram message
│ ↓
│ Google Sheets event log
│
└── CRITICAL
↓
Telegram message
↓
TTS API
↓
Telegram Voice
↓
Google Sheets
↓
Supervisor
36. Agentic IoT Concept
The important difference between ordinary IoT and agentic IoT is that the cloud system can interpret the data and select actions.
Conventional IoT
Sensor
↓
Cloud
↓
Dashboard
Agentic IoT
Sensor
↓
Cloud
↓
AI Agent
↓
Understand
↓
Reason
↓
Choose action
↓
Execute action
↓
Verify/log result
For this project:
ESP32
↓
"CH4 increasing + impact + inactivity"
↓
AI Agent
↓
"Possible serious event"
↓
Telegram text
↓
TTS
↓
Telegram voice
↓
Google Sheets event record
37. Example Emergency Scenario
Suppose the worker is operating underground.
At:
10:20:01
the system measures:
Methane = normal
Acceleration = 1.02 g
Temperature = 31°C
Risk:
12/100
At:
10:20:06
methane begins increasing.
Methane = 410
Risk:
28/100
At:
10:20:11
the helmet detects:
Acceleration = 5.9 g
The ESP32 locally identifies a possible impact.
At:
10:20:16
the worker remains nearly motionless.
The ESP32 sends:
{
"helmet_id": "H001",
"methane": 580,
"co": 103,
"acceleration": 5.9,
"fall": true,
"sos": false,
"temperature": 33.1
}
n8n receives it.
The AI Agent evaluates:
Gas increasing
+
High acceleration
+
Possible fall
+
Abnormal motion
and returns:
CRITICAL
Risk = 86
Then:
CRITICAL
│
┌──────────┴──────────┐
▼ ▼
Telegram text Voice generation
│
▼
Telegram voice
Supervisor receives:
🚨 CRITICAL ALERT
Helmet H001
Possible worker fall detected.
Elevated hazardous gas readings
were also detected.
Risk: 86/100.
Check worker immediately.
38. Local Emergency Path
The most important safety architecture is:
SENSOR
│
▼
ESP32
│
┌──────────┴───────────┐
│ │
▼ ▼
LOCAL ALARM INTERNET
│ │
▼ ▼
Worker n8n
│
▼
AI Agent
│
▼
Supervisor
Even if:
Wi-Fi fails
the local alarm can still operate.
39. Offline Mode
Mining environments may have unreliable connectivity.
Therefore implement:
Wi-Fi connected?
│
┌───┴────┐
YES NO
│ │
▼ ▼
n8n Local alarm
│ │
▼ ▼
Cloud SD/Flash buffer
When Wi-Fi returns:
Stored records
↓
Upload old data
↓
Cloud
An optional microSD module can be added for local event storage.
40. Watchdog
The firmware should include a watchdog.
ESP32 running
│
▼
Sensor loop
│
▼
Communication
│
▼
Watchdog reset if firmware hangs
This is important for long-duration operation.
41. Heartbeat
Send a heartbeat packet every few seconds:
{
"helmet_id": "H001",
"device_status": "ONLINE",
"battery": 3.91,
"firmware": "1.0.0",
"timestamp": "..."
}
n8n can detect:
No heartbeat for 30 seconds
↓
DEVICE OFFLINE
↓
Supervisor notification
42. Battery Monitoring
Use a voltage divider:
Battery +
│
100k
│
├──────── ESP32 ADC
│
100k
│
GND
For example:
Battery = 4.2 V
ADC ≈ 2.1 V
The actual divider and ADC calibration must be designed for the selected ESP32 variant and battery.
43. SOS Button
The SOS button should be treated as a high-priority event.
Worker presses SOS
↓
ESP32
↓
Local buzzer
↓
JSON event
↓
n8n
↓
Bypass normal AI delay
↓
Telegram emergency
↓
Voice alert
A good architecture is to have n8n immediately route:
SOS = TRUE
to the emergency branch.
Do not make an LLM decide whether an explicitly pressed emergency button constitutes an emergency.
44. Security
Do not hard-code sensitive credentials into public source code.
Bad:
const char* PASSWORD = "myPassword123";
for code that will be uploaded to GitHub.
Use:
Environment variables
Secret manager
n8n credentials
Secure provisioning
At minimum:
ESP32
│
HTTPS
│
▼
n8n
and authenticate the webhook with a secret/token.
45. Recommended Webhook Security
Instead of:
POST /webhook/mining-helmet
use a secret header:
X-Helmet-Key: YOUR_SECRET
n8n checks:
Header correct?
│
┌─┴──┐
YES NO
│ │
▼ ▼
Process Reject
46. MQTT Alternative
For a larger deployment, consider MQTT:
ESP32
↓
MQTT
↓
MQTT Broker
↓
n8n
Topics:
mine/helmet/H001/sensors
mine/helmet/H001/status
mine/helmet/H001/alert
mine/helmet/H001/command
This is more scalable than sending independent HTTP requests when many helmets are involved.
For the first prototype, however:
ESP32 → HTTP → n8n
is simpler.
47. Multi-Helmet Architecture
For 100 workers:
Helmet H001 ─┐
Helmet H002 ─┤
Helmet H003 ─┤
Helmet H004 ─┤
Helmet H005 ─┤
│
▼
MQTT / HTTP
│
▼
n8n
│
┌──────┼──────┐
▼ ▼ ▼
Database Sheets ThingSpeak
│
▼
AI Agent
│
▼
Supervisor Dashboard
Each helmet must have a unique:
helmet_id
48. AI Risk Dashboard
The dashboard should display:
┌─────────────────────────────────────────┐
│ MINE CONTROL ROOM │
├─────────────────────────────────────────┤
│ │
│ H001 🟢 NORMAL Risk: 18 │
│ H002 🟡 WARNING Risk: 52 │
│ H003 🔴 CRITICAL Risk: 91 │
│ H004 🟢 NORMAL Risk: 12 │
│ H005 🟠HIGH Risk: 72 │
│ │
└─────────────────────────────────────────┘
Selecting H003:
Helmet H003
Temperature: 34.2°C
Humidity: 71%
Methane: HIGH
CO: HIGH
Acceleration: abnormal
Fall: POSSIBLE
AI Risk: 91/100
Recommendation:
Immediate worker verification.
49. Project Software Stack
┌──────────────────────────────────┐
│ FRONTEND │
│ HTML + CSS + JavaScript │
└────────────────┬─────────────────┘
│
▼
┌──────────────────────────────────┐
│ CLOUD DASHBOARD │
│ ThingSpeak │
└────────────────┬─────────────────┘
│
│
┌────────────────▼─────────────────┐
│ n8n │
│ │
│ Webhook │
│ Data processing │
│ AI Agent │
│ Google Sheets │
│ Telegram │
│ TTS │
└────────────────┬─────────────────┘
│
▼
┌──────────────────────────────────┐
│ ESP32 │
│ │
│ Sensors │
│ Local safety logic │
│ Wi-Fi │
│ JSON │
└──────────────────────────────────┘
50. Development Procedure
Phase 1 — ESP32 setup
Install:
Arduino IDE
ESP32 board package
Required libraries
Espressif provides official Arduino-ESP32 setup documentation.
Test:
Blink LED
↓
Wi-Fi
↓
Serial monitor
Phase 2 — MPU6050
Test:
Acceleration X
Acceleration Y
Acceleration Z
Gyroscope X
Gyroscope Y
Gyroscope Z
Verify that the helmet reports approximately:
1 g
when stationary due to gravity.
Phase 3 — BME280
Display:
Temperature
Humidity
Pressure
Phase 4 — Gas sensors
Allow the sensors to warm up according to their datasheets.
Then:
Raw ADC
↓
Calibration
↓
Baseline
↓
Abnormal detection
Do not use arbitrary raw ADC thresholds as certified gas limits.
Phase 5 — Fall detection
Collect data for:
Walking
Running
Sitting
Bending
Helmet movement
Safe controlled impact simulation
Then tune:
impact threshold
inactivity period
orientation threshold
Never test dangerous falls on people.
51. Phase 6 — n8n
Build:
Webhook
↓
JSON
↓
Google Sheets
First confirm that the data reaches the spreadsheet.
Then add:
ThingSpeak
Then:
AI Agent
Then:
Telegram
Finally:
TTS + Telegram Voice
This staged approach makes debugging much easier.
52. Phase 7 — AI
Start with a rule-based model:
Risk = rule engine
Then add AI:
Rule engine
+
AI interpretation
Finally, when enough labeled data exists:
Machine-learning model
+
AI Agent
This is much better than immediately asking an LLM to "predict accidents" from arbitrary sensor values.
53. Testing Matrix
| Test | Expected result |
|---|---|
| ESP32 boot | Device starts |
| Wi-Fi | Connected |
| BME280 | Valid readings |
| MPU6050 | Valid readings |
| MQ sensors | ADC values change |
| SOS | Immediate local alarm |
| Impact simulation | Possible fall |
| n8n webhook | JSON received |
| Google Sheets | Row inserted |
| ThingSpeak | Chart updated |
| AI Agent | JSON risk result |
| Telegram | Text alert |
| TTS | Audio generated |
| Telegram voice | Voice received |
| Wi-Fi failure | Local safety logic continues |
| Device restart | Firmware recovers |
54. Example Test Case
Test 1 — Normal operation
Input:
Temperature = 30°C
Gas = normal
Acceleration = 1.0g
Fall = false
SOS = false
Expected:
Risk = LOW
No emergency alert
Dashboard = GREEN
Test 2 — Gas warning
Gas = increasing
Temperature = normal
Motion = normal
Expected:
Risk = WARNING
Telegram text alert
Test 3 — Possible fall
Acceleration = 5g+
Fall = true
Inactivity = true
Expected:
Risk = HIGH/CRITICAL
Local alarm
Telegram
Voice alert
Test 4 — SOS
SOS = true
Expected:
Immediate local alarm
Immediate Telegram alert
Voice alert
Event stored
55. Project Folder Structure
AI-Mining-Helmet/
│
├── firmware/
│ ├── mining_helmet.ino
│ ├── config.h
│ ├── sensors.cpp
│ ├── sensors.h
│ ├── fall_detection.cpp
│ └── fall_detection.h
│
├── n8n/
│ ├── workflow-design.md
│ ├── ai-prompt.txt
│ └── sample-payload.json
│
├── dashboard/
│ ├── index.html
│ ├── style.css
│ └── dashboard.js
│
├── documentation/
│ ├── project-report.md
│ ├── architecture.md
│ ├── testing.md
│ └── calibration.md
│
└── README.md
56. Final System Flow Diagram
┌─────────────────┐
│ WORKER │
│ MINING HELMET │
└────────┬────────┘
│
▼
┌────────────────────────┐
│ ESP32 │
│ │
│ Temp/Humidity │
│ Gas │
│ Accelerometer │
│ Gyroscope │
│ GPS │
│ Battery │
│ SOS │
└───────────┬────────────┘
│
Local safety│logic
│
┌───────────┴────────────┐
│ │
▼ ▼
Local Alarm Wi-Fi
│
▼
┌─────────────────┐
│ n8n │
│ │
│ Webhook │
│ Automation │
│ AI Agent │
└───────┬─────────┘
│
┌───────────────────────────┼─────────────────────┐
│ │ │
▼ ▼ ▼
┌──────────────┐ ┌─────────────┐ ┌─────────────┐
│Google Sheets │ │ ThingSpeak │ │ AI Decision │
│ │ │ │ │ │
│Historical │ │ Dashboard │ │ Risk Score │
│Data │ │ Graphs │ │ │
└──────────────┘ └─────────────┘ └──────┬──────┘
│
┌──────────────┼───────────┐
│ │ │
▼ ▼ ▼
NORMAL WARNING CRITICAL
│ │ │
│ ▼ ▼
│ Telegram Telegram
│ │
│ ▼
│ TTS Engine
│ │
│ ▼
│ Telegram Voice
│ │
└─────────────┬───────────┘
▼
┌──────────────┐
│ SUPERVISOR │
│ PHONE / PC │
└──────────────┘
57. Final Project Workflow in One Sentence
ESP32 sensors continuously monitor the miner and environment → ESP32 performs immediate local safety detection → data is sent to n8n → n8n stores it in Google Sheets and ThingSpeak → an AI Agent analyzes the current state and history → risk is classified → n8n automatically sends Telegram text and, for serious events, a Telegram voice alert → the supervisor monitors the situation through the web/cloud dashboard.
58. Recommended Final-Year Project Features
To make this a strong academic/engineering project, implement the following in stages:
- ESP32 sensor acquisition
- MPU6050 fall/impact detection
- Gas/environment monitoring
- SOS emergency button
- Local buzzer + vibration alarm
- Wi-Fi JSON communication
- n8n webhook
- Google Sheets logging
- ThingSpeak cloud dashboard
- n8n AI Agent
- Risk-score engine
- Telegram text notifications
- TTS-generated Telegram voice notifications
- Browser dashboard
- Offline data buffering
- Device heartbeat
- Battery monitoring
- Historical-data-based ML model
- Multi-helmet support
- Security/authentication
The ESP32 platform has the necessary networking/peripheral capabilities for this prototype, while n8n's Telegram integration and Telegram's Bot API provide the automation/notification path.
For the next engineering iteration, the most valuable upgrade is to replace the illustrative gas thresholds with calibrated sensor measurements and validated alarm limits, and replace the initial rule-based "accident prediction" with a model trained on experimentally collected and labeled helmet-motion/environment data.

No comments:
Post a Comment