#include <TimerOne.h>
#include <MsTimer2.h>
#include <TM1637Display.h>
// --- پینها ---
const int mosfetChargePin = 3;
const int mosfetDischargePin = 4;
const int mosfetOutputSwitchPin = 5;
const int adapterStatusPin = 8;
const int ledAdapterPin = 7;
const int batteryVoltagePin = A0;
// --- نمایشگر TM1637 ---
#define DISPLAY_CLK 6
#define DISPLAY_DIO 9
TM1637Display display(DISPLAY_CLK, DISPLAY_DIO);
// --- تقسیم ولتاژ ---
const float voltageDividerRatio = 3.0;
// --- هیسترزیس ---
const float chargeOnVoltage = 13.6;
const float chargeOffVoltage = 13.8;
const float dischargeOnVoltage = 11.9;
const float dischargeOffVoltage = 11.8;
// --- متغیرها ---
volatile bool checkBatteryNow = false;
volatile bool updateDisplayNow = false;
bool isCharging = false;
bool isDischarging = true;
volatile bool adapterConnected = false;
volatile bool adapterChanged = false;
float latestBatteryVoltage = 0.0;
float lastPrintedVoltage = 0.0;
bool lastChargingState = false;
bool lastDischargingState = true;
bool lastOutputState = false;
void setup() {
pinMode(mosfetChargePin, OUTPUT);
pinMode(mosfetDischargePin, OUTPUT);
pinMode(mosfetOutputSwitchPin, OUTPUT);
pinMode(adapterStatusPin, INPUT);
pinMode(ledAdapterPin, OUTPUT);
digitalWrite(mosfetChargePin, LOW);
digitalWrite(mosfetDischargePin, LOW);
digitalWrite(mosfetOutputSwitchPin, LOW);
digitalWrite(ledAdapterPin, LOW);
Serial.begin(9600);
display.setBrightness(1); // روشنایی 0 تا 7
// تایمر بررسی باتری و نمایشگر (هر 1ms)
Timer1.initialize(1000); // 1ms = 1,000 میکروثانیه
Timer1.attachInterrupt(timerISR);
// تایمر نظارت آداپتور (1ms)
MsTimer2::set(1, timerAdapterCheckISR);
MsTimer2::start();
}
void loop() {
// تغییر وضعیت آداپتور
if (adapterChanged) {
adapterChanged = false;
digitalWrite(mosfetOutputSwitchPin, adapterConnected ? HIGH : LOW);
digitalWrite(ledAdapterPin, adapterConnected ? LOW : HIGH);
}
// بررسی ولتاژ باتری
if (checkBatteryNow) {
checkBatteryNow = false;
float batteryVoltage = readBatteryVoltage();
latestBatteryVoltage = batteryVoltage;
// کنترل شارژ
if (batteryVoltage < chargeOnVoltage) {
isCharging = true;
} else if (batteryVoltage > chargeOffVoltage) {
isCharging = false;
}
digitalWrite(mosfetChargePin, isCharging ? HIGH : LOW);
// کنترل دشارژ
if (batteryVoltage > dischargeOnVoltage) {
isDischarging = true;
} else if (batteryVoltage < dischargeOffVoltage) {
isDischarging = false;
}
digitalWrite(mosfetDischargePin, isDischarging ? HIGH : LOW);
bool currentOutputState = digitalRead(mosfetOutputSwitchPin);
// فقط اگر وضعیت تغییر کرده چاپ کن
if (fabs(batteryVoltage - lastPrintedVoltage) > 0.05 ||
isCharging != lastChargingState ||
isDischarging != lastDischargingState ||
currentOutputState != lastOutputState) {
Serial.print("Battery Voltage: ");
Serial.print(batteryVoltage, 2);
Serial.print(" V | Power: ");
Serial.print(isDischarging ? "ON" : "OFF");
Serial.print(" | Charging: ");
Serial.print(isCharging ? "ON" : "OFF");
Serial.print(" | Output: ");
Serial.println(currentOutputState ? "ON" : "OFF");
lastPrintedVoltage = batteryVoltage;
lastChargingState = isCharging;
lastDischargingState = isDischarging;
lastOutputState = currentOutputState;
}
}
// نمایش درصد باتری روی سون سگمنت
if (updateDisplayNow) {
updateDisplayNow = false;
float voltage = latestBatteryVoltage;
int batteryPercent = (int)(((voltage - 11.8) / (13.8 - 11.8)) * 100.0);
batteryPercent = constrain(batteryPercent, 0, 100);
uint8_t digits[4] = {0x00, 0x00, 0x00, 0x00}; // تمام سگمنتها خاموش
if (batteryPercent < 1) {
// فقط رقم اول "0" روشن باشد
digits[0] = display.encodeDigit(0);
} else if (batteryPercent < 10) {
digits[0] = display.encodeDigit(batteryPercent);
// بقیه خاموش
} else if (batteryPercent < 100) {
digits[0] = display.encodeDigit((batteryPercent / 10) % 10); // دهگان
digits[1] = display.encodeDigit(batteryPercent % 10); // یکان
// دو رقم بعدی خاموش
} else {
digits[0] = display.encodeDigit(1);
digits[1] = display.encodeDigit(0);
digits[2] = display.encodeDigit(0);
// رقم آخر خاموش
}
display.setSegments(digits);
}
}
// تایمر سختافزاری هر 1ms
void timerISR() {
static int counter = 0;
counter++;
if (counter >= 100) { // هر 100ms
checkBatteryNow = true;
updateDisplayNow = true;
counter = 0;
}
}
// تایمر برق شهری (آداپتور)
void timerAdapterCheckISR() {
static bool lastAdapterState = false;
bool current = digitalRead(adapterStatusPin) == LOW;
if (current != lastAdapterState) {
lastAdapterState = current;
adapterConnected = current;
adapterChanged = true;
}
}
// خواندن ولتاژ باتری
float readBatteryVoltage() {
int raw = analogRead(batteryVoltagePin);
float voltage = (raw * 5.0) / 1023.0;
return voltage * voltageDividerRatio;
}