bms lv

Dependencies:   mbed

main.cpp

Committer:
nemanja1994
Date:
2019-03-25
Revision:
2:86cf05e531e6
Parent:
1:a2d940c93002

File content as of revision 2:86cf05e531e6:

#include "mbed.h"
// short demo for BMS LV IC
// this code was created using the example code for arduino for using this IC: https://github.com/Ralim/Open-BMS/blob/master/Arduino%20Test/ISL94202/ISL94202.ino
// https://www.renesas.com/eu/en/doc/datasheet/isl94202.pdf

// UART Initialization
// Serial pc(PC_10,PC_11,19200); // if using ASAD uncomment this line
Serial pc(SERIAL_TX, SERIAL_RX,19200); // if using ASAD comment this line

// I2C initialization
//I2C i2c(PB_14, PB_13); // if using ASAD uncomment this line
I2C i2c(PB_9,PB_8); // if using ASAD comment this line

// BMS LV slave address
// IMPORTANT INFO FOR NEWBIES - The mbed API uses 8 bit addresses, so make sure to take that 7 bit address and left shift it by 1 before passing it. 
#define BMS_LV (0x50<<1) // this is the value given in datasheet (0x50)
// define BMS_LV (0x28<<1) // this is the value used in arduino example I found

//I2C write, read explanation:
//i2c.write(slave_address,char array we want to send, number of bytes we are sending, repeat)
// default value for repeat is false, which means i2c stops communication after sending message 

//i2c.read(slave_address,char array we want to receive, number of bytes we are receiving,repeat)


// I2C dummy messages
char dummy[1]={0x00};

// helper functions

void write_register(char reg, int value){
    char msg[2]={reg,value};
    i2c.write(BMS_LV,msg,2,false);
    }
void disableEEPROMAccess(){
    write_register(0x89,0x00);
    }
void enableEEPROMAccess(){
    write_register(0x89,0x01);
    }
char read_register(char reg){
    char msg[1]={reg};
    char result[1];
    i2c.write(BMS_LV,msg,1,true);
    i2c.read(BMS_LV,result,1,false);
    return result[0];
    };
void set_number_of_cells(int val){
    enableEEPROMAccess();
    char buffer[4];
    char base;
    char msg1[1];
    char msg2[2];
    // The register is anded (&) with 0xFC because of EEPROM pages explained in datasheet
    // for more details call me :D cannot explain it easily with this comments
    base=0x49 & 0xFC;
    buffer[0]=read_register(base);
    wait_ms(1); // delay to allow EEPROM refresh
    
    // read 4 bytes in EEPROM page starting from base address
    msg1[0]=base;
    i2c.write(BMS_LV,msg1,1,true);
    i2c.read(BMS_LV,buffer,4,false);
    
    //update wanted value in EEPROM
     buffer[0x49 & 0x03] = 0b11000011;
     msg2[0]=base;
     msg2[1]=buffer[0];
     i2c.write(BMS_LV,msg2,2,false);
     wait_ms(50);
     
     //^Special case for first byte causing EEPROM reload
     for (uint8_t i = 0; i < 4; i++){
         msg2[0]=base+i;
         msg2[1]=buffer[i];
         i2c.write(BMS_LV,msg2,2,false);
    wait_ms(35);//pause for EEPROM write
    }
    wait_ms(50); 
    disableEEPROMAccess();
    };
float readCellVoltage(int val){
    char buffer[2];
    int tmpres;
    float res;
    buffer[0]=read_register(0x90+2*val);
    buffer[1]=read_register(0x90+2*val+1);
    tmpres=(buffer[1]<<8) | buffer[0];
    res=tmpres*1.8*8;
    res=res/(4095*3);
    return res;
    };
    //main code
int main()
{
    pc.printf("BMS LV example");
    // dummy conversation on the beggining - I do not know why this guy used this but here it is
    i2c.write(0x01,dummy,1,false);
    disableEEPROMAccess();
    
    
    set_number_of_cells(4);
    while(1) {
        // print voltage of each cell starting from the one closest to the GND 
        pc.printf("The voltage of cell number %d is %.2f V\n",1,readCellVoltage(0));
        wait(1);
        pc.printf("The voltage of cell number %d is %.2f V\n",2,readCellVoltage(1));
        wait(1);
        pc.printf("The voltage of cell number %d is %.2f V\n",3,readCellVoltage(6));
        wait(1);
        pc.printf("The voltage of cell number %d is %.2f V\n",4,readCellVoltage(7));
        wait(1);
    }
}