ESP32 ile akıllı akü şarj sistemi-Bluetooth Classic

👤 Yazar: ozcan 📅 Tarih: 01.06.2026 01:37 👁️ Görüntüleme: 107

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.

Projenin Donanım Anatomisi ve Bağlantı Şeması

  • ESP32 Geliştirme Kartı: Sistemin beyni olarak tüm ölçüm ve PWM kararlarını yürütür.
  • IRF540N N-Kanal MOSFET ve Sürücü Devresi: Şarj kaynağından (Adaptör vb.) gelen akımı yüksek frekansta anahtarlayarak aküye aktarır. PWM pini olan GPIO 25'e bağlıdır.
  • ACS712 (20A veya 30A) Akım Sensörü: Şarj hattına seri bağlanır. Çıkış ucu gürültüden arındırılmak üzere GPIO 35 analog pinine bağlanır.
  • Voltaj Bölücü Direnç Ağı (10kΩ ve 2.2kΩ): 12V akünün voltajını ESP32'nin okuyabileceği güvenli aralığa (0-3.3V) düşürür. Orta noktası GPIO 34 analog pinine bağlanır.

ESP32 Akıllı Şarj Kontrol ve Filtreleme Kod Bloğu (Tek Parça)

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); 
}

Telefon Üzerinden Sistemi Yönetme Rehberi

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 Geçişleri: MOD:1, MOD:2 veya MOD:3 yazarak senaryolar arasında hızlıca atlayabilirsiniz.
  • Şarj Akım Ayarı: Akünün kapasitesine uygun maksimum şarj akımını ayarlamak için örneğin AKIM:3.5 göndermeniz yeterlidir.
  • Limit Değişiklikleri: İhtiyacınıza göre limit değerleri değiştirmek isterseniz 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.

💬 Yorumlar

Henüz yorum yapılmamış. İlk yorumu siz yapın!

Bir Yorum Bırakın

Güvenlik Kontrolü:

Yenidir.com
↑ Sayfa Başı
📞 İletişim ✉ E-Posta Gönder
© 2026 Yenidir.com
Yenidir CMS V0.1