Files
Arduino/14041130/TestLCD/Sensors - Copy.hold
2026-02-19 06:17:44 +03:30

472 lines
12 KiB
Plaintext

#ifndef SENSORS_H
#define SENSORS_H
#include <Arduino.h>
#include <Wire.h>
#include "Config.h"
#define VCC 4.63
#define RL 10000.0
#define VDIV_RATIO 0.681
#define I2C_TIMEOUT_MS 100
// تعریف پین‌ها
#define BH1750_SDA_PIN PB7
#define BH1750_SCL_PIN PB6
#define SHT31_SDA_PIN PB9
#define SHT31_SCL_PIN PB8
#define SHT31_ADDR 0x44
#define BH1750_ADDR 0x23
// متغیرهای خارجی
extern SensorData currentData;
extern bool sht31Connected;
extern bool lightSensorConnected;
extern bool coSensorConnected;
extern bool calibrationComplete;
extern unsigned long systemStartTime;
extern unsigned long lastSensorRead;
extern float MQ7_R0;
extern TwoWire Wire1;
extern const long calibrationPeriod;
// توابع
void initSensors();
void readSensors();
void checkSensorStatus();
// -------------------- پاکسازی باس I2C --------------------
inline void i2cBusClear(uint8_t scl_pin, uint8_t sda_pin, bool isWire1 = false) {
Serial1.print("Clearing I2C bus on pins SCL:");
Serial1.print(scl_pin);
Serial1.print(" SDA:");
Serial1.println(sda_pin);
// آزاد کردن باس
if (isWire1) {
Wire1.end();
} else {
Wire.end();
}
delay(50);
// تنظیم پین‌ها به صورت دستی
pinMode(scl_pin, OUTPUT_OPEN_DRAIN);
pinMode(sda_pin, OUTPUT_OPEN_DRAIN);
digitalWrite(sda_pin, HIGH);
digitalWrite(scl_pin, HIGH);
delayMicroseconds(10);
// تولید پالس کلاک برای رهاسازی باس
for (int i = 0; i < 18; i++) {
digitalWrite(scl_pin, LOW);
delayMicroseconds(5);
digitalWrite(scl_pin, HIGH);
delayMicroseconds(5);
}
// ایجاد شرط STOP
digitalWrite(sda_pin, LOW);
delayMicroseconds(5);
digitalWrite(scl_pin, HIGH);
delayMicroseconds(5);
digitalWrite(sda_pin, HIGH);
delayMicroseconds(5);
delay(100);
// راه‌اندازی مجدد
if (isWire1) {
Wire1.setSDA(sda_pin);
Wire1.setSCL(scl_pin);
Wire1.begin();
Wire1.setClock(50000); // سرعت پایین برای پایداری
} else {
Wire.setSDA(sda_pin);
Wire.setSCL(scl_pin);
Wire.begin();
Wire.setClock(50000); // سرعت پایین برای پایداری
}
delay(100);
}
// -------------------- کالیبراسیون MQ7 --------------------
inline void calibrateMQ7() {
Serial1.println("Calibrating MQ7...");
float sumRS = 0;
for(int i = 0; i < 50; i++) { // کاهش از 100 به 50
int adc = analogRead(MQ7_PIN);
float v_adc = adc * (5.0 / 4095.0);
float v_ao = v_adc / VDIV_RATIO;
if (v_ao < 0.01) v_ao = 0.01;
float RS = RL * (VCC / v_ao - 1.0);
sumRS += RS;
delay(20); // کاهش تاخیر
}
MQ7_R0 = (sumRS / 50.0) / 9.8;
calibrationComplete = true;
Serial1.print("MQ7 R0 calibrated: ");
Serial1.println(MQ7_R0);
}
// -------------------- خواندن CO --------------------
inline float readCOImproved() {
float sumVoltage = 0;
for (int i = 0; i < 10; i++) { // کاهش از 20 به 10
int adc = analogRead(MQ7_PIN);
float v_adc = adc * (5.0 / 4095.0);
sumVoltage += v_adc;
delay(1);
}
float v_avg = sumVoltage / 10.0;
if (v_avg < 0.01) v_avg = 0.01;
if (v_avg > 4.99) v_avg = 4.99;
float v_ao = v_avg / VDIV_RATIO;
float RS = RL * (VCC / v_ao - 1.0);
float ratio = RS / MQ7_R0;
float ppm = 0;
if (ratio > 0) {
ppm = 100.0 * pow(ratio, -1.53);
ppm = constrain(ppm, 0, 5000);
}
if (!calibrationComplete) {
ppm = -ppm;
}
return ppm;
}
// -------------------- خواندن SHT31 (ساده‌شده) --------------------
inline bool readSHT31(float &temperature, float &humidity) {
static uint8_t errorCount = 0;
static bool needsReset = false;
// اگر نیاز به بازنشانی داریم
if (needsReset) {
Serial1.println("Resetting SHT31 I2C bus...");
i2cBusClear(SHT31_SCL_PIN, SHT31_SDA_PIN, false);
needsReset = false;
delay(100);
}
// تست اتصال اولیه
Wire.beginTransmission(SHT31_ADDR);
uint8_t connError = Wire.endTransmission();
if (connError != 0) {
Serial1.print("SHT31 connection error: ");
Serial1.println(connError);
errorCount++;
if (errorCount >= 2) {
needsReset = true;
errorCount = 0;
}
return false;
}
// ارسال دستور اندازه‌گیری (کوتاه)
Wire.beginTransmission(SHT31_ADDR);
if (Wire.write(0x2C) != 1) { // دستور سریع
Serial1.println("SHT31 write failed");
return false;
}
if (Wire.write(0x06) != 1) { // تکرار بالا
Serial1.println("SHT31 write failed");
return false;
}
uint8_t writeError = Wire.endTransmission();
if (writeError != 0) {
Serial1.print("SHT31 write error: ");
Serial1.println(writeError);
errorCount++;
if (errorCount >= 2) {
needsReset = true;
errorCount = 0;
}
return false;
}
// تاخیر اندازه‌گیری
delay(20); // برای حالت High Repeatability
// خواندن داده
uint8_t bytesRead = Wire.requestFrom(SHT31_ADDR, (uint8_t)6, (uint8_t)true);
if (bytesRead != 6) {
Serial1.print("SHT31 read error, bytes: ");
Serial1.println(bytesRead);
// خالی کردن بافر
while (Wire.available()) {
Wire.read();
}
errorCount++;
if (errorCount >= 2) {
needsReset = true;
errorCount = 0;
}
return false;
}
// خواندن بایت‌ها
uint8_t data[6];
for (int i = 0; i < 6; i++) {
data[i] = Wire.read();
}
// بررسی CRC (ساده‌شده)
uint16_t tRaw = (data[0] << 8) | data[1];
uint16_t hRaw = (data[3] << 8) | data[4];
// تبدیل مقادیر
temperature = -45.0 + 175.0 * tRaw / 65535.0;
humidity = 100.0 * hRaw / 65535.0;
// اعتبارسنجی
if (isnan(temperature) || isnan(humidity) ||
temperature < -40 || temperature > 125 ||
humidity < 0 || humidity > 100) {
Serial1.println("SHT31 invalid data");
return false;
}
errorCount = 0; // ریست شمارنده خطا
return true;
}
// -------------------- خواندن BH1750 --------------------
inline bool readBH1750(float &lux) {
static bool initialized = false;
static uint8_t errorCount = 0;
// مقداردهی اولیه
if (!initialized) {
Serial1.println("Initializing BH1750...");
Wire1.setSDA(BH1750_SDA_PIN);
Wire1.setSCL(BH1750_SCL_PIN);
Wire1.begin();
Wire1.setClock(50000); // سرعت پایین
delay(100);
// پاور آن
Wire1.beginTransmission(BH1750_ADDR);
Wire1.write(0x01);
if (Wire1.endTransmission() != 0) {
Serial1.println("BH1750 power on failed");
return false;
}
delay(10);
// تنظیم حالت
Wire1.beginTransmission(BH1750_ADDR);
Wire1.write(0x13); // Continuous H-Resolution Mode 0.5lx
if (Wire1.endTransmission() != 0) {
Serial1.println("BH1750 mode set failed");
return false;
}
initialized = true;
delay(180); // زمان اولیه برای اندازه‌گیری
}
// خواندن داده
uint8_t bytesRead = Wire1.requestFrom(BH1750_ADDR, (uint8_t)2);
if (bytesRead != 2) {
Serial1.print("BH1750 read error, bytes: ");
Serial1.println(bytesRead);
errorCount++;
if (errorCount >= 3) {
initialized = false;
errorCount = 0;
}
return false;
}
// خواندن بایت‌ها
uint8_t highByte = Wire1.read();
uint8_t lowByte = Wire1.read();
uint16_t raw = (highByte << 8) | lowByte;
lux = raw / 1.2f;
errorCount = 0;
return true;
}
// -------------------- بررسی وضعیت سنسورها --------------------
inline void checkSensorStatus() {
// فقط چاپ وضعیت فعلی
Serial1.println("--- Sensor Status ---");
Serial1.print("SHT31: ");
Serial1.println(sht31Connected ? "OK" : "ERROR");
Serial1.print("BH1750: ");
Serial1.println(lightSensorConnected ? "OK" : "ERROR");
Serial1.print("MQ7: ");
Serial1.println(coSensorConnected ? "OK" : "ERROR");
}
// -------------------- خواندن همه سنسورها --------------------
inline void readSensors() {
Serial1.println("\n=== Reading Sensors ===");
// اول BH1750 را بخوان (چون کار می‌کند)
float lux;
if (readBH1750(lux)) {
currentData.lightLux = lux;
lightSensorConnected = true;
Serial1.print("BH1750: ");
Serial1.print(lux, 0);
Serial1.println(" lux");
} else {
currentData.lightLux = 0;
lightSensorConnected = false;
Serial1.println("BH1750: FAILED");
}
// سپس SHT31
float temperature = NAN, humidity = NAN;
bool sht31Read = readSHT31(temperature, humidity);
if (sht31Read && !isnan(temperature) && !isnan(humidity)) {
currentData.temperature = temperature;
currentData.humidity = humidity;
sht31Connected = true;
Serial1.print("SHT31: T=");
Serial1.print(temperature, 1);
Serial1.print("C, H=");
Serial1.print(humidity, 1);
Serial1.println("%");
} else {
currentData.temperature = NAN;
currentData.humidity = NAN;
sht31Connected = false;
Serial1.println("SHT31: FAILED");
}
// کالیبراسیون MQ7
if (!calibrationComplete && (millis() - systemStartTime >= calibrationPeriod)) {
calibrateMQ7();
calibrationComplete = true;
}
// خواندن CO
currentData.coPPM = readCOImproved();
int adc = analogRead(MQ7_PIN);
coSensorConnected = (adc > 10 && adc < 4085);
Serial1.print("MQ7: ");
Serial1.print(currentData.coPPM, 1);
Serial1.println(" ppm");
// محاسبه درصدها
calculatePercentages(currentData);
lastSensorRead = millis();
Serial1.println("=== Sensor Readings Complete ===\n");
// اگر SHT31 کار نمی‌کند، سیستم را مسدود نکن
if (!sht31Connected) {
Serial1.println("Warning: SHT31 not responding, continuing anyway...");
}
}
// -------------------- مقداردهی اولیه --------------------
inline void initSensors() {
Serial1.println("Initializing sensors...");
// راه‌اندازی I2C1 برای SHT31 (سرعت پایین)
Wire.setSDA(SHT31_SDA_PIN);
Wire.setSCL(SHT31_SCL_PIN);
Wire.begin();
Wire.setClock(50000); // 50kHz برای پایداری
Wire.setTimeout(100);
// راه‌اندازی I2C2 برای BH1750
Wire1.setSDA(BH1750_SDA_PIN);
Wire1.setSCL(BH1750_SCL_PIN);
Wire1.begin();
Wire1.setClock(50000); // 50kHz
Wire1.setTimeout(100);
// پیکربندی MQ7
pinMode(MQ7_PIN, INPUT);
analogReadResolution(12);
delay(1000);
// اسکن آدرس‌های I2C
Serial1.println("Scanning I2C1 (SHT31)...");
byte error;
int found1 = 0;
for(byte addr = 1; addr < 127; addr++) {
Wire.beginTransmission(addr);
error = Wire.endTransmission();
if (error == 0) {
Serial1.print("Found device at 0x");
if (addr < 16) Serial1.print("0");
Serial1.println(addr, HEX);
found1++;
}
}
Serial1.print("I2C1 devices: ");
Serial1.println(found1);
Serial1.println("Scanning I2C2 (BH1750)...");
int found2 = 0;
for(byte addr = 1; addr < 127; addr++) {
Wire1.beginTransmission(addr);
error = Wire1.endTransmission();
if (error == 0) {
Serial1.print("Found device at 0x");
if (addr < 16) Serial1.print("0");
Serial1.println(addr, HEX);
found2++;
}
}
Serial1.print("I2C2 devices: ");
Serial1.println(found2);
// تست اولیه سریع
Serial1.println("Quick sensor test...");
float lux;
if (readBH1750(lux)) {
lightSensorConnected = true;
Serial1.print("BH1750 OK: ");
Serial1.print(lux);
Serial1.println(" lux");
}
delay(100);
float temp, hum;
if (readSHT31(temp, hum)) {
sht31Connected = true;
Serial1.print("SHT31 OK: ");
Serial1.print(temp);
Serial1.print("C ");
Serial1.print(hum);
Serial1.println("%");
}
Serial1.println("Sensor init done");
}
#endif // SENSORS_H