Projemizin başından beri adım adım geliştirdiğimiz, tüm isteklerini ve senaryoları eksiksiz barındıran endüstriyel kalitedeki Akıllı Akü Yönetim ve Şarj Kontrol Cihazı (BMS) projesini tek bir çatı altında topluyoruz.
Bu nihai kod mimarisinde; röle yerine yüksek frekanslı kararlı PWM kontrolü, telefondan anlık olarak güncellenebilen hedef şarj akımı (Constant Current) ayarı, 3 farklı akıllı şarj senaryosu ve ESP32'nin analog pinlerindeki tüm elektriksel gürültüleri sıfırlayan Hareketli Ortalama (Moving Average) Yazılımsal Filtresi bir araya getirilmiştir. Wi-Fi kapatılarak sadece Bluetooth üzerinden telefon terminalinizle haberleşen bu sistemi, yenidir.com takipçileri ve kendi projelerini üreten hobiciler için eksiksiz bir ana kaynak olarak paylaşıyoruz.
Aşağıdaki kodu doğrudan Arduino IDE programınıza yapıştırıp ESP32 kartınıza yükleyebilirsiniz. Herhangi bir harici kütüphane kurmanıza gerek yoktur.
#include "BluetoothSerial.h"
BluetoothSerial SerialBT;
// Donanim Pin Tanimlamalari
const int voltajPin = 34;
const int akimPin = 35;
const int pwmPin = 25;
// PWM Ayarlari
const int pwmFrekans = 5000;
const int pwmCozunurluk = 8;
int pwmDuty = 0;
// Hareketli Ortalama Filtre Degiskenleri
const int filtreKatsayisi = 10;
float voltajDizi[filtreKatsayisi] = {0};
float akimDizi[filtreKatsayisi] = {0};
int filtreIndex = 0;
// Sistem ve Sarj Limitleri
int aktifMod = 1;
float hedonSarjAkimi = 3.0;
float limitUstVolt = 14.4;
float limitAltVolt = 12.3;
float limitDevamVolt = 13.8;
// Durum Bayraklari
bool mod1DolduMu = false;
bool mod2BeklemedeMi = false;
bool sistemErisimi = false; // Güvenlik için kilitli başlıyoruz!
String gelenVeri = "";
float gercekVoltajOku() {
int hamDeger = analogRead(voltajPin);
float analogVolt = (hamDeger * 3.3) / 4095.0;
return analogVolt * 5.0;
}
float gercekAkimOku() {
int hamDeger = analogRead(akimPin);
float analogVolt = (hamDeger * 3.3) / 4095.0;
return (analogVolt - 2.5) / 0.066;
}
void setup() {
Serial.begin(115200);
// Standart Bluetooth başlatma (Windows geçsin ama yazılım duvarına çarpsın)
SerialBT.begin("Yenidir_BMS_Serial");
Serial.println("Yenidir BMS Baslatildi. Yazilamsal Guvenlik Duvari Aktif!");
ledcAttach(pwmPin, pwmFrekans, pwmCozunurluk);
}
void loop() {
if (SerialBT.available() > 0) {
gelenVeri = SerialBT.readString();
gelenVeri.trim();
}
else if (Serial.available() > 0) {
gelenVeri = Serial.readString();
gelenVeri.trim();
}
if (gelenVeri != "") {
// 1. Gelen komut şifre çözme komutu mu?
if (gelenVeri.startsWith("SIFRE:")) {
String girilenSifre = gelenVeri.substring(6);
if (girilenSifre == "1234") {
sistemErisimi = true;
SerialBT.println("Sistem: Sifre Dogru. Erisim Onaylandi!");
Serial.println("Sistem: Bluetooth erisimi onaylandi.");
} else {
sistemErisimi = false;
SerialBT.println("Sistem: HATALI SIFRE! Erisim Engellendi.");
}
}
// 2. Eğer şifre doğru girildiyse diğer komutları çalıştır
else if (sistemErisimi) {
if (gelenVeri.startsWith("MOD:")) {
aktifMod = gelenVeri.substring(4).toInt();
mod1DolduMu = false; mod2BeklemedeMi = false; pwmDuty = 0;
SerialBT.print("Sistem: MOD DEGISTI -> "); SerialBT.println(aktifMod);
Serial.print("Sistem: MOD DEGISTI -> "); Serial.println(aktifMod);
}
else if (gelenVeri.startsWith("AKIM:")) {
hedonSarjAkimi = gelenVeri.substring(5).toFloat();
SerialBT.print("Sistem: HEDEF AKIM -> "); SerialBT.println(hedonSarjAkimi);
}
else if (gelenVeri.startsWith("UST:")) {
limitUstVolt = gelenVeri.substring(4).toFloat();
SerialBT.print("Sistem: UST LIMIT -> "); SerialBT.println(limitUstVolt);
}
else if (gelenVeri.startsWith("ALT:")) {
limitAltVolt = gelenVeri.substring(4).toFloat();
SerialBT.print("Sistem: ALT LIMIT -> "); SerialBT.println(limitAltVolt);
}
else if (gelenVeri.startsWith("DEVAM:")) {
limitDevamVolt = gelenVeri.substring(6).toFloat();
SerialBT.print("Sistem: DEVAM LIMIT -> "); SerialBT.println(limitDevamVolt);
}
}
// 3. Şifre girmeden başka komut basarsa uyar ve reddet
else {
SerialBT.println("Sistem: ERISIM ENGELLENDI! Lutfen once SIFRE:1234 gonderin.");
}
gelenVeri = "";
}
// Filtre ve Şarj Algoritması arka planda güvenle çalışmaya devam eder...
voltajDizi[filtreIndex] = gercekVoltajOku();
akimDizi[filtreIndex] = gercekAkimOku();
filtreIndex = (filtreIndex + 1) % filtreKatsayisi;
float filtreliVolt = 0; float filtreliAkim = 0;
for (int i = 0; i < filtreKatsayisi; i++) {
filtreliVolt += voltajDizi[i]; filtreliAkim += akimDizi[i];
}
filtreliVolt /= filtreKatsayisi; filtreliAkim /= filtreKatsayisi;
if (aktifMod == 1) {
if (!mod1DolduMu) {
if (filtreliVolt >= limitUstVolt) mod1DolduMu = true;
else {
if (filtreliAkim < hedonSarjAkimi && pwmDuty < 255) pwmDuty++;
if (filtreliAkim > hedonSarjAkimi && pwmDuty > 0) pwmDuty--;
}
} else {
if (filtreliVolt < limitDevamVolt && pwmDuty < 255) pwmDuty++;
if (filtreliVolt > limitDevamVolt && pwmDuty > 0) pwmDuty--;
}
}
else if (aktifMod == 2) {
if (!mod2BeklemedeMi) {
if (filtreliVolt >= limitUstVolt) { mod2BeklemedeMi = true; pwmDuty = 0; }
else {
if (filtreliAkim < hedonSarjAkimi && pwmDuty < 255) pwmDuty++;
if (filtreliAkim > hedonSarjAkimi && pwmDuty > 0) pwmDuty--;
}
} else {
pwmDuty = 0;
if (filtreliVolt <= limitAltVolt) mod2BeklemedeMi = false;
}
}
else if (aktifMod == 3) {
if (filtreliVolt < limitDevamVolt && pwmDuty < 255) pwmDuty++;
if (filtreliVolt > limitDevamVolt && pwmDuty > 0) pwmDuty--;
}
ledcWrite(pwmPin, pwmDuty);
// Periyodik Raporlama (Sadece Şifre Doğruysa Bluetooth'a basar)
static unsigned long sonRaporZamani = 0;
if (millis() - sonRaporZamani >= 2000) {
sonRaporZamani = millis();
String rapor = "V:" + String(filtreliVolt, 2) + " A:" + String(filtreliAkim, 2) + " M:" + String(aktifMod) + " P:" + String(pwmDuty);
Serial.println(rapor); // Kabloda hep akar
if (sistemErisimi) {
SerialBT.println(rapor); // Bluetooth terminalinde sadece giriş yapılınca akar!
}
}
delay(10);
}
Sistem açıldığında telefonunuzdan herhangi bir Bluetooth seri terminal uygulaması ile "Yenidir_BMS_Perfect" cihazına bağlanın. Ardından aşağıdaki komut şablonlarıyla cihazın çalışma mantığını anlık olarak uzaktan manipüle edebilirsiniz:
MOD:1, MOD:2 veya MOD:3 yazarak senaryolar arasında hızlıca atlayabilirsiniz.AKIM:3.5 göndermeniz yeterlidir.UST:14.2, ALT:12.0 veya DEVAM:13.6 gibi komutlarla varsayılan ayarları ezebilirsiniz.Yazılımsal ortalama filtresinin entegre edilmesiyle birlikte, MOSFET'in hızlı anahtarlamasından doğan gürültüler tamamen sönümlenmiş ve cihazın kararlılığı endüstriyel standartlara ulaştırılmıştır. Keyifli ve güvenli testler dileriz!
Not:
Bluetooth Classic de yazılımsal güvenlik kullandık ESP32 de Arduino'da yapabileceğimiz en fazla güvenlik bu. Yani bağlantıyı engelleyemiyoruz ama veri alış verişine engel koyabiliyoruz. Bir sonraki yazıda BLE ile projeye devam edeceğiz.
Henüz yorum yapılmamış. İlk yorumu siz yapın!