backup 14041130
This commit is contained in:
197
14041130/MQ7-1/MQ7-1.ino
Normal file
197
14041130/MQ7-1/MQ7-1.ino
Normal file
@@ -0,0 +1,197 @@
|
||||
#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);
|
||||
}
|
||||
148
14041130/MQ7-1/Voltage_Reader.h
Normal file
148
14041130/MQ7-1/Voltage_Reader.h
Normal file
@@ -0,0 +1,148 @@
|
||||
#ifndef VOLTAGE_READER_H
|
||||
#define VOLTAGE_READER_H
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#define VOLTAGE_DIVIDER_PIN PA0 // پین خواندن ولتاژ
|
||||
#define BATTERY_VOLTAGE_PIN_A3 PA3 // پین جدید برای باتری
|
||||
#define VOLTAGE_DIVIDER_RATIO 2.0 // نسبت تقسیم (R1=R2=10k => نسبت = 2)
|
||||
#define ADC_REF_VOLTAGE 3.3 // ولتاژ مرجع ADC در STM32 (معمولاً 3.3V)
|
||||
#define ADC_RESOLUTION 4096 // رزولوشن ADC 12-bit = 4096
|
||||
|
||||
|
||||
class VoltageReader {
|
||||
private:
|
||||
float filteredVoltage = 0.0;
|
||||
bool firstReading = true; // فلگ برای اولین خواندن
|
||||
const float alpha = 0.3; // ضریب فیلتر را کمی بیشتر کردم
|
||||
|
||||
public:
|
||||
VoltageReader() {
|
||||
init();
|
||||
}
|
||||
|
||||
void init() {
|
||||
pinMode(VOLTAGE_DIVIDER_PIN, INPUT_ANALOG);
|
||||
analogReadResolution(12); // تنظیم رزولوشن ADC به 12-bit
|
||||
delay(100); // کمی بیشتر صبر کن
|
||||
|
||||
// چند بار خواندن برای تخلیه خازنهای داخلی
|
||||
for (int i = 0; i < 10; i++) {
|
||||
analogRead(VOLTAGE_DIVIDER_PIN);
|
||||
delay(1);
|
||||
}
|
||||
}
|
||||
|
||||
// خواندن ولتاژ بدون فیلتر
|
||||
float readRawVoltage() {
|
||||
int samples = 32; // تعداد نمونهها را بیشتر کردم
|
||||
long sum = 0;
|
||||
|
||||
for (int i = 0; i < samples; i++) {
|
||||
sum += analogRead(VOLTAGE_DIVIDER_PIN);
|
||||
delayMicroseconds(20);
|
||||
}
|
||||
|
||||
int rawValue = sum / samples;
|
||||
|
||||
// تبدیل به ولتاژ
|
||||
float voltageAtPin = (rawValue * ADC_REF_VOLTAGE) / ADC_RESOLUTION;
|
||||
|
||||
// محاسبه ولتاژ اصلی
|
||||
float actualVoltage = voltageAtPin * VOLTAGE_DIVIDER_RATIO;
|
||||
|
||||
return actualVoltage;
|
||||
}
|
||||
|
||||
// خواندن با فیلتر
|
||||
float readVoltage() {
|
||||
float currentVoltage = readRawVoltage();
|
||||
|
||||
// اگر اولین بار است، فیلتر را با مقدار فعلی مقداردهی کن
|
||||
if (firstReading) {
|
||||
filteredVoltage = currentVoltage;
|
||||
firstReading = false;
|
||||
} else {
|
||||
// اعمال فیلتر Low-pass
|
||||
filteredVoltage = (alpha * currentVoltage) + ((1 - alpha) * filteredVoltage);
|
||||
}
|
||||
|
||||
return currentVoltage; // actual voltage برمیگردانیم
|
||||
}
|
||||
|
||||
// دریافت ولتاژ فیلتر شده
|
||||
float getFilteredVoltage() {
|
||||
return filteredVoltage;
|
||||
}
|
||||
|
||||
// تست سلامت مدار
|
||||
bool testCircuit() {
|
||||
Serial1.println("\n🔌 Testing voltage divider circuit...");
|
||||
|
||||
// چند بار خواندن برای اطمینان
|
||||
float sum = 0;
|
||||
int readings = 10;
|
||||
|
||||
for (int i = 0; i < readings; i++) {
|
||||
sum += readRawVoltage();
|
||||
delay(50);
|
||||
}
|
||||
|
||||
float avgVoltage = sum / readings;
|
||||
|
||||
Serial1.print("Average voltage: ");
|
||||
Serial1.print(avgVoltage, 2);
|
||||
Serial1.println("V");
|
||||
|
||||
Serial1.print("Raw ADC value: ");
|
||||
Serial1.println(analogRead(VOLTAGE_DIVIDER_PIN));
|
||||
|
||||
// ولتاژ در پین
|
||||
float pinVoltage = avgVoltage / VOLTAGE_DIVIDER_RATIO;
|
||||
Serial1.print("Voltage at PA0 pin: ");
|
||||
Serial1.print(pinVoltage, 2);
|
||||
Serial1.println("V");
|
||||
|
||||
if (avgVoltage > 4.5 && avgVoltage < 5.5) {
|
||||
Serial1.println("✅ Circuit OK (within expected 5V ±10%)");
|
||||
return true;
|
||||
} else {
|
||||
Serial1.print("❌ Expected ~5V, got ");
|
||||
Serial1.print(avgVoltage, 2);
|
||||
Serial1.println("V");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// نمایش اطلاعات دیباگ
|
||||
void debugInfo() {
|
||||
float rawVoltage = readRawVoltage();
|
||||
int rawADC = analogRead(VOLTAGE_DIVIDER_PIN);
|
||||
float pinVoltage = rawVoltage / VOLTAGE_DIVIDER_RATIO;
|
||||
|
||||
Serial1.println("\n📊 Voltage Debug Info:");
|
||||
Serial1.print("Raw ADC value: ");
|
||||
Serial1.println(rawADC);
|
||||
Serial1.print("Voltage at PA0 pin: ");
|
||||
Serial1.print(pinVoltage, 3);
|
||||
Serial1.println("V");
|
||||
Serial1.print("Actual voltage (raw): ");
|
||||
Serial1.print(rawVoltage, 3);
|
||||
Serial1.println("V");
|
||||
Serial1.print("Filtered voltage: ");
|
||||
Serial1.print(filteredVoltage, 3);
|
||||
Serial1.println("V");
|
||||
}
|
||||
|
||||
// ریست فیلتر
|
||||
void resetFilter() {
|
||||
filteredVoltage = 0.0;
|
||||
firstReading = true;
|
||||
Serial1.println("✅ Voltage filter reset");
|
||||
}
|
||||
};
|
||||
|
||||
// ایجاد نمونه سراسری
|
||||
VoltageReader voltageReader;
|
||||
|
||||
#endif // VOLTAGE_READER_H
|
||||
Reference in New Issue
Block a user