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 ESP_BT;
// --- Pin Tanımlamaları ---
const int voltajReadPin = 34; // Akü Voltajı Okuma Pini (A0)
const int akimReadPin = 35; // ACS712 Akım Sensörü Okuma Pini
// --- PWM Donanım Ayarları ---
const int pwmPin = 25; // MOSFET Tetikleme Pini
const int pwmFrekansi = 5000; // 5 kHz frekans
const int pwmKanali = 0;
const int pwmCozunurluk = 8; // 8-bit çözünürlük (0 - 255 arası duty cycle)
// --- Kullanıcı Ayarlı Şarj Parametreleri (Varsayılanlar) ---
float limitUstVolt = 14.4; // Üst kesim / dolum voltajı
float limitAltVolt = 12.3; // Yeniden şarj başlama voltajı
float limitDevamVolt = 13.8; // Sabit tutma / devamlı şarj voltajı
float hedefSarjAkimi = 2.0; // Telefondan ayarlanabilir hedef şarj akımı (Amper)
// --- Hareketli Ortalama (Moving Average) Filtre Parametreleri ---
const int FILTRE_BOYUTU = 10; // Son 10 okumanın ortalaması alınacak
int voltajGecmis[FILTRE_BOYUTU] = {0};
int vFiltreIndeks = 0;
long voltajToplam = 0;
int akimGecmis[FILTRE_BOYUTU] = {0};
int aFiltreIndeks = 0;
long akimToplam = 0;
// --- Algoritma Durum Değişkenleri ---
int aktifMod = 1; // 1: Hibrit, 2: Kesimli Normal, 3: Direkt Sabit
int pwmDuty = 0; // O anki aktif PWM gücü (0-255)
bool mod1DolduMu = false; // Mod 1 için geçiş kontrolü
bool mod2BeklemedeMi = false; // Mod 2 için kesim sonrası bekleme kontrolü
float akuVoltaj = 0.0;
float sarjAkimi = 0.0;
unsigned long eskiZaman = 0;
// --- Filtreleme Fonksiyonları ---
int filtreleVoltaj(int yeniDeger) {
voltajToplam = voltajToplam - voltajGecmis[vFiltreIndeks];
voltajGecmis[vFiltreIndeks] = yeniDeger;
voltajToplam = voltajToplam + yeniDeger;
vFiltreIndeks = (vFiltreIndeks + 1) % FILTRE_BOYUTU;
return voltajToplam / FILTRE_BOYUTU;
}
int filtreleAkim(int yeniDeger) {
akimToplam = akimToplam - akimGecmis[aFiltreIndeks];
akimGecmis[aFiltreIndeks] = yeniDeger;
akimToplam = akimToplam + yeniDeger;
aFiltreIndeks = (aFiltreIndeks + 1) % FILTRE_BOYUTU;
return akimToplam / FILTRE_BOYUTU;
}
void setup() {
Serial.begin(115200);
// ESP32 PWM Yapılandırması
ledcSetup(pwmKanali, pwmFrekansi, pwmCozunurluk);
ledcAttachPin(pwmPin, pwmKanali);
ledcWrite(pwmKanali, 0); // Başlangıçta şarj kapalı
// Bluetooth Ağ Başlatma
ESP_BT.begin("Yenidir_BMS_Perfect");
Serial.println("Sistem Aktif! Bluetooth Eşleşme Adı: Yenidir_BMS_Perfect");
}
void loop() {
// 1. BLUETOOTH KOMUT AYRIŞTIRMA MERKEZİ
if (ESP_BT.available()) {
String gelenVeri = ESP_BT.readStringUntil('\n');
gelenVeri.trim();
if (gelenVeri.startsWith("MOD:")) {
aktifMod = gelenVeri.substring(4).toInt();
mod1DolduMu = false;
mod2BeklemedeMi = false;
pwmDuty = 0;
ESP_BT.print("Sistem: MOD "); ESP_BT.print(aktifMod); ESP_BT.println(" aktif edildi.");
}
else if (gelenVeri.startsWith("AKIM:")) {
hedefSarjAkimi = gelenVeri.substring(5).toFloat();
ESP_BT.print("Sistem: Yeni Hedef Şarj Akımı = "); ESP_BT.print(hedefSarjAkimi); ESP_BT.println(" A");
}
else if (gelenVeri.startsWith("UST:")) {
limitUstVolt = gelenVeri.substring(4).toFloat();
ESP_BT.print("Sistem: Üst Limit = "); ESP_BT.print(limitUstVolt); ESP_BT.println("V");
}
else if (gelenVeri.startsWith("ALT:")) {
limitAltVolt = gelenVeri.substring(4).toFloat();
ESP_BT.print("Sistem: Alt Limit = "); ESP_BT.print(limitAltVolt); ESP_BT.println("V");
}
else if (gelenVeri.startsWith("DEVAM:")) {
limitDevamVolt = gelenVeri.substring(6).toFloat();
ESP_BT.print("Sistem: Devamlı Voltajı = "); ESP_BT.print(limitDevamVolt); ESP_BT.println("V");
}
}
// 2. KONTROL VE HASSAS AYARLAMA DÖNGÜSÜ (Her 100 milisaniyede bir)
if (millis() - eskiZaman > 100) {
eskiZaman = millis();
// Analog Okumalar ve Filtre Entegrasyonu
int vHamAnalog = analogRead(voltajReadPin);
int vFiltreliAnalog = filtreleVoltaj(vHamAnalog); // Gürültüden arındırılmış voltaj verisi
akuVoltaj = (vFiltreliAnalog * 3.3 / 4095.0) * 5.545; // Voltaj bölücü dönüşümü
int iHamAnalog = analogRead(akimReadPin);
int iFiltreliAnalog = filtreleAkim(iHamAnalog); // Gürültüden arındırılmış akım verisi
float iVoltaj = (iFiltreliAnalog * 3.3) / 4095.0;
sarjAkimi = (iVoltaj - 2.5) / 0.1; // 20A ACS712 hassasiyet dönüşümü (100mV/A)
if (sarjAkimi < 0) sarjAkimi = 0.0;
// Telefona Durum Raporu Gönderme (Her 2 saniyede bir - 20 döngüde bir)
static int raporZamanlayici = 0;
if (raporZamanlayici++ >= 20) {
raporZamanlayici = 0;
ESP_BT.print("Akü: "); ESP_BT.print(akuVoltaj, 2); ESP_BT.print("V | ");
ESP_BT.print("Akım: "); ESP_BT.print(sarjAkimi, 2); ESP_BT.print("A / "); ESP_BT.print(hedefSarjAkimi, 1); ESP_BT.print("A | ");
ESP_BT.print("Mod: "); ESP_BT.print(aktifMod); ESP_BT.print(" | ");
ESP_BT.print("PWM: %"); ESP_BT.println((pwmDuty * 100) / 255);
}
// 3. SEÇİLEN MODA GÖRE HEDEF VOLTAJ BELİRLEME
float hedefVoltaj = 0.0;
bool sistemiKapat = false;
if (aktifMod == 1) {
// [SENARYO 1] Akü dolar 14.4V'a geçer, sonra otomatik 13.8V devamlı şarjda sabit kalır.
if (!mod1DolduMu) {
hedefVoltaj = limitUstVolt;
if (akuVoltaj >= limitUstVolt) {
mod1DolduMu = true;
ESP_BT.println("BİLGİ: Mod 1 tepe noktaya ulaştı. 13.8V Koruma Şarjına geçiliyor.");
}
} else {
hedefVoltaj = limitDevamVolt;
}
}
else if (aktifMod == 2) {
// [SENARYO 2] Akü dolar 14.4V olur şarj kesilir. 12.3V'a düşünce yeniden şarj başlar.
if (akuVoltaj >= limitUstVolt) mod2BeklemedeMi = true;
if (akuVoltaj <= limitAltVolt) mod2BeklemedeMi = false;
if (mod2BeklemedeMi) sistemiKapat = true;
else hedefVoltaj = limitUstVolt;
}
else if (aktifMod == 3) {
// [SENARYO 3] Sınırlara bakılmaksızın direkt akü belirlenen devamlı voltajla (13.8V) şarj edilir.
hedefVoltaj = limitDevamVolt;
}
// 4. CC / CV (SABİT AKIM / SABİT VOLTAJ) PWM DENGELEME MOTORU
if (sistemiKapat) {
pwmDuty = 0;
}
else {
// Akım Korunumu Önceliği (Constant Current Fazı)
if (sarjAkimi > (hedefSarjAkimi + 0.05)) {
pwmDuty -= 2; // Okunan akım hedeften büyükse PWM gücünü hızlıca kıs
}
// Voltaj Dengelenmesi Önceliği (Constant Voltage Fazı)
else {
if (akuVoltaj < hedefVoltaj) {
if (sarjAkimi < hedefSarjAkimi) {
pwmDuty += 1; // Voltaj düşük ve akım payı varsa gücü kademeli artır
}
}
else if (akuVoltaj > hedefVoltaj) {
pwmDuty -= 1; // Hedef voltaj aşıldıysa PWM'i yumuşakça düşür
}
}
}
// PWM Değerini Donanım Sınırlarında Tut (8-Bit Koruma)
if (pwmDuty > 255) pwmDuty = 255;
if (pwmDuty < 0) pwmDuty = 0;
// Hesaplanan PWM değerini MOSFET sürücüye ilet
ledcWrite(pwmKanali, pwmDuty);
}
}
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 Özcan.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!
Görsel Önerileri:
1. Kapak Görseli: Tüm bu birleştirilmiş özellikleri simgeleyen, akım ve voltaj dengesini tek bir potansiyometre veya mobil arayüz çizgisiyle simüle eden kapsamlı bir sistem mimarisi şeması.
Henüz yorum yapılmamış. İlk yorumu siz yapın!