// I tested this 5/14/25, it works irl!!!! Now with RTC + PPM
#include <Wire.h>
#include "RTClib.h"
#define MQ2pin 2 // or 26, either is fine
#define Buzzer 5 // can be any
#define RL 10.0 // load resistor in kΩ
#define Ro 3.3 // default Ro in clean air (kΩ), approximated
int dangerPPM = 2000; // 2000 ppm threshold for LPG alert
RTC_DS3231 rtc;
char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
// function to read Rs using analog voltage
float readRs(int analogPin, float RL) {
int adc = analogRead(analogPin);
float voltage = adc * (3.3 / 1023.0); // 5 represents the voltage
float rs = (3.3 - voltage) * RL / voltage;
return rs;
}
// function to estimate LPG PPM based on Rs/Ro ratio
float estimateLPGppm(float rs, float ro) {
float rs_ro_ratio = rs / ro;
// LPG curve approximation from datasheet
float m = -0.38;
float b = 1.15;
float logRatio = log10(rs_ro_ratio);
float logPPM = (logRatio - b) / m;
float ppm = pow(10, logPPM);
return ppm;
}
void setup() {
Serial.begin(9600);
pinMode(Buzzer, OUTPUT);
Serial.println("MQ2 warming up!");
// allow the MQ2 to warm up
delay(20000);
// start RTC
if (!rtc.begin()) {
Serial.println("Couldn't find RTC");
while (1) delay(10);
}
if (rtc.lostPower()) {
Serial.println("RTC lost power, setting time to compile time");
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
}
}
void loop() {
// get sensor reading and convert to PPM
float rs = readRs(MQ2pin, RL);
float ppm = estimateLPGppm(rs, Ro);
// get RTC time
DateTime now = rtc.now();
String yearStr = String(now.year(), DEC);
String monthStr = (now.month() < 10 ? "0" : "") + String(now.month(), DEC);
String dayStr = (now.day() < 10 ? "0" : "") + String(now.day(), DEC);
String hourStr = (now.hour() < 10 ? "0" : "") + String(now.hour(), DEC);
String minuteStr = (now.minute() < 10 ? "0" : "") + String(now.minute(), DEC);
String secondStr = (now.second() < 10 ? "0" : "") + String(now.second(), DEC);
String dayOfWeek = daysOfTheWeek[now.dayOfTheWeek()];
String timestamp = dayOfWeek + ", " + yearStr + "-" + monthStr + "-" + dayStr + " " + hourStr + ":" + minuteStr + ":" + secondStr;
// print readings
Serial.print("Timestamp: ");
Serial.println(timestamp);
Serial.print("Sensor Rs: ");
Serial.print(rs);
Serial.print(" kΩ, Estimated LPG PPM: ");
Serial.println(ppm);
// if ppm exceeds threshold, activate buzzer
if (ppm >= dangerPPM) {
Serial.println("Danger: Gas concentration exceeded safe limit");
digitalWrite(Buzzer, HIGH); // buzzer on
delay(20000); // give the miner time to react
digitalWrite(Buzzer, LOW); // buzzer off
}
delay(15000); // sample every 15 seconds
}
Loading
xiao-esp32-c3
xiao-esp32-c3