Files
Arduino/14041130/MQ7-1/MQ7-1.ino
2026-02-19 06:17:44 +03:30

197 lines
5.5 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <U8g2lib.h>
#include <Wire.h>
#include "Voltage_Reader.h"
// تنظیمات OLED
#define I2C_SDA_PIN PB9
#define I2C_SCL_PIN PB8
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);
// ========== پارامترهای مدار MQ7 (مقادیر دقیق اندازه‌گیری‌شده) ==========
#define VREF_ADC 3.3f // ولتاژ مرجع ADC
#define ADC_RESOLUTION 4095.0f // رزولوشن ADC 12 بیت
#define R1 2190.0f // مقاومت سری اول (اهم)
#define R2 3270.0f // مقاومت به زمین (اهم)
#define RL_SENSOR 839.0f // مقاومت بار ماژول (مقاومت بین خروجی آنالوگ و GND)
#define ADC_PIN PA2 // پین ADC
#define NUM_SAMPLES 10 // تعداد نمونه برای میانگین‌گیری
// پارامترهای سنسور MQ7 برای تبدیل به ppm (از دیتاشیت)
#define CO_A 1.9f // ضریب A
#define CO_B -0.6f // ضریب B
// ============================ متغیرهای سراسری ============================
// متغیرهای جهانی
float VCC_SENSOR = 4.9f; // ولتاژ تغذیه سنسور MQ7
float MQ7_R0 = 21000.0; // مقدار R0 (پس از کالیبراسیون) تقریب اولیه ۲۰ کیلواهم
bool calibrationComplete = false;
unsigned long lastReadTime = 0;
const unsigned long readInterval = 3000;
float volage;
float readSensorVoltage() {
uint32_t sum = 0;
for (int i = 0; i < NUM_SAMPLES; i++) {
sum += analogRead(ADC_PIN);
delay(10);
}
float adcValue = sum / (float)NUM_SAMPLES;
float vAdc = (adcValue / ADC_RESOLUTION) * VREF_ADC;
// محاسبه ولتاژ خروجی سنسور با جبران تقسیم ولتاژ (R1 و R2)
return vAdc * (R1 + R2) / R2;
}
float calculateRs(float vOut) {
if (vOut <= 0.0f) return 0.0f;
return RL_SENSOR * (VCC_SENSOR / vOut - 1.0f);
}
float calculatePPM(float rs) {
float ratio = rs / MQ7_R0;
if (ratio <= 0.0f) return 0.0f;
return CO_A * pow(ratio, CO_B);
}
// ========== کالیبراسیون MQ7 ==========
void calibrateMQ7() {
Serial1.println("Starting calibration in clean air...");
u8g2.clearBuffer();
u8g2.setFont(u8g2_font_ncenB08_tr);
u8g2.drawStr(0, 30, "Calibrating ...");
u8g2.drawStr(0, 50, "Wait 120 seconds");
u8g2.sendBuffer();
// صبر برای پایدار شدن سنسور (توصیه: حداقل ۲ دقیقه، ولی برای نمونه ۳۰ ثانیه)
delay(120000);
float sumRs = 0;
const int samples = 50;
for (int i = 0; i < samples; i++) {
float vOut = readSensorVoltage();
float rs = calculateRs(vOut);
sumRs += rs;
delay(20);
}
//////////MQ7_R0 = sumRs / samples; // در هوای پاک R0 = Rs
calibrationComplete = true;
Serial1.print("[MQ7] Calibration complete. R0 = ");
Serial1.println(MQ7_R0, 1);
Serial1.println("You can update the #define R0 in code with this value for future use.");
}
// ========== خواندن CO با استفاده از پارامترهای جدید ==========
float readCO() {
if (!calibrationComplete) return -1.0f;
float vOut = readSensorVoltage();
float rs = calculateRs(vOut);
float ppm = calculatePPM(rs);
// محدود کردن به بازه معقول
ppm = constrain(ppm, 0.0f, 5000.0f);
return ppm;
}
// نمایش روی OLED
void displayCO(int ppm) {
if(ppm<0)
return;
u8g2.clearBuffer();
// انتخاب فونت بر اساس اندازه عدد
if (ppm < 1000) {
// برای اعداد تا ۳ رقمی از فونت 35 پیکسل
u8g2.setFont(u8g2_font_fub35_tr);
// موقعیت مرکزی
if (ppm < 10) {
u8g2.setCursor(50, 55);
} else if (ppm < 100) {
u8g2.setCursor(25, 55);
} else {
u8g2.setCursor(10, 55);
}
} else {
// برای اعداد ۴ رقمی از فونت 25 پیکسل
u8g2.setFont(u8g2_font_fub25_tr);
u8g2.setCursor(10, 60);
}
u8g2.print(ppm);
// نمایش واحد ppm در پایین
u8g2.setFont(u8g2_font_ncenB12_tr);
u8g2.setCursor(90, 60);
u8g2.print("ppm");
u8g2.sendBuffer();
}
void setup() {
Serial1.begin(115200);
delay(2000);
// تنظیم پین I2C
Wire.setSDA(I2C_SDA_PIN);
Wire.setSCL(I2C_SCL_PIN);
Wire.begin();
// راه‌اندازی OLED
u8g2.begin();
u8g2.setFont(u8g2_font_ncenB08_tr);
u8g2.clearBuffer();
u8g2.drawStr(0, 35, "Sensor Calibrating...");
u8g2.sendBuffer();
analogReadResolution(12);
bool voltageOK = voltageReader.testCircuit();
if (!voltageOK) {
Serial1.println("⚠️ Voltage issue detected!");
}
// 2. اطلاعات دیباگ ولتاژ
voltageReader.debugInfo();
volage=voltageReader.readVoltage();
VCC_SENSOR=volage;
// کالیبراسیون اولیه سنسور
calibrateMQ7();
// نمایش پیام راه‌اندازی
/*u8g2.clearBuffer();
u8g2.drawStr(0, 40, "MQ-7 Ready!");
u8g2.drawStr(0, 60, "Monitoring CO...");
u8g2.sendBuffer();*/
delay(2000);
}
void loop() {
if (millis() - lastReadTime >= readInterval) {
volage=voltageReader.readVoltage();
VCC_SENSOR=volage;
float ppm = readCO();
int ppm_rounded = round(ppm);
displayCO(ppm_rounded);
//voltageReader.debugInfo();
// نمایش در سریال مانیتور (اختیاری)
Serial1.print("CO Concentration: ");
Serial1.print(ppm);
Serial1.println(" ppm");
Serial1.print(" VCC_SENSOR:");
Serial1.println(VCC_SENSOR);
lastReadTime = millis();
}
delay(1000);
}