116 lines
2.6 KiB
C++
116 lines
2.6 KiB
C++
/*
|
|
MQ-7 Module - با ضرایب صحیح
|
|
*/
|
|
|
|
#include <Arduino.h>
|
|
|
|
const uint8_t ADC_PIN = PA2;
|
|
const uint8_t LED_PIN = PC13;
|
|
|
|
const float ADC_REF = 3.3;
|
|
const uint32_t ADC_MAX = 4095;
|
|
const float RL = 10000.0;
|
|
float R0 = -1.0;
|
|
const float CO_THRESHOLD = 50.0;
|
|
|
|
// ضرایب صحیح برای MQ-7 و گاز CO
|
|
const float CO_A = 99.042;
|
|
const float CO_B = -1.518;
|
|
|
|
float readVoltage() {
|
|
const int N = 10;
|
|
uint32_t sum = 0;
|
|
for (int i = 0; i < N; i++) {
|
|
sum += analogRead(ADC_PIN);
|
|
delay(3);
|
|
}
|
|
float adc_avg = sum / float(N);
|
|
return adc_avg * (ADC_REF / ADC_MAX);
|
|
}
|
|
|
|
float calcRs(float Vout) {
|
|
if (Vout <= 0.001) return 1e6;
|
|
|
|
// فرمول اصلاح شده: ما Vout را از سنسور میخوانیم که نسبت به 5V داخلی ماژول است
|
|
// بنابراین باید از 5.0 در فرمول استفاده کنیم، نه ADC_REF
|
|
return RL * (5.0 - Vout) / Vout; // این فرمول صحیح است
|
|
}
|
|
|
|
float toRealPPM(float Rs) {
|
|
if (R0 <= 0) return -1;
|
|
float ratio = Rs / R0;
|
|
|
|
// فرمول صحیح براساس دیتاشیت MQ-7
|
|
float ppm = CO_A * pow(ratio, CO_B);
|
|
|
|
return ppm;
|
|
}
|
|
|
|
void calibrateR0() {
|
|
Serial1.println("=== Calibrating R0 in clean air ===");
|
|
const int N = 50;
|
|
float sum_R0 = 0;
|
|
|
|
for (int i = 0; i < N; i++) {
|
|
float V = readVoltage();
|
|
float Rs = calcRs(V);
|
|
|
|
// در هوای پاک: نسبت Rs/R0 ≈ 27.5 (طبق دیتاشیت)
|
|
// بنابراین: R0 = Rs / 27.5
|
|
sum_R0 += Rs / 27.5;
|
|
|
|
delay(100);
|
|
}
|
|
|
|
R0 = sum_R0 / N;
|
|
Serial1.print("Calibration complete. R0 = ");
|
|
Serial1.println(R0, 2);
|
|
}
|
|
|
|
void setup() {
|
|
Serial1.begin(115200);
|
|
pinMode(LED_PIN, OUTPUT);
|
|
digitalWrite(LED_PIN, LOW);
|
|
|
|
Serial1.println("MQ-7 CO Monitor - Waiting for warm up...");
|
|
delay(30000); // 30 ثانیه پیشگرمایش
|
|
Serial1.println("Ready. Send 'c' to calibrate.");
|
|
calibrateR0();
|
|
}
|
|
|
|
void loop() {
|
|
if (Serial1.available()) {
|
|
char c = Serial1.read();
|
|
if (c == 'c' || c == 'C') calibrateR0();
|
|
}
|
|
|
|
float V = readVoltage();
|
|
float Rs = calcRs(V);
|
|
float ppm = toRealPPM(Rs);
|
|
|
|
Serial1.print("Vout=");
|
|
Serial1.print(V, 3);
|
|
Serial1.print("V, Rs=");
|
|
Serial1.print(Rs, 1);
|
|
Serial1.print("Ω");
|
|
|
|
if (R0 > 0) {
|
|
Serial1.print(", Rs/R0=");
|
|
Serial1.print(Rs/R0, 3);
|
|
Serial1.print(", CO=");
|
|
Serial1.print(ppm, 1);
|
|
Serial1.println("ppm");
|
|
|
|
// هشدار
|
|
if (ppm > CO_THRESHOLD) {
|
|
digitalWrite(LED_PIN, HIGH);
|
|
Serial1.println("⚠️ WARNING: High CO level!");
|
|
} else {
|
|
digitalWrite(LED_PIN, LOW);
|
|
}
|
|
} else {
|
|
Serial1.println(" [Not calibrated]");
|
|
}
|
|
|
|
delay(2000);
|
|
} |