#include #include #include #include "DHT.h" // --------------------------- تنظیمات --------------------------- #define DHTPIN PA0 #define DHTTYPE DHT11 DHT dht(DHTPIN, DHTTYPE); #define SOIL_PIN PA1 #define MQ7_PIN PA2 #define SDA_PIN PB9 #define SCL_PIN PB8 BH1750 lightMeter; #define EC200U_TX PB10 #define EC200U_RX PB11 HardwareSerial EC200U(USART3); #define PWRKEY_PIN PB5 #define UPLOAD_INTERVAL_MIN 0.2 String networkTime = ""; bool sslOK = false; // تابع بهبود یافته برای ارسال AT bool sendAT(String cmd, uint16_t wait = 2000) { Serial1.print(">> "); Serial1.println(cmd); EC200U.println(cmd); String response = ""; unsigned long start = millis(); while (millis() - start < wait) { while (EC200U.available()) { char c = EC200U.read(); response += c; Serial1.write(c); } // اگر پاسخ کامل دریافت شد، خارج شو if (response.indexOf("OK") != -1 || response.indexOf("ERROR") != -1) { break; } } Serial1.println(); // بررسی موفقیت یا خطا if (response.indexOf("OK") != -1) { return true; } else if (response.indexOf("ERROR") != -1 || response.indexOf("FAIL") != -1) { return false; } else { Serial1.println("⚠️ No response11"); return false; } } // تابع برای منتظر ماندن پاسخ خاص bool waitForResponse(String expected, unsigned long timeout = 10000) { unsigned long startTime = millis(); String response = ""; while (millis() - startTime < timeout) { while (EC200U.available()) { char c = EC200U.read(); response += c; Serial1.write(c); if (response.indexOf(expected) != -1) { return true; } if (response.indexOf("ERROR") != -1) { return false; } } } Serial1.println("⏰ Timeout waiting for: " + expected); return false; } void initEC200U() { Serial1.println("🚀1 Starting EC200U..."); // روشن کردن ماژول digitalWrite(PWRKEY_PIN, HIGH); delay(2000); digitalWrite(PWRKEY_PIN, LOW); delay(5000); // افزایش زمان انتظار // بررسی ارتباط if (!sendAT("AT", 3000)) { Serial1.println("❌ EC200U not responding!"); return; } sendAT("ATI", 2000); sendAT("AT+CPIN?", 2000); sendAT("AT+CSQ", 2000); sendAT("AT+CREG?", 2000); sendAT("AT+CGREG?", 2000); // فعال کردن GPRS sendAT("AT+CGATT=1", 5000); sendAT("AT+CGDCONT=1,\"IP\",\"mcinet\"", 2000); // فعال کردن PDP context if (sendAT("AT+QIACT=1", 15000)) { Serial1.println("✅ PDP context activated"); } else { Serial1.println("❌ Failed to activate PDP context"); sendAT("AT+QIACT?", 2000); } // تنظیمات HTTP sendAT("AT+QHTTPCFG=\"contextid\",1", 2000); sendAT("AT+QHTTPCFG=\"requestheader\",1", 2000); sendAT("AT+QHTTPCFG=\"responseheader\",1", 2000); // تنظیمات SSL sendAT("AT+QSSLCFG=\"sslversion\",1,4", 2000); sendAT("AT+QSSLCFG=\"ciphersuite\",1,0XFFFF", 2000); sendAT("AT+QSSLCFG=\"seclevel\",1,0", 2000); sendAT("AT+QSSLCFG=\"ignorelocaltime\",1,1", 2000); Serial1.println("✅ EC200U Initialized"); } void getNetworkTime() { if (sendAT("AT+QLTS=2", 5000)) { networkTime = "Time received"; } else { networkTime = "No time"; } } // --- MQ7 تابع مخصوص ماژول آماده --- float MQ7_ReadPPM() { long sum = 0; for (int i = 0; i < 10; i++) { sum += analogRead(MQ7_PIN); delay(5); } float adcValue = sum / 10.0; float voltage = (adcValue / 4095.0) * 3.3; // اصلاح به 3.3V برای STM32 float ppm; if (voltage < 0.1) ppm = 0; else if (voltage < 0.2) ppm = 10 * (voltage / 0.2); else if (voltage < 0.5) ppm = 50 + (voltage - 0.2) * 300; else if (voltage < 1.0) ppm = 140 + (voltage - 0.5) * 800; else if (voltage < 2.0) ppm = 500 + (voltage - 1.0) * 1500; else ppm = 2000 + (voltage - 2.0) * 2000; if (ppm < 0) ppm = 0; if (ppm > 10000) ppm = 10000; return ppm; } // --- Soil Sensor (تبدیل به درصد) --- int readSoil() { int adcValue = analogRead(SOIL_PIN); const int adcDry = 4095; // خاک کاملاً خشک (12-bit ADC) const int adcWet = 1200; // خاک کاملاً خیس // محاسبه درصد رطوبت float soilPercent = (float)(adcDry - adcValue) / (adcDry - adcWet) * 100.0; // محدود کردن بین 0 تا 100 if (soilPercent > 100.0) soilPercent = 100.0; if (soilPercent < 0.0) soilPercent = 0.0; return (int)soilPercent; } // --- سایر سنسورها --- float readLight() { float lux = lightMeter.readLightLevel(); if (isnan(lux)) return 0; return lux; } float readTemp() { float temp = dht.readTemperature(); if (isnan(temp)) return -999; return temp; } float readHum() { float hum = dht.readHumidity(); if (isnan(hum)) return -999; return hum; } bool sendData(float temp, float hum, int soil, float gas, float lux, String timeStr) { // بررسی مقادیر سنسورها if (temp == -999 || hum == -999) { Serial1.println("❌ DHT Sensor error!"); return false; } String gazStr = String(gas, 0); gazStr.trim(); String dataStr = "temperatureC=" + String(temp, 1) + "&humidityPercent=" + String(hum, 1) + "&soilPercent=" + String(soil) + "&gasPPM=" + gazStr + "&lux=" + String(lux, 1); String url = "https://ghback.nabaksoft.ir/api/Telemetry/AddData?deviceName=dr110&" + dataStr; url.replace(" ", ""); Serial1.println("📤 Sending data to server..."); Serial1.println("URL: " + url); Serial1.println("Length: " + String(url.length())); // تنظیمات SSL برای HTTPS Serial1.println("🔒 Configuring SSL..."); if (!sendAT("AT+QHTTPCFG=\"sslctxid\",1", 2000)) { Serial1.println("❌ SSL configuration failed"); return false; } // تنظیم URL String urlCmd = "AT+QHTTPURL=" + String(url.length()) + ",443"; Serial1.println(">> " + urlCmd); EC200U.println(urlCmd); // منتظر CONNECT if (waitForResponse("CONNECT", 10000)) { Serial1.println("✅ CONNECT received, sending URL..."); // ارسال URL EC200U.print(url); // منتظر OK if (waitForResponse("OK", 5000)) { Serial1.println("✅ URL set successfully"); } else { Serial1.println("❌ Failed to set URL"); return false; } } else { Serial1.println("❌ CONNECT timeout"); return false; } // اجرای درخواست GET Serial1.println("🚀 Sending GET request..."); EC200U.println("AT+QHTTPGET=120"); if (waitForResponse("+QHTTPGET:", 30000)) { Serial1.println("✅ GET request sent"); // بررسی کد پاسخ String response = ""; unsigned long start = millis(); while (millis() - start < 5000) { while (EC200U.available()) { char c = EC200U.read(); response += c; Serial1.write(c); } if (response.indexOf("OK") != -1 || response.indexOf("ERROR") != -1) { break; } } // خواندن پاسخ سرور Serial1.println("📖 Reading server response..."); EC200U.println("AT+QHTTPREAD=80"); if (waitForResponse("+QHTTPREAD:", 15000)) { Serial1.println("✅ Response received"); // خواندن داده‌های پاسخ String serverResponse = ""; start = millis(); while (millis() - start < 10000) { while (EC200U.available()) { char c = EC200U.read(); serverResponse += c; Serial1.write(c); } if (serverResponse.indexOf("OK") != -1 || serverResponse.indexOf("ERROR") != -1) { break; } } Serial1.println("✅ Data sent successfully"); return true; } else { Serial1.println("❌ Failed to read response"); return false; } } else { Serial1.println("❌ GET request failed"); return false; } } // --------------------------- setup --------------------------- void setup() { pinMode(PWRKEY_PIN, OUTPUT); digitalWrite(PWRKEY_PIN, LOW); Serial1.begin(115200); EC200U.begin(115200); delay(3000); Serial1.println("🚀 System Starting..."); // مقداردهی سنسورها dht.begin(); Wire.setSDA(SDA_PIN); Wire.setSCL(SCL_PIN); Wire.begin(); if (lightMeter.begin(BH1750::CONTINUOUS_HIGH_RES_MODE)) { Serial1.println("✅ BH1750 OK"); } else { Serial1.println("❌ BH1750 Error"); } // مقداردهی پین‌های آنالوگ pinMode(SOIL_PIN, INPUT); pinMode(MQ7_PIN, INPUT); initEC200U(); getNetworkTime(); Serial1.println("✅ System Ready"); } // --------------------------- loop --------------------------- unsigned long lastUpload = 0; void loop() { if (millis() - lastUpload > UPLOAD_INTERVAL_MIN * 60UL * 1000UL || lastUpload == 0) { Serial1.println("=========================================="); // خواندن سنسورها float temp = readTemp(); float hum = readHum(); int soil = readSoil(); float gas = MQ7_ReadPPM(); float lux = readLight(); // نمایش مقادیر Serial1.println("📊 Sensor Readings:"); Serial1.println("Temperature: " + String(temp, 1) + "°C"); Serial1.println("Humidity: " + String(hum, 1) + "%"); Serial1.println("Soil: " + String(soil) + "%"); Serial1.println("Gas: " + String(gas, 0) + " ppm"); Serial1.println("Light: " + String(lux, 1) + " lux"); Serial1.println("------------------------------------------"); // ارسال داده if (sendData(temp, hum, soil, gas, lux, networkTime)) { Serial1.println("🎉 Data upload successful!"); } else { Serial1.println("❌ Data upload failed!"); } lastUpload = millis(); Serial1.println("=========================================="); } delay(1000); }