211 lines
6.1 KiB
C++
211 lines
6.1 KiB
C++
#include <Arduino.h>
|
||
#include <Wire.h>
|
||
#include <BH1750.h>
|
||
#include "DHT.h"
|
||
|
||
// --------------------------- تنظیمات ---------------------------
|
||
#define DHTPIN A0
|
||
#define DHTTYPE DHT22
|
||
DHT dht(DHTPIN, DHTTYPE);
|
||
|
||
#define SOIL_PIN A1
|
||
|
||
#define MQ7_PIN A2
|
||
#define VREF 5.0 // ولتاژ مرجع ADC
|
||
#define ADC_MAX 4095.0 // برای STM32 (۱۲ بیتی)
|
||
|
||
#define SDA_PIN PB9
|
||
#define SCL_PIN PB8
|
||
BH1750 lightMeter;
|
||
|
||
// UART EC200U
|
||
HardwareSerial EC200U(1);
|
||
#define PWRKEY_PIN PB5
|
||
|
||
// ارسال هر n دقیقه
|
||
#define UPLOAD_INTERVAL_MIN 1
|
||
|
||
// ذخیره ساعت شبکه
|
||
String networkTime = "";
|
||
|
||
// --------------------------- توابع ---------------------------
|
||
|
||
// روشن کردن ماژول EC200U
|
||
void powerEC200U() {
|
||
pinMode(PWRKEY_PIN, OUTPUT);
|
||
digitalWrite(PWRKEY_PIN, HIGH);
|
||
delay(1000); // نگه داشتن HIGH حدود 1 ثانیه برای روشن کردن
|
||
digitalWrite(PWRKEY_PIN, LOW);
|
||
delay(2000); // کمی صبر قبل از AT
|
||
}
|
||
|
||
// ارسال دستور AT و نمایش پاسخ
|
||
void sendAT(String cmd, uint16_t wait = 1000) {
|
||
Serial.print(">> "); Serial.println(cmd);
|
||
EC200U.println(cmd);
|
||
unsigned long start = millis();
|
||
while (millis() - start < wait) {
|
||
while (EC200U.available()) Serial.write(EC200U.read());
|
||
}
|
||
Serial.println();
|
||
}
|
||
|
||
// آمادهسازی ماژول و اینترنت
|
||
void initEC200U() {
|
||
Serial.println("🚀 Initializing EC200U...");
|
||
sendAT("AT",1000);
|
||
sendAT("ATI",1000);
|
||
sendAT("AT+CPIN?",1000);
|
||
sendAT("AT+CSQ",1000);
|
||
sendAT("AT+CREG?",1000);
|
||
sendAT("AT+CGATT=1",2000);
|
||
sendAT("AT+CGDCONT=1,\"IP\",\"mcinet\"",1000);
|
||
sendAT("AT+QIACT=1",5000);
|
||
sendAT("AT+QIACT?",2000);
|
||
Serial.println("✅ EC200U Ready");
|
||
}
|
||
|
||
// خواندن ساعت شبکه
|
||
void getNetworkTime() {
|
||
sendAT("AT+QLTS=2", 3000);
|
||
networkTime = "";
|
||
unsigned long t = millis();
|
||
while (millis()-t < 3000) {
|
||
while(EC200U.available()) {
|
||
char c = EC200U.read();
|
||
Serial.write(c);
|
||
networkTime += c;
|
||
}
|
||
}
|
||
}
|
||
|
||
// خواندن سنسورها
|
||
float readDHT22() { return dht.readTemperature(); }
|
||
float readHumidity() { return dht.readHumidity(); }
|
||
|
||
// رطوبت خاک به درصد
|
||
int readSoilPercent() {
|
||
int val = analogRead(SOIL_PIN); // 0-4095
|
||
int perc = map(val, 3000, 1500, 0, 100); // خشک: 3000, خیس:1500 (تنظیم شود)
|
||
if(perc>100) perc=100;
|
||
if(perc<0) perc=0;
|
||
return perc;
|
||
}
|
||
|
||
float readMQ7ppm() {
|
||
// --- 1. میانگینگیری چند قرائت برای پایداری ---
|
||
long sum = 0;
|
||
for (int i = 0; i < 10; i++) {
|
||
sum += analogRead(MQ7_PIN);
|
||
delay(5);
|
||
}
|
||
float adcValue = sum / 10.0;
|
||
|
||
// --- 2. محاسبه ولتاژ خروجی ---
|
||
float voltage = (adcValue / ADC_MAX) * VREF;
|
||
|
||
// --- 3. تبدیل تقریبی به ppm ---
|
||
// منحنی تجربی بر اساس تست ماژولهای MQ7 آماده (ولتاژ به ppm CO)
|
||
// این ضرایب با ولتاژ 0.1V ~ 1V برای ppm=50~5000 کالیبره شدهاند.
|
||
// اگر مقدار خروجی بیش از 4V باشد، سنسور اشباع است.
|
||
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; // 50–140ppm
|
||
else if (voltage < 1.0) ppm = 140 + (voltage - 0.5) * 800; // تا حدود 500ppm
|
||
else if (voltage < 2.0) ppm = 500 + (voltage - 1.0) * 1500; // تا حدود 2000ppm
|
||
else ppm = 2000 + (voltage - 2.0) * 2000; // تا ~4000ppm
|
||
|
||
// --- 4. محدود کردن مقدار ---
|
||
if (ppm < 0) ppm = 0;
|
||
if (ppm > 10000) ppm = 10000;
|
||
|
||
// --- 5. نمایش برای دیباگ ---
|
||
Serial.print("MQ7 voltage: ");
|
||
Serial.print(voltage, 3);
|
||
Serial.print(" V, CO ≈ ");
|
||
Serial.print(ppm, 1);
|
||
Serial.println(" ppm");
|
||
|
||
return ppm;
|
||
}
|
||
|
||
|
||
float readLight() { return lightMeter.readLightLevel(); }
|
||
|
||
// ارسال داده HTTP GET
|
||
void sendData(float temp, float hum, int soilPerc, float mq7ppm, float lux, String timeStr) {
|
||
String dataStr = String(temp,1) + "," + String(hum,1) + "," + String(soilPerc) + "," + String(mq7ppm,0) + "," + String(lux,1) + "," + timeStr;
|
||
// 'http://localhost:5064/api/Telemetry/AddData?deviceName=dr110&temperatureC=24.5&humidityPercent=26.3&soilPercent=12&gasPPM=2&lux=103'
|
||
String url = "http://nabaksoft.ir/api/Telemetry/AddData?deviceName=dr110&temperatureC="+String(temp,1)
|
||
+"&humidityPercent="+String(hum,1)+"&soilPercent="+String(soilPerc)+"&gasPPM="+String(mq7ppm,0)+"&lux="+String(lux,1);
|
||
|
||
Serial.println("🌐 Sending data: " + dataStr);
|
||
|
||
sendAT("AT+QHTTPURL=" + String(url.length()) + ",80", 500);
|
||
delay(500);
|
||
EC200U.print(url);
|
||
delay(1000);
|
||
sendAT("AT+QHTTPGET=80", 5000);
|
||
sendAT("AT+QHTTPREAD=80", 5000);
|
||
}
|
||
|
||
// --------------------------- راهاندازی ---------------------------
|
||
void setup() {
|
||
Serial.begin(115200);
|
||
delay(1000);
|
||
Serial.println("🚀 STM32 + EC200U + Sensors");
|
||
|
||
// روشن کردن ماژول EC200U
|
||
powerEC200U();
|
||
|
||
// UART EC200U
|
||
EC200U.setRx(PA10);
|
||
EC200U.setTx(PA9);
|
||
EC200U.begin(115200);
|
||
delay(1000);
|
||
|
||
// سنسورها
|
||
dht.begin();
|
||
Wire.setSDA(SDA_PIN);
|
||
Wire.setSCL(SCL_PIN);
|
||
Wire.begin();
|
||
if (lightMeter.begin(BH1750::CONTINUOUS_HIGH_RES_MODE)) {
|
||
Serial.println("BH1750 Initialized successfully!");
|
||
} else {
|
||
Serial.println("Error initializing BH1750!");
|
||
}
|
||
|
||
// آماده سازی ماژول و اینترنت
|
||
initEC200U();
|
||
|
||
// خواندن ساعت شبکه
|
||
getNetworkTime();
|
||
}
|
||
|
||
// --------------------------- حلقه اصلی ---------------------------
|
||
unsigned long lastUpload = 0;
|
||
|
||
void loop() {
|
||
unsigned long now = millis();
|
||
if (now - lastUpload > UPLOAD_INTERVAL_MIN*60UL*1000UL || lastUpload==0) {
|
||
// خواندن سنسورها
|
||
float temp = readDHT22();
|
||
float hum = readHumidity();
|
||
int soil = readSoilPercent();
|
||
float mq7 = readMQ7ppm();
|
||
float lux = readLight();
|
||
|
||
// دریافت ساعت شبکه
|
||
getNetworkTime();
|
||
|
||
// ارسال به سرور
|
||
sendData(temp, hum, soil, mq7, lux, networkTime);
|
||
|
||
lastUpload = now;
|
||
}
|
||
|
||
delay(500);
|
||
}
|