backup 14041130
This commit is contained in:
433
14041130/I2C-best/I2C-best.ino
Normal file
433
14041130/I2C-best/I2C-best.ino
Normal file
@@ -0,0 +1,433 @@
|
||||
#include <Wire.h>
|
||||
|
||||
// تعریف پینهای I2C
|
||||
#define I2C_SDA PB9
|
||||
#define I2C_SCL PB8
|
||||
|
||||
// آدرس سنسورها
|
||||
#define BH1750_ADDR 0x23
|
||||
#define SHT31_ADDR 0x44
|
||||
|
||||
// حالتهای اندازهگیری BH1750
|
||||
#define BH1750_CONTINUOUS_HIGH_RES_MODE 0x10
|
||||
#define BH1750_ONE_TIME_HIGH_RES_MODE 0x20
|
||||
|
||||
// دستورات SHT31
|
||||
#define SHT31_MEAS_HIGHREP 0x2400
|
||||
#define SHT31_MEAS_MEDREP 0x240B
|
||||
#define SHT31_MEAS_LOWREP 0x2416
|
||||
#define SHT31_SOFTRESET 0x30A2
|
||||
#define SHT31_HEATER_ENABLE 0x306D
|
||||
#define SHT31_HEATER_DISABLE 0x3066
|
||||
#define SHT31_STATUS_REG 0xF32D
|
||||
#define SHT31_CLEAR_STATUS 0x3041
|
||||
|
||||
// متغیرهای ذخیرهسازی مقادیر
|
||||
float lastLightLevel = 0.0;
|
||||
float lastTemperature = 0.0;
|
||||
float lastHumidity = 0.0;
|
||||
|
||||
// متغیرهای تشخیص خطا
|
||||
bool bh1750Available = false;
|
||||
bool sht31Available = false;
|
||||
uint8_t bh1750ErrorCount = 0;
|
||||
uint8_t sht31ErrorCount = 0;
|
||||
const uint8_t MAX_ERRORS = 5;
|
||||
|
||||
// زمان آخرین اندازهگیری موفق
|
||||
unsigned long lastBh1750Success = 0;
|
||||
unsigned long lastSht31Success = 0;
|
||||
|
||||
// تابع بازیابی نرم I2C (بدون ریست سختافزاری)
|
||||
void recoverI2C() {
|
||||
Serial1.println("Attempting I2C recovery...");
|
||||
|
||||
// آزاد کردن خطوط
|
||||
pinMode(I2C_SDA, INPUT_PULLUP);
|
||||
pinMode(I2C_SCL, INPUT_PULLUP);
|
||||
delay(1000);
|
||||
|
||||
// تولید پالسهای ساعت برای آزادسازی هر دستگاه قفل شده
|
||||
pinMode(I2C_SCL, OUTPUT);
|
||||
for (int i = 0; i < 9; i++) {
|
||||
digitalWrite(I2C_SCL, LOW);
|
||||
delayMicroseconds(5);
|
||||
digitalWrite(I2C_SCL, HIGH);
|
||||
delayMicroseconds(5);
|
||||
}
|
||||
|
||||
// ایجاد شرط STOP
|
||||
pinMode(I2C_SDA, OUTPUT);
|
||||
digitalWrite(I2C_SDA, LOW);
|
||||
delayMicroseconds(5);
|
||||
digitalWrite(I2C_SCL, HIGH);
|
||||
delayMicroseconds(5);
|
||||
digitalWrite(I2C_SDA, HIGH);
|
||||
delayMicroseconds(5);
|
||||
|
||||
// بازگشت به حالت عادی
|
||||
Wire.begin();
|
||||
|
||||
Serial1.println("I2C recovery completed");
|
||||
}
|
||||
|
||||
// تابع بررسی وجود دستگاه روی باس I2C
|
||||
bool checkDevice(uint8_t address) {
|
||||
Wire.beginTransmission(address);
|
||||
byte error = Wire.endTransmission();
|
||||
return (error == 0);
|
||||
}
|
||||
|
||||
bool initBH1750() {
|
||||
if (!checkDevice(BH1750_ADDR)) {
|
||||
Serial1.println("BH1750 not found!");
|
||||
bh1750Available = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
bh1750Available = true;
|
||||
bh1750ErrorCount = 0;
|
||||
Serial1.println("BH1750 ready (One-Time mode)");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool readBH1750(float &lightLevel) {
|
||||
|
||||
if (!bh1750Available && bh1750ErrorCount < MAX_ERRORS) {
|
||||
if (!initBH1750()) return false;
|
||||
}
|
||||
|
||||
if (!bh1750Available) return false;
|
||||
|
||||
// ارسال فرمان One-Time High Resolution
|
||||
Wire.beginTransmission(BH1750_ADDR);
|
||||
Wire.write(BH1750_ONE_TIME_HIGH_RES_MODE);
|
||||
byte error = Wire.endTransmission();
|
||||
|
||||
if (error != 0) {
|
||||
bh1750ErrorCount++;
|
||||
Serial1.println("BH1750 command error");
|
||||
return false;
|
||||
}
|
||||
|
||||
// زمان تبدیل (حداکثر 180ms طبق دیتاشیت)
|
||||
delay(180);
|
||||
|
||||
// درخواست 2 بایت داده
|
||||
Wire.requestFrom(BH1750_ADDR, 2);
|
||||
|
||||
if (Wire.available() == 2) {
|
||||
uint16_t value = Wire.read();
|
||||
value <<= 8;
|
||||
value |= Wire.read();
|
||||
|
||||
lightLevel = value / 1.2;
|
||||
|
||||
if (lightLevel >= 0 && lightLevel <= 65535) {
|
||||
lastLightLevel = lightLevel;
|
||||
bh1750ErrorCount = 0;
|
||||
lastBh1750Success = millis();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// در صورت خطا
|
||||
bh1750ErrorCount++;
|
||||
Serial1.println("Error reading BH1750");
|
||||
|
||||
if (bh1750ErrorCount >= MAX_ERRORS) {
|
||||
bh1750Available = false;
|
||||
Serial1.println("BH1750 marked as unavailable");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// تابع مقداردهی اولیه BH1750
|
||||
bool __initBH1750() {
|
||||
if (!checkDevice(BH1750_ADDR)) {
|
||||
Serial1.println("BH1750 not found!");
|
||||
bh1750Available = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
// ارسال دستور اندازهگیری پیوسته
|
||||
Wire.beginTransmission(BH1750_ADDR);
|
||||
Wire.write(BH1750_CONTINUOUS_HIGH_RES_MODE);
|
||||
byte error = Wire.endTransmission();
|
||||
|
||||
if (error == 0) {
|
||||
bh1750Available = true;
|
||||
bh1750ErrorCount = 0;
|
||||
Serial1.println("BH1750 initialized successfully");
|
||||
return true;
|
||||
} else {
|
||||
bh1750Available = false;
|
||||
Serial1.print("BH1750 init error: ");
|
||||
Serial1.println(error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// تابع خواندن نور از BH1750
|
||||
bool __readBH1750(float &lightLevel) {
|
||||
if (!bh1750Available && bh1750ErrorCount < MAX_ERRORS) {
|
||||
if (initBH1750()) {
|
||||
delay(180); // تأخیر برای اولین اندازهگیری
|
||||
}
|
||||
}
|
||||
|
||||
if (!bh1750Available) return false;
|
||||
|
||||
// درخواست 2 بایت داده
|
||||
Wire.requestFrom(BH1750_ADDR, 2);
|
||||
|
||||
if (Wire.available() == 2) {
|
||||
uint16_t value = Wire.read();
|
||||
value <<= 8;
|
||||
value |= Wire.read();
|
||||
|
||||
lightLevel = value / 1.2; // محاسبه لوکس
|
||||
|
||||
// اعتبارسنجی مقدار
|
||||
if (lightLevel >= 0 && lightLevel <= 65535) {
|
||||
lastLightLevel = lightLevel;
|
||||
bh1750ErrorCount = 0;
|
||||
lastBh1750Success = millis();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// در صورت خطا
|
||||
bh1750ErrorCount++;
|
||||
Serial1.println("Error reading BH1750");
|
||||
|
||||
if (bh1750ErrorCount >= MAX_ERRORS) {
|
||||
bh1750Available = false;
|
||||
Serial1.println("BH1750 marked as unavailable");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// تابع مقداردهی اولیه SHT31
|
||||
bool initSHT31() {
|
||||
if (!checkDevice(SHT31_ADDR)) {
|
||||
Serial1.println("SHT31 not found!");
|
||||
sht31Available = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
// ارسال دستور ریست نرم
|
||||
Wire.beginTransmission(SHT31_ADDR);
|
||||
Wire.write(SHT31_SOFTRESET >> 8);
|
||||
Wire.write(SHT31_SOFTRESET & 0xFF);
|
||||
byte error = Wire.endTransmission();
|
||||
|
||||
if (error != 0) {
|
||||
sht31Available = false;
|
||||
Serial1.print("SHT31 reset error: ");
|
||||
Serial1.println(error);
|
||||
return false;
|
||||
}
|
||||
|
||||
delay(10); // تأخیر بعد از ریست
|
||||
|
||||
// غیرفعال کردن هیتر (برای مصرف کمتر و عمر طولانیتر)
|
||||
Wire.beginTransmission(SHT31_ADDR);
|
||||
Wire.write(SHT31_HEATER_DISABLE >> 8);
|
||||
Wire.write(SHT31_HEATER_DISABLE & 0xFF);
|
||||
error = Wire.endTransmission();
|
||||
|
||||
if (error == 0) {
|
||||
sht31Available = true;
|
||||
sht31ErrorCount = 0;
|
||||
Serial1.println("SHT31 initialized successfully");
|
||||
return true;
|
||||
} else {
|
||||
sht31Available = false;
|
||||
Serial1.print("SHT31 init error: ");
|
||||
Serial1.println(error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// تابع خواندن دما و رطوبت از SHT31
|
||||
bool readSHT31(float &temperature, float &humidity) {
|
||||
if (!sht31Available && sht31ErrorCount < MAX_ERRORS) {
|
||||
initSHT31();
|
||||
}
|
||||
|
||||
if (!sht31Available) return false;
|
||||
|
||||
// ارسال دستور اندازهگیری با دقت بالا
|
||||
Wire.beginTransmission(SHT31_ADDR);
|
||||
Wire.write(SHT31_MEAS_HIGHREP >> 8);
|
||||
Wire.write(SHT31_MEAS_HIGHREP & 0xFF);
|
||||
byte error = Wire.endTransmission();
|
||||
|
||||
if (error != 0) {
|
||||
sht31ErrorCount++;
|
||||
Serial1.println("Error sending measurement command to SHT31");
|
||||
return false;
|
||||
}
|
||||
|
||||
// تأخیر برای تبدیل (حداکثر 15ms برای حالت High Rep)
|
||||
delay(15);
|
||||
|
||||
// خواندن 6 بایت داده
|
||||
Wire.requestFrom(SHT31_ADDR, 6);
|
||||
|
||||
if (Wire.available() == 6) {
|
||||
uint16_t tempRaw = Wire.read();
|
||||
tempRaw <<= 8;
|
||||
tempRaw |= Wire.read();
|
||||
uint8_t tempCRC = Wire.read();
|
||||
|
||||
uint16_t humRaw = Wire.read();
|
||||
humRaw <<= 8;
|
||||
humRaw |= Wire.read();
|
||||
uint8_t humCRC = Wire.read();
|
||||
|
||||
// تبدیل مقادیر
|
||||
temperature = -45 + (175 * (float)tempRaw / 65535.0);
|
||||
humidity = 100 * (float)humRaw / 65535.0;
|
||||
|
||||
// اعتبارسنجی مقادیر
|
||||
if (temperature >= -40 && temperature <= 125 &&
|
||||
humidity >= 0 && humidity <= 100) {
|
||||
lastTemperature = temperature;
|
||||
lastHumidity = humidity;
|
||||
sht31ErrorCount = 0;
|
||||
lastSht31Success = millis();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// در صورت خطا
|
||||
sht31ErrorCount++;
|
||||
Serial1.println("Error reading SHT31");
|
||||
|
||||
if (sht31ErrorCount >= MAX_ERRORS) {
|
||||
sht31Available = false;
|
||||
Serial1.println("SHT31 marked as unavailable");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// تابع بررسی دورهای سلامت باس I2C
|
||||
void checkI2CHealth() {
|
||||
static unsigned long lastCheck = 0;
|
||||
unsigned long currentMillis = millis();
|
||||
|
||||
// هر 30 ثانیه بررسی کن
|
||||
if (currentMillis - lastCheck >= 30000) {
|
||||
lastCheck = currentMillis;
|
||||
|
||||
bool bh1750WasAvailable = bh1750Available;
|
||||
bool sht31WasAvailable = sht31Available;
|
||||
|
||||
// بررسی BH1750
|
||||
if (checkDevice(BH1750_ADDR)) {
|
||||
if (!bh1750WasAvailable) {
|
||||
Serial1.println("BH1750 reappeared, reinitializing...");
|
||||
initBH1750();
|
||||
}
|
||||
} else if (bh1750WasAvailable) {
|
||||
Serial1.println("BH1750 disappeared!");
|
||||
bh1750Available = false;
|
||||
}
|
||||
|
||||
// بررسی SHT31
|
||||
if (checkDevice(SHT31_ADDR)) {
|
||||
if (!sht31WasAvailable) {
|
||||
Serial1.println("SHT31 reappeared, reinitializing...");
|
||||
initSHT31();
|
||||
}
|
||||
} else if (sht31WasAvailable) {
|
||||
Serial1.println("SHT31 disappeared!");
|
||||
sht31Available = false;
|
||||
}
|
||||
|
||||
// اگر هر دو دستگاه از دست رفتهاند، بازیابی باس I2C
|
||||
if (!bh1750Available && !sht31Available) {
|
||||
recoverI2C();
|
||||
|
||||
// تلاش مجدد برای مقداردهی اولیه
|
||||
delay(100);
|
||||
initBH1750();
|
||||
initSHT31();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void setup() {
|
||||
Serial1.begin(115200);
|
||||
Serial1.println("Starting STM32 with BH1750 and SHT31...");
|
||||
|
||||
// مقداردهی اولیه I2C
|
||||
Wire.setSDA(I2C_SDA);
|
||||
Wire.setSCL(I2C_SCL);
|
||||
Wire.begin();
|
||||
Wire.setClock(100000); // 100kHz برای پایداری بهتر
|
||||
|
||||
// افزایش timeout برای جلوگیری از hang شدن
|
||||
Wire.setTimeout(1000);
|
||||
|
||||
delay(1000); // تأخیر برای پایدار شدن
|
||||
|
||||
// مقداردهی اولیه سنسورها
|
||||
initBH1750();
|
||||
initSHT31();
|
||||
|
||||
Serial1.println("Setup completed");
|
||||
}
|
||||
|
||||
void loop() {
|
||||
static unsigned long lastRead = 0;
|
||||
unsigned long currentMillis = millis();
|
||||
|
||||
// خواندن هر 2 ثانیه
|
||||
if (currentMillis - lastRead >= 2000) {
|
||||
lastRead = currentMillis;
|
||||
|
||||
// خواندن BH1750
|
||||
float light;
|
||||
if (readBH1750(light)) {
|
||||
Serial1.print("Light: ");
|
||||
Serial1.print(light);
|
||||
Serial1.println(" lux");
|
||||
} else {
|
||||
Serial1.print("Using last BH1750 value: ");
|
||||
Serial1.print(lastLightLevel);
|
||||
Serial1.println(" lux");
|
||||
}
|
||||
delay(500);
|
||||
// خواندن SHT31
|
||||
float temp, hum;
|
||||
if (readSHT31(temp, hum)) {
|
||||
Serial1.print("Temperature: ");
|
||||
Serial1.print(temp);
|
||||
Serial1.print(" °C, Humidity: ");
|
||||
Serial1.print(hum);
|
||||
Serial1.println(" %");
|
||||
} else {
|
||||
Serial1.print("Using last SHT31 values - Temp: ");
|
||||
Serial1.print(lastTemperature);
|
||||
Serial1.print(" °C, Hum: ");
|
||||
Serial1.print(lastHumidity);
|
||||
Serial1.println(" %");
|
||||
}
|
||||
|
||||
Serial1.println("---");
|
||||
}
|
||||
|
||||
// بررسی سلامت دورهای
|
||||
checkI2CHealth();
|
||||
|
||||
// تأخیر کوتاه برای جلوگیری از overload
|
||||
delay(10);
|
||||
}
|
||||
Reference in New Issue
Block a user