/* MQ-7 Module - با ضرایب صحیح */ #include 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); }