F. Yao
Created October 24, 2018

On-line Industrial Battery Bank Monitor

On-line battery monitoring

48

Things used in this project

Hardware components

CoolMOS C7 Gold SJ MOSFET
Infineon CoolMOS C7 Gold SJ MOSFET
×1
STM32 Nucleo-64 Board
STMicroelectronics STM32 Nucleo-64 Board
×1
tlp3547 OptiRelay
×1

Software apps and online services

mbed IDE

Story

Read more

Schematics

Circuit Diagram Simple Offline Solution

Circuit Diagram for BMS ,Circuit Diagram Simple Offline Solution

Showcase of Circuit Diagram for BMS with more batteries

Showcase of Circuit Diagram for BMS with more batteries
In this case, 18 cells of 12V, 100Ah makes ~220V DC output,
Total storage ranging 21.6kWH.

Circuit Diagram for BMS with backend connection

Circuit Diagram for BMS with backend connection, MKR1000 wired I2C, to thinkspeak.com

Code

onLineBatteryMonitor Simple solution offline

C/C++
onLineBatteryMonitor in mbed IDE
// onLineBatteryMonitor
# include <stdio.h>
# include <stdlib.h>
#include "mbed.h"
#include "TextLCD.h"    // LCD1602


/*********************
#define VOL_REF 3300
#define CUR_REF 1000
#define TEM_REF 100
**********************/
#define VOL_REF 3300 * 10  //With convert RATIO in shun resistors
#define CUR_REF 1000 / 10     //With 10ohm Resistor
#define TEM_REF 100
#define VOLMAX 12       // In 12V
#define CURMAX 500      // In 500mA
#define TEMMAX 100      // In 100C degree
#define MEASURESPAN  5          // in 20s


DigitalOut led1(LED1);

AnalogIn voltage_value(A1);
AnalogIn current_value(A2);
AnalogIn temperature_value(A0);


InterruptIn control(USER_BUTTON);
InterruptIn protection(D0);
DigitalOut trip_protection(D0);
DigitalOut trip_control(D1);

Ticker mticker;
Ticker pticker;

TextLCD lcd(D8, D9, D4, D5, D6, D7);



// Functions

// display text on LCD
void textLCD(char *text, int line) {
    char tmpBuf[16];
    for (int i = 0; i < 16; i++) tmpBuf[i] = 0x20;
    for (int i = 0; i < strlen(text); i++) {
        if (i < 16) tmpBuf[i] = text[i];
        lcd.locate(i, line);
        lcd.putc(tmpBuf[i]);
    }
}

void digitLCD(int val, int line) {
    char tmpBuf[8];
    //printf("bms = %d\n",  val);
    for (int i = 4; i < 12; i++) tmpBuf[i] = 0x20;
    int i=12;
    while (val){
        tmpBuf[i] = (val % 10) + '0';  
        val =val /10;
        lcd.locate(i, line);
        lcd.putc(tmpBuf[i]);
        i--;
        }           
} // end  of digitLCD
          



void measuretick() {

    float ana_read_a1,ana_read_a2,ana_read_a0;
    
    
    ana_read_a1 = VOL_REF* (voltage_value.read()); // Read the analog input value (value from 0.0 to 1.0 = full ADC conversion range) and Converts value in the 0V-3.3V range
    ana_read_a2 = CUR_REF* (current_value.read()); 
    ana_read_a0 = TEM_REF* (temperature_value.read()); 
        //printf("Voltage = %f: Current = %f: Temperature = %f.\n",  ana_read_a1,ana_read_a2,ana_read_a0);
       digitLCD( floor(ana_read_a1+0.5), 0 );
       digitLCD( floor(ana_read_a2+0.5), 1 );
       

}

void protectick() {
    float ana_read_a1,ana_read_a2,ana_read_a0;
    bool fault;
    
    ana_read_a1 = VOL_REF* (voltage_value.read()); // Read the analog input value (value from 0.0 to 1.0 = full ADC conversion range) and Converts value in the 0V-3.3V range
    ana_read_a2 = CUR_REF* (current_value.read()); 
    ana_read_a0 = TEM_REF* (temperature_value.read()); 
    fault = (ana_read_a1 > VOLMAX) or (ana_read_a2 > CURMAX ) or (ana_read_a0 > TEMMAX);
        if (fault) {
            trip_protection=0;        
        }
}



void control_ON_OFF() {
    trip_control = !trip_control;

    if (trip_control == 1) {
        led1= 1 ;
        trip_protection=1;
            textLCD("BMS is On.      ", 0);
            textLCD("Ready to go.    ", 1);
            wait(2);
        //trip_control= 1;  
           textLCD("VOL=          mV", 0);
           textLCD("CUR=          mA", 1);
           mticker.attach(&measuretick, MEASURESPAN);  
           pticker.attach(&protectick, 0.1);  
        }
    else if (trip_control != 1) {
        //trip_control= 0;  
        led1 = 0;           
           textLCD("BMS is Off.     ", 0);
           textLCD("Trip Off.       ", 1);
           mticker.detach(); 
           wait(1);
           //trip_protection=0; 
           //pticker.detach(); 
        }
}
void protection_on() {
           //trip_protection=0;
           if (trip_control==1){
               textLCD("BMS Fault.      ", 0);
               textLCD("Trip Off.       ", 1);
               pticker.detach(); 
               } 
}

int main(){
        lcd.cls();
    textLCD("Battery Monitor.", 1);
    wait(2);
    
    // Assign functions to button
    protection.fall(&protection_on);
    control.fall(&control_ON_OFF);    
    
    trip_protection=0;
    trip_control= 0;   // Start Close then trip on.
    control_ON_OFF();


        
    while(1){
           //closeLCD();
             
    } // end of while
}    // end of main

onLineBatteryMonitor.NUCLEO_F410RB.bin offline solution

C/C++
onLineBatteryMonitor.NUCLEO_F410RB.bin offline solution
No preview (download only).

I2C_bms_thingspeak.ino Cloud Supported Part

C/C++
I2C_bms_thingspeak.ino Cloud Supported Part
/* BMS on MKR1000 for thingspeak */

#include <SPI.h>
#include <WiFi101.h>
#include <Wire.h>
#include "ThingSpeak.h"
#include "arduino_secrets.h" 

#define MKR_ADDR  0x60
#define I2CCLOCK  100000

///////please enter your sensitive data in the Secret tab/arduino_secrets.h
char ssid[] = SECRET_SSID;        // your network SSID (name)
char pass[] = SECRET_PASS;    // your network password (use for WPA, or use as key for WEP)
int status = WL_IDLE_STATUS;     // the Wifi radio's status
WiFiClient  client;

unsigned long myChannelNumber = SECRET_BMS_CH_ID;
const char * myWriteAPIKey = SECRET_BMS_WRITE_APIKEY;
const char * myReadAPIKey = SECRET_BMS_READ_APIKEY;
unsigned int bmsFieldNumber = 3;
int ts_number = random(0,100);
int bms_voltage,  bms_current,  bms_temperature=0;
bool Fault=false;


void thingspeak_on(){  
  // check for the WiFi module:
  if (WiFi.status() == WL_NO_SHIELD) {
    Serial.println("WiFi shield not present.\n");
    while (true);
  }

  while (status != WL_CONNECTED) {
    Serial.print("Attempting to connect to WPA SSID: ");
    Serial.println(ssid);
    status = WiFi.begin(ssid, pass);
    delay(10000); 
  }
  
  Serial.print("You're connected to the network for ThingSpeak Update.");
   ThingSpeak.begin(client);  // Initialize ThingSpeak
   return;
}

void receiveEvent(int howMany){   
      String statusStr = "";     
      String comdata = "";
      int i=0;
      int index;
      //int index = comdata.indexOf(','); int x = str.substring(0, index).toInt(); int y = str.substring(index + 1, str.length()).toInt();

  while(0 < Wire.available()) // loop through the last
  {
    char c = Wire.read(); // receive byte as a character
    comdata += c;
    i++;
    if (i>24) { break; }
    Serial.print(c);         // print the character
  }
  // First data,
  index = comdata.indexOf(',');
  bms_voltage=comdata.substring(0,index).toInt();
  comdata=comdata.substring(index+1,comdata.length()); 
  // 2nd and 3rd data,
  index = comdata.indexOf(',');
  bms_current=comdata.substring(0,index).toInt();
  bms_temperature=comdata.substring(index+1,comdata.length()).toInt(); 

      // set the fields with the values
      ThingSpeak.setField(1, bms_voltage); 
      ThingSpeak.setField(2, bms_current);
      ThingSpeak.setField(3, bms_temperature);
      statusStr = String("Three fields set.");
      
      int x = ThingSpeak.writeFields(myChannelNumber, myWriteAPIKey);
      if(x == 200){
        Serial.println("Channel update successful. With number of "+String(ts_number) );
        }
        else{
          Serial.println("Problem updating channel. HTTP error code " + String(x));
          }
}  


void setup() {
  //Initialize serial and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {; }
  Wire.begin(MKR_ADDR);    // join i2c bus (address optional for master)
  Wire.setClock(I2CCLOCK); 
  Wire.onReceive(receiveEvent); // register event
  thingspeak_on();
  
}

void loop() {    
  //Serial.println("\nLoop On.");
  //delay(100);   
  // Network connection once every 20 seconds:
}

Credits

F. Yao

F. Yao

18 projects • 13 followers
.

Comments