#include <EEPROM.h>
#include <TimerOne.h>
#include <LiquidCrystal_I2C.h>
// LCD I2C
LiquidCrystal_I2C lcd(0x27, 16, 2);
// --- تنظیمات ---
#define NUM_SENSORS 3
#define NUM_REMOTE_KEYS 4
// --- پینها ---
const int sensorPins[NUM_SENSORS] = {2, 3, 4};
const int remotePins[NUM_REMOTE_KEYS] = {6, 7, 8, 9};
const int buzzerPin = 5;
const int ledArmedPin = 10;
const int ledDisarmedPin = 11;
const int ledSilentPin = 12;
const int ledSensorPins[NUM_SENSORS] = {A0, A1, A2};
// --- باتری ---
const int batteryRelayPin = A5;
const int batteryAnalogPin = A3;
const float batteryStartCharge = 12.4;
const float batteryStopCharge = 12.6;
const float batteryDividerRatio = 2.6;
// EEPROM
#define EEPROM_ADDR_ARMED 0
#define EEPROM_ADDR_SILENT 1
// وضعیت سیستم
bool systemArmed = false;
bool silentMode = false;
bool buzzerActive = false;
bool sensorTriggered = false;
bool sensorLatched[NUM_SENSORS] = {false};
bool remoteLock[NUM_REMOTE_KEYS] = {false};
bool isCharging = false;
unsigned long lastMotionTime = 0;
const unsigned long alarmDuration = 20000;
// کنترل LCD
unsigned long lcdActiveUntil = 0;
bool lcdIsOn = true;
bool alarmStoppedByRemote = false;
bool alarmStoppedAuto = false;
int lastTriggeredSensor = -1;
// بوق
volatile bool beepRequested = false;
volatile int beepCount = 0;
// باتری
volatile bool batteryCheckFlag = false;
volatile unsigned int batteryCheckCounter = 0;
// --- توابع LCD ---
void lcdBacklightControl() {
if (millis() > lcdActiveUntil && lcdIsOn) {
lcd.noBacklight();
lcdIsOn = false;
}
}
void showOnLCD(String line1, String line2) {
lcd.clear();
lcd.setCursor(0, 0); lcd.print(line1);
lcd.setCursor(0, 1); lcd.print(line2);
lcd.backlight();
lcdIsOn = true;
lcdActiveUntil = millis() + 20000;
}
// --- EEPROM ---
void saveSystemState() {
EEPROM.write(EEPROM_ADDR_ARMED, systemArmed);
EEPROM.write(EEPROM_ADDR_SILENT, silentMode);
}
void loadSystemState() {
systemArmed = EEPROM.read(EEPROM_ADDR_ARMED);
silentMode = EEPROM.read(EEPROM_ADDR_SILENT);
Serial.println(systemArmed ? (silentMode ? "✅ Silent ARMED" : "✅ ARMED") : "❌ DISARMED");
}
// --- تایمر ---
void requestBeep(int times) {
if (!beepRequested) {
beepCount = times * 2;
beepRequested = true;
}
}
void timerISR() {
static bool buzzerState = false;
static int intervalCounter = 0;
if (beepRequested && beepCount > 0) {
if (intervalCounter == 0) {
buzzerState = !buzzerState;
digitalWrite(buzzerPin, buzzerState);
if (!buzzerState && --beepCount == 0)
beepRequested = false;
intervalCounter = 2;
} else intervalCounter--;
}
batteryCheckCounter++;
if (batteryCheckCounter >= 40) {
batteryCheckCounter = 0;
batteryCheckFlag = true;
}
}
// --- آژیر ---
void activateAlarm() {
if (!silentMode) {
buzzerActive = true;
digitalWrite(buzzerPin, HIGH);
}
}
// --- وضعیت LED ---
void updateStatusLEDs() {
digitalWrite(ledArmedPin, systemArmed && !silentMode);
digitalWrite(ledSilentPin, systemArmed && silentMode);
digitalWrite(ledDisarmedPin, !systemArmed);
for (int i = 0; i < NUM_SENSORS; i++)
digitalWrite(ledSensorPins[i], sensorLatched[i]);
}
void resetSensorLEDs() {
for (int i = 0; i < NUM_SENSORS; i++) {
sensorLatched[i] = false;
digitalWrite(ledSensorPins[i], LOW);
}
}
// --- باتری ---
void checkBattery() {
int rawBattery = analogRead(batteryAnalogPin);
float voltageBattery = (rawBattery * 5.0 / 1023.0) * batteryDividerRatio;
if (!isCharging && voltageBattery < batteryStartCharge) {
digitalWrite(batteryRelayPin, HIGH);
isCharging = true;
Serial.println("🔋 Charging started");
}
else if (isCharging && voltageBattery >= batteryStopCharge) {
digitalWrite(batteryRelayPin, LOW);
isCharging = false;
Serial.println("✅ Charging stopped");
}
}
void showBatteryPercentage() {
int rawBattery = analogRead(batteryAnalogPin);
float voltageBattery = (rawBattery * 5.0 / 1023.0) * batteryDividerRatio;
float percentage = ((voltageBattery - 11.0) / (12.6 - 11.0)) * 100.0;
if (percentage > 100) percentage = 100;
if (percentage < 0) percentage = 0;
Serial.print("🔋 Battery: ");
Serial.print(percentage, 1);
Serial.println(" %");
String status = (systemArmed ? (silentMode ? "ARMED-SILENT" : "ARMED") : "DISARMED");
String line1 = "Stat:" + status;
String line2 = "Bat:" + String((int)percentage) + "% " + (isCharging ? "Chg" : "OK");
showOnLCD(line1, line2);
}
// --- ریموت ---
void handleRemoteCommand(int key) {
lcdActiveUntil = millis() + 20000;
switch (key) {
case 0:
systemArmed = true; silentMode = false; sensorTriggered = false;
resetSensorLEDs(); saveSystemState(); requestBeep(1);
Serial.println("✅ Armed (normal)");
showOnLCD("System ARMED", "Normal Mode");
break;
case 1:
systemArmed = false; silentMode = false;
buzzerActive = false; sensorTriggered = false;
digitalWrite(buzzerPin, LOW);
saveSystemState(); requestBeep(1);
Serial.println("❌ Disarmed");
showOnLCD("Alarm stopped", "(remote)");
alarmStoppedByRemote = true;
break;
case 2:
systemArmed = true; silentMode = true; sensorTriggered = false;
resetSensorLEDs(); saveSystemState(); requestBeep(1);
Serial.println("🔇 Armed (silent)");
showOnLCD("System ARMED", "Silent Mode");
break;
case 3:
if (buzzerActive) {
buzzerActive = false;
digitalWrite(buzzerPin, LOW);
requestBeep(1);
Serial.println("🛑 Alarm stopped");
showOnLCD("Alarm stopped", "(remote)");
alarmStoppedByRemote = true;
}
break;
}
updateStatusLEDs();
}
// --- setup ---
void setup() {
Serial.begin(9600);
Serial.println("🛡️ System started");
lcd.init();
lcd.backlight();
showOnLCD("System Loading...", "");
delay(1000);
for (int i = 0; i < NUM_SENSORS; i++) {
pinMode(sensorPins[i], INPUT);
pinMode(ledSensorPins[i], OUTPUT);
}
for (int i = 0; i < NUM_REMOTE_KEYS; i++) pinMode(remotePins[i], INPUT);
pinMode(buzzerPin, OUTPUT);
pinMode(ledArmedPin, OUTPUT);
pinMode(ledDisarmedPin, OUTPUT);
pinMode(ledSilentPin, OUTPUT);
pinMode(batteryRelayPin, OUTPUT);
digitalWrite(batteryRelayPin, LOW);
Timer1.initialize(100000);
Timer1.attachInterrupt(timerISR);
loadSystemState();
updateStatusLEDs();
showBatteryPercentage();
}
// --- loop ---
void loop() {
for (int i = 0; i < NUM_REMOTE_KEYS; i++) {
if (digitalRead(remotePins[i]) == HIGH && !remoteLock[i]) {
handleRemoteCommand(i);
remoteLock[i] = true;
} else if (digitalRead(remotePins[i]) == LOW) {
remoteLock[i] = false;
}
}
if (systemArmed) {
for (int i = 0; i < NUM_SENSORS; i++) {
if (digitalRead(sensorPins[i]) == HIGH) {
sensorTriggered = true;
lastMotionTime = millis();
activateAlarm();
if (!sensorLatched[i]) {
sensorLatched[i] = true;
lastTriggeredSensor = i;
Serial.print("🚨 Triggered sensor ");
Serial.println(i + 1);
updateStatusLEDs();
showOnLCD("ALARM TRIGGERED", "Sensor #" + String(i + 1));
}
}
}
}
if (buzzerActive && millis() - lastMotionTime > alarmDuration) {
buzzerActive = false;
digitalWrite(buzzerPin, LOW);
Serial.println("🔕 Auto alarm off");
showOnLCD("Alarm auto", "stopped");
alarmStoppedAuto = true;
}
if ((alarmStoppedByRemote || alarmStoppedAuto) && millis() - lastMotionTime > 3000) {
alarmStoppedByRemote = false;
alarmStoppedAuto = false;
showBatteryPercentage();
}
checkBattery();
if (batteryCheckFlag) {
batteryCheckFlag = false;
showBatteryPercentage();
}
lcdBacklightControl();
}