This commit is contained in:
2026-01-06 19:06:03 +03:30
parent 66a02f4584
commit abe1a64338
24 changed files with 2799 additions and 6053 deletions

View File

@@ -1,265 +1,196 @@
#include <Arduino.h>
#include <Wire.h>
#include <Adafruit_SHT31.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Fonts/FreeSans9pt7b.h>
#include <Fonts/FreeSansBold12pt7b.h>
#include <Fonts/FreeSansBold18pt7b.h>
#include <Adafruit_SHT31.h>
#include <BH1750.h>
#include <SPI.h>
// تعریف پین‌ها
#define ADC_PIN PA2 // یا A2 اگر تعریف شده
#define LED_PIN PC13
#define OLED_ADDR 0x3C
// -------------------- فایل‌های پروژه --------------------
#include "Config.h"
#include "Memory.h"
#include "Sensors.h"
#include "EC200U.h"
#include "Display.h"
#include "Voltage_Reader.h"
// پین‌های I2C
#define I2C_SDA PB9
#define I2C_SCL PB8
// آبجکت‌ها
Adafruit_SHT31 sht31;
// -------------------- متغیرهای سراسری --------------------
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
BH1750 lightMeter;
Adafruit_SSD1306 display(128, 64, &Wire, -1);
Adafruit_SHT31 sht31;
HardwareSerial EC200U(USART3);
SPIClass flashSPI(FLASH_MOSI, FLASH_MISO, FLASH_SCK);
// متغیرها
float temperature, humidity, light;
int raw_adc = 0;
float voltage = 0;
float co_ppm = 0;
DeviceConfig config;
SensorData currentData;
// تابع دیباگ برای تست ADC
void testADC() {
Serial1.print("ADC Pin: PA2 (Pin ");
Serial1.print(ADC_PIN);
Serial1.println(")");
// خواندن 10 نمونه
Serial1.println("Reading ADC values:");
for (int i = 0; i < 10; i++) {
int val = analogRead(ADC_PIN);
Serial1.print("Sample ");
Serial1.print(i);
Serial1.print(": ");
Serial1.print(val);
Serial1.print(" (");
Serial1.print(val * 3.3 / 4095.0, 3);
Serial1.println("V)");
delay(200);
}
}
// متغیرهای موقت برای پردازش پیامک‌ها
String tempPhoneNumber = "";
String tempTokenCode = "";
bool awaitingSMS2 = false;
// تابع برای بررسی اتصال MQ-7
void checkMQ7Connection() {
Serial1.println("\n=== Testing MQ-7 Connection ===");
// حالت 1: اتصال باز (هوای آزاد)
Serial1.println("1. Disconnect MQ-7 (open circuit):");
delay(3000);
raw_adc = analogRead(ADC_PIN);
voltage = raw_adc * 3.3 / 4095.0;
Serial1.print(" ADC: ");
Serial1.print(raw_adc);
Serial1.print(" -> Voltage: ");
Serial1.print(voltage, 3);
Serial1.println("V");
// حالت 2: اتصال به GND
Serial1.println("2. Short MQ-7 output to GND:");
Serial1.println(" (Connect AOUT to GND temporarily)");
delay(5000);
raw_adc = analogRead(ADC_PIN);
voltage = raw_adc * 3.3 / 4095.0;
Serial1.print(" ADC: ");
Serial1.print(raw_adc);
Serial1.print(" -> Voltage: ");
Serial1.print(voltage, 3);
Serial1.println("V");
// حالت 3: اتصال به 3.3V
Serial1.println("3. Short MQ-7 output to 3.3V:");
Serial1.println(" (Connect AOUT to 3.3V temporarily)");
delay(5000);
raw_adc = analogRead(ADC_PIN);
voltage = raw_adc * 3.3 / 4095.0;
Serial1.print(" ADC: ");
Serial1.print(raw_adc);
Serial1.print(" -> Voltage: ");
Serial1.print(voltage, 3);
Serial1.println("V");
Serial1.println("=== End Test ===");
}
unsigned long lastSensorRead = 0;
unsigned long lastUpload = 0;
unsigned long lastDisplayChange = 0;
unsigned long lastNetworkStatusUpdate = 0;
float readCO() {
// خواندن مستقیم ADC
raw_adc = analogRead(ADC_PIN);
voltage = raw_adc * 3.3 / 4095.0;
// اگر ولتاژ خیلی کم یا زیاد باشد
if (voltage < 0.1) {
return 0.1; // حداقل مقدار
}
if (voltage > 4.9) {
return 1000; // حداکثر مقدار
}
// محاسبه Rs (مقاومت سنسور)
float Rs = 10000.0 * (5.0 - voltage) / voltage;
// فرض R0 ثابت (می‌توانید کالیبره کنید)
float R0 = 10000.0;
float ratio = Rs / R0;
// محاسبه PPM با فرمول MQ-7
float ppm = 99.042 * pow(ratio, -1.518);
// محدود کردن خروجی
if (ppm < 0.5) ppm = 0.5;
if (ppm > 1000) ppm = 1000;
return ppm;
}
bool networkConnected = false;
int displayMode = 0;
String lastError = "";
String currentAPN = "";
String lastMessage = "";
// وضعیت سنسورها و اتصالات
bool sht31Connected = false;
bool lightSensorConnected = false;
bool coSensorConnected = false;
bool simConnected = false;
bool networkRegistered = false;
int signalStrength = 0;
// متغیرهای CO کالیبراسیون
unsigned long systemStartTime = 0;
const long calibrationPeriod = 600000; // 10 دقیقه
bool calibrationComplete = false;
float MQ7_R0 = 10000.0;
bool isInCall = false;
bool powerState = false;
// -------------------- Setup --------------------
void setup() {
Serial1.begin(115200);
Serial1.println("\n=== STM32 4-Sensor Monitor ===");
// تنظیم پین‌ها
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, HIGH); // روشن برای نشان دادن فعالیت
pinMode(PWRKEY_PIN, OUTPUT);
digitalWrite(PWRKEY_PIN, LOW);
pinMode(POWER_PIN, INPUT);
powerState = digitalRead(POWER_PIN) == HIGH;
delay(1000);
// تنظیم ADC
analogReadResolution(12); // برای STM32 مهم است!
Serial1.println("\n\n🚀 IoT Device Starting...");
// تنظیم I2C
Wire.setSDA(I2C_SDA);
Wire.setSCL(I2C_SCL);
systemStartTime = millis();
pinMode(MQ7_PIN, INPUT);
Wire.setSDA(SDA_PIN);
Wire.setSCL(SCL_PIN);
Wire.begin();
// OLED
if (!display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR)) {
Serial1.println("OLED not found!");
while(1);
// 1. ولتاژ را تست کن
bool voltageOK = voltageReader.testCircuit();
if (!voltageOK) {
Serial1.println("⚠️ Voltage issue detected!");
}
// SHT31
if (!sht31.begin(0x44)) {
Serial1.println("SHT31 not found!");
// 2. اطلاعات دیباگ ولتاژ
voltageReader.debugInfo();
// 3. خواندن اولیه ولتاژ
float initialVoltage = voltageReader.readVoltage();
Serial1.print("Initial voltage: ");
Serial1.print(initialVoltage, 2);
Serial1.println("V");
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial1.println("❌ OLED failed!");
}
// BH1750
if (!lightMeter.begin()) {
Serial1.println("BH1750 not found!");
sht31.begin(0x44);
lightMeter.begin(BH1750::CONTINUOUS_HIGH_RES_MODE);
flashInit();
readConfig();
calibrateMQ7();
awaitingSMS2 = false;
tempPhoneNumber = "";
tempTokenCode = "";
EC200U.begin(115200);
initEC200U();
if (config.verified) {
Serial1.println("Device ID: " + String(config.deviceId));
currentAPN = simTypeToAPN(config.simType);
//initEC200U();
} else {
lightMeter.configure(BH1750::CONTINUOUS_HIGH_RES_MODE);
Serial1.println("⚠️ Not configured - Waiting for SMS");
}
// تست اولیه ADC
testADC();
readSensors();
// نمایش صفحه شروع
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(20, 20);
display.println("ADC Test Mode");
display.setCursor(30, 35);
display.println("Check Serial");
display.display();
updateNetworkStatus();
lastNetworkStatusUpdate = millis();
Serial1.println("\nSend 't' to test MQ-7 connection");
Serial1.println("Send 'r' to read normal values");
Serial1.println("✅ Ready - CO calibration: " + String(calibrationComplete ? "Complete" : "In progress"));
if (config.verified && networkConnected) {
Serial1.println("\n🚀 First upload - sending data immediately...");
uploadData();
}
}
// -------------------- Loop --------------------
void loop() {
// بررسی دستورات سریال
if (Serial1.available()) {
char cmd = Serial1.read();
if (!isInCall) {
digitalWrite(PWRKEY_PIN, LOW);
}
bool currentPower = digitalRead(POWER_PIN) == HIGH;
if (currentPower != powerState) {
if (cmd == 't' || cmd == 'T') {
checkMQ7Connection();
powerState = currentPower;
if (powerState) {
Serial.println("5V Connected");
} else {
Serial.println("5V Disconnected");
}
if (cmd == 'r' || cmd == 'R') {
// خواندن حالت عادی
temperature = sht31.readTemperature();
humidity = sht31.readHumidity();
light = lightMeter.readLightLevel();
co_ppm = readCO();
Serial1.print("\nTemp: ");
Serial1.print(temperature, 1);
Serial1.print("C, Hum: ");
Serial1.print(humidity, 1);
Serial1.print("%, Light: ");
Serial1.print(light, 0);
Serial1.print("lx, CO: ");
Serial1.print(co_ppm, 1);
Serial1.print("ppm, ADC: ");
Serial1.print(raw_adc);
Serial1.print(" (");
Serial1.print(voltage, 3);
Serial1.println("V)");
lastUpload -= 86400000L;
}
checkSMS();
if (!calibrationComplete && (millis() - systemStartTime >= calibrationPeriod)) {
calibrationComplete = true;
Serial1.println("✅ CO calibration period completed!");
}
if (millis() - lastSensorRead > SENSOR_READ_INTERVAL) {
readSensors();
float voltage = voltageReader.readVoltage();
Serial1.print("📊 System Voltage: ");
Serial1.print(voltage, 2);
Serial1.println("V");
currentData.volage=voltage;
if(currentPower)
currentData.power=1;
else
currentData.power=0;
unsigned long uploadIntervalMs = config.uploadInterval * 60000UL;
if (millis() - lastUpload > uploadIntervalMs) {
Serial1.print("Upload interval reached (");
Serial1.print(config.uploadInterval);
Serial1.println(" min), starting upload...");
uploadData();
}
}
// خواندن و نمایش معمول
temperature = sht31.readTemperature();
humidity = sht31.readHumidity();
light = lightMeter.readLightLevel();
co_ppm = readCO();
// نمایش روی OLED
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
// عنوان
display.setCursor(40, 0);
display.println("SENSORS");
display.drawLine(0, 10, 128, 10, SSD1306_WHITE);
// دما
display.setCursor(0, 15);
display.print("Temp: ");
display.print(temperature, 1);
display.print("C");
// رطوبت
display.setCursor(0, 25);
display.print("Hum: ");
display.print(humidity, 1);
display.print("%");
// نور
display.setCursor(0, 35);
display.print("Light:");
if (light < 1000) {
display.print(light, 0);
} else {
display.print(light / 1000, 1);
display.print("k");
}
display.print("lx");
// CO با نمایش ولتاژ
display.setCursor(0, 45);
display.print("CO: ");
display.print(co_ppm, 1);
display.print("ppm");
// نمایش ADC و ولتاژ در پایین
display.drawLine(0, 55, 128, 55, SSD1306_WHITE);
display.setCursor(0, 58);
display.print("ADC:");
display.print(raw_adc);
display.print(" V:");
display.print(voltage, 2);
display.print("V");
// چشمک زدن LED برای نشان دادن فعالیت
static unsigned long lastBlink = 0;
if (millis() - lastBlink > 1000) {
digitalWrite(LED_PIN, !digitalRead(LED_PIN));
lastBlink = millis();
}
display.display();
delay(500);
}
updateDisplay();
delay(100);
}