0

I wanted to replicate this BMS I have seen in youtube because I cannot afford the price the owner is asking. I want to explore how to do it. Here's the youtube link

I already have the codes for measuring temperature, voltage and current.

// Floats for ADC voltage & Input voltage
float adc_voltage = 0.0;
float in_voltage = 0.0;

// Floats for resistor values in divider (in ohms)
float R1 = 30000.0;
float R2 = 7500.0; 

// Float for Reference Voltage
float ref_voltage = 5.0;

// Integer for ADC value
int adc_value = 0;

// Variables for Measured Voltage and Calculated Current
double Vout = 0;
double Current = 0;

const double scale_factor = 0.066; // 30A

const double vRef = 5.00;
const double resConvert = 1024;
double resADC = vRef/resConvert;
double zeroPoint = vRef/2;

void setup(){
   // Setup Serial Monitor
   Serial.begin(9600);
   Serial.println("BMS");
}

void loop(){
   // Read the Analog Input
   adc_value = analogRead(A0);

   // Determine voltage at ADC input
   adc_voltage  = (adc_value * ref_voltage) / 1024.0; 

   // Calculate voltage at divider input
   in_voltage = adc_voltage / (R2/(R1+R2)); 

   // Print results to Serial Monitor to 2 decimal places
  Serial.print("Input_Voltage = ");
  Serial.print(in_voltage, 2);
  Serial.print(" V "); 

  // Vout is read 1000 Times for precision
  for(int i = 0; i < 1000; i++) {
    Vout = (Vout + (resADC * analogRead(A1)));   
    delay(1);
  }

  // Get Vout in mv
  Vout = Vout /1000;

  // Convert Vout into Current using Scale Factor
  Current = (Vout - zeroPoint)/ scale_factor;                   

  // Print Vout and Current to two Current = ");                  
                        
  Serial.print("Input_Current = ");                  
  Serial.print(Current,2);
  Serial.print(" A ");

  //Multiply voltage and current to get power

  float power = in_voltage*Current;

  Serial.print("Power= ");                  
  Serial.print(power,2);
  Serial.print(" W ");

  // Get a reading from the temperature sensor:
  int reading = analogRead(A3);

  // Convert the reading into voltage:
  float voltage = reading * (5000 / 1024.0);

  // Convert the voltage into the temperature in degree Celsius:
  float temperature = voltage / 10;

  // Print the temperature in the Serial Monitor:
  Serial.print("Temperature = ");
  Serial.print(temperature);
  Serial.print(" \xC2\xB0"); // shows degree symbol
  Serial.println("C");


  delay(1000); 
}

I also seen this code for SOC calculation but there's no comments in the code so I cannot fully understand where are the values are comming and the basis for some of the multipliers used

  #include <LiquidCrystal.h>                                                                                
  LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
  const int mVperAmp = 100;const float chargingdfficiency= 0.7;
  int RawValue= 0, ACSoffset = 2500;
  double Voltage = 0, Amps = 0;
  double g,q;
  int m=0,c=0,d;
  void resett() {
        digitalWrite(8,LOW);
        digitalWrite(7,LOW);
  }

  void setup() {
    pinMode(A0, INPUT);pinMode(A1, INPUT);
    pinMode(7,OUTPUT);pinMode(8,OUTPUT);
    pinMode(9,OUTPUT);
    Serial.begin(9600);
    delay(10);lcd.begin(20, 4); delay(10);
  }

  void loop() {
    resett();
    double vini=analogRead(1);vini = vini*5/1023;
    vini=5*vini;Serial.print(vini,3);vini=vini/6;
    double soc=((666.6667)*vini)-1300;delay(10);
    q=soc*.42;
    if(soc<30){
      m=1;resett(); digitalWrite(7,HIGH);
    } //charging

    if(soc>=100){
      m=0;resett();digitalWrite(8,HIGH); 
    } // DISCHARGING

    if(m==0){
      resett();digitalWrite(8,HIGH);
    }

    delay(10);

    while(1){
      RawValue = analogRead(0);
      Voltage = (RawValue / 1024.0) * 5000;
      Amps = ((Voltage - ACSoffset) / mVperAmp);Amps=-Amps;
      if((Amps<.098)&&(Amps>-.098)){
        Amps=0;
      }

      if(Amps>9){
        resett();
        lcd.clear();
        lcd.display();
        lcd.setCursor(1,0);
        lcd.print("Overload");digitalWrite(9,HIGH);
        while(1);
      }
      if(m==0){
        if(Amps<=1.5) {
          g=1.183;
        }
        else if(Amps<=2) {
          g=0.042*Amps+1.12;
        }
        else if(Amps<=4) {
          g=0.028*Amps+1.148;
        }
        else if(Amps<=5) {
          g=0.032*Amps+1.132;
        }
        else if(Amps<=6) {
          g=0.03*Amps+1.142;
        }
        else if(Amps<=7) {
          g=0.325*Amps-0.628;
        }
        else if(Amps<=7.5) {
          g=0.066*Amps+1.185;
        }
        else if(Amps<=8) {
          g=0.028*Amps+1.47;
        }
        else if(Amps<=10){
          g=1.694;
        }

        soc=(q-Amps*g*0.0002778)*2.38095; 
        q=soc*.42;

        if(soc<5) {
          m=1;resett();digitalWrite(7,HIGH);
        } 
      }
      if(m==1){

        soc=(q-Amps*chargingdfficiency*0.0002778)*2.38095;

        q=soc*.42;

        if(soc>=100) {
          m=0;resett();digitalWrite(8,HIGH);
        }
      }
      lcd.clear();
      lcd.display();
      lcd.setCursor(1,0);
      lcd.print("Soc = ");
      lcd.setCursor(13,0);
      lcd.print(soc,1);
      lcd.setCursor(19,0);
      lcd.print("%");
      lcd.setCursor(1,1);
      lcd.print("Amps= ");
      lcd.setCursor(13,1);
      lcd.print(Amps,1);

      if (m==1) {
        lcd.setCursor(1,2);lcd.print("Charging");
        }

     else {
        lcd.setCursor(1,2);lcd.print("Discharge");
      }

      lcd.setCursor(1,3);lcd.print("Normal");
      Serial.println((vini),3);
      Serial.print("Amps = ");
      Serial.println(Amps,9);
      Serial.print(" Soc = ");
      Serial.println(soc,9);

      for(d=0;((Amps==0)&&(d<=1200));d++) {
        RawValue = analogRead(0);
        Voltage = (RawValue / 1024.0) * 5000;
        Amps = ((Voltage - ACSoffset) / mVperAmp);Amps=-Amps;

        if(d==1200 ){
          vini=analogRead(1);vini = vini*25/(6*1023);
          soc=((666.6667)*vini)-1300;d=0;
        }
      }

      delay(1000);
    }
  }

I also tried to convert the couomb counting method (the integration formula) in tode but no luck it wasn't working well and I cant show it here I've deleted it already :< I really need to estimate the SOC and SOH. I dont need it to be too accurate (compared to SOC estimation methods that includes kalman filter or other that uses matlab or python) I really need it in Arduino only.

New contributor
Anonymous X is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct.
2
  • What is your question?
    – StarCat
    Mar 17 at 7:37
  • How to estimate the SOC and calculate the SOH using arduino just like in the youtube link mentioned above or any other method as long as it is only in arduino (through coding). Mar 17 at 7:55

0