Ultima versão da banca de ensaios BMS Fev2017

Dependencies:   CANnucleo LTC68041 mbed

Fork of BMS_4 by Gerardo Antonio

main.cpp

Committer:
Crazyaboutmachines
Date:
2017-03-01
Revision:
50:3cc0ad385612
Parent:
49:94a58ef0edc4

File content as of revision 50:3cc0ad385612:

#include "CANnucleo.h"
#include "mbed.h"
#include "LTC68041.h"

uint8_t const TOTAL_IC = 1;//!<number of ICs in the daisy chain
uint8_t rx_cfg[TOTAL_IC][8];
uint8_t tx_cfg[TOTAL_IC][6];
uint16_t aux_codes[TOTAL_IC][6];
uint16_t cell_codes[TOTAL_IC][12];

//uint16_t temp_codes[32]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32};
float temp_codes[32]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32};

volatile bool           msgAvailable = false;
volatile bool           to_send = false;
CANnucleo::CAN          can(PA_11, PA_12);  // CAN Rx pin name, CAN Tx pin name
CANnucleo::CANMessage   rxMsg;
CANnucleo::CANMessage   txMsg;
DigitalOut              led(PA_5);

/*!***********************************
\brief Initializes the configuration array
**************************************/
void init_cfg()
{
    for (int i = 0; i<TOTAL_IC; i++) {
        tx_cfg[i][0] = 0xFE;
        tx_cfg[i][1] = 0x00 ;
        tx_cfg[i][2] = 0x00 ;
        tx_cfg[i][3] = 0x00 ;
        tx_cfg[i][4] = 0x00 ;
        tx_cfg[i][5] = 0x00 ;
    }
}
void serial_print_hex(uint8_t data)
{
    if (data< 16) {
        printf("0");
        printf("%x",(uint8_t)data);
    } else
        printf("%x",(uint8_t)data);
}
void print_config()
{
    int cfg_pec;
    printf("Written Configuration:\n\r ");
    for (int current_ic = 0; current_ic<TOTAL_IC; current_ic++) {
        printf(" IC ");
        printf("%d", current_ic+1);
        printf(": ");
        printf("0x");
        serial_print_hex(tx_cfg[current_ic][0]);
        printf(", 0x");
        serial_print_hex(tx_cfg[current_ic][1]);
        printf(", 0x");
        serial_print_hex(tx_cfg[current_ic][2]);
        printf(", 0x");
        serial_print_hex(tx_cfg[current_ic][3]);
        printf(", 0x");
        serial_print_hex(tx_cfg[current_ic][4]);
        printf(", 0x");
        serial_print_hex(tx_cfg[current_ic][5]);
        printf(", Calculated PEC: 0x");
        cfg_pec = pec15_calc(6,&tx_cfg[current_ic][0]);
        serial_print_hex((uint8_t)(cfg_pec>>8));
        printf(", 0x");
        serial_print_hex((uint8_t)(cfg_pec));
    }
    printf("\n\r");
}

void print_rxconfig()
{
    printf("Received Configuration ");
    for (int current_ic=0; current_ic<TOTAL_IC; current_ic++) {
        printf(" IC ");
        printf("%d " ,current_ic+1);
        printf(": 0x");
        serial_print_hex(rx_cfg[current_ic][0]);
        printf(", 0x");
        serial_print_hex(rx_cfg[current_ic][1]);
        printf(", 0x");
        serial_print_hex(rx_cfg[current_ic][2]);
        printf(", 0x");
        serial_print_hex(rx_cfg[current_ic][3]);
        printf(", 0x");
        serial_print_hex(rx_cfg[current_ic][4]);
        printf(", 0x");
        serial_print_hex(rx_cfg[current_ic][5]);
        printf(", Received PEC: 0x");
        serial_print_hex(rx_cfg[current_ic][6]);
        printf(", 0x");
        serial_print_hex(rx_cfg[current_ic][7]);
    }
}

int err;
void print_cells2()
{

    for (int current_ic = 0 ; current_ic < TOTAL_IC; current_ic++) {

        for (int i=0; i<12; i++) {
            printf(" C");
            printf("%d",i+1);
            printf(":");
            printf("%f", cell_codes[current_ic][i]*0.0001);
            printf(",");
        }

    }
}

void pec_error()
{
    for(int i = 0; i<5; i++) {
        led = 1;
        wait(0.2);
        led=0;
        wait(0.2);
    }
}
char cells_left=0;
char temps_left=0;
Ticker ticker;
Ticker sender;

typedef union can_union {
    int i[2];
    char bytes[8];
    float f[2];
} data;


/*
void message_trigger()
{
    if(cells_left < 1) {
        sender.detach();
    } else {
        to_send = 1;
    }
}
*/

void message_trigger()
{
    if((cells_left < 1)&&(temps_left < 1)) {
        sender.detach();
    } else {
        to_send = 1;
    }
}


void check_charging_voltage()
{
    wakeup_idle();
    LTC6804_adcv();
    wait_ms(10);
    wakeup_idle();
    err = LTC6804_rdcv(0, TOTAL_IC,cell_codes);
    if (err == -1) {
        pec_error();
    }
    cells_left = 12;
    for (int current_ic = 0 ; current_ic < TOTAL_IC; current_ic++) {
        for (int i=0; i<12; i++) {
            if(cell_codes[current_ic][i]*0.0001  > 4.07) {   //liga balanceamento
                switch (i) {
                    case 0: //cell 1
                        tx_cfg[0][4] = tx_cfg[0][4] | 0x01 ;    // 00000001
                    case 1: //cell 2
                        tx_cfg[0][4] = tx_cfg[0][4] | 0x02 ;    // 00000010
                    case 2: //cell 3
                        tx_cfg[0][4] = tx_cfg[0][4] | 0x04 ;    // 00000100
                    case 3: //cell 4
                        tx_cfg[0][4] = tx_cfg[0][4] | 0x08 ;    // 00001000
                    case 4: //cell 5
                        tx_cfg[0][4] = tx_cfg[0][4] | 0x10 ;    // 00010000
                    case 6: //cell 7
                        tx_cfg[0][4] = tx_cfg[0][4] | 0x40 ;    // 01000000
                    case 7: //cell 8
                        tx_cfg[0][4] = tx_cfg[0][4] | 0x80 ;    // 10000000
                    case 8: //cell 9
                        tx_cfg[0][5] = tx_cfg[0][5] | 0x01;    // 00000001
                    case 9: //cell 10
                        tx_cfg[0][5] = tx_cfg[0][5] | 0x02;    // 00000010
                }
            } else {
                switch (i) {
                    case 0: //cell 1
                        tx_cfg[0][4] = tx_cfg[0][4] & 0xFE ;    // 11111110
                    case 1: //cell 2
                        tx_cfg[0][4] = tx_cfg[0][4] & 0xFD ;    // 11111101
                    case 2: //cell 3
                        tx_cfg[0][4] = tx_cfg[0][4] & 0xFB ;    // 11111011
                    case 3: //cell 4
                        tx_cfg[0][4] = tx_cfg[0][4] & 0xF7 ;    // 11110111
                    case 4: //cell 5
                        tx_cfg[0][4] = tx_cfg[0][4] & 0xEF ;    // 11101111
                    case 6: //cell 7
                        tx_cfg[0][4] = tx_cfg[0][4] & 0xBF ;    // 10111111
                    case 7: //cell 8
                        tx_cfg[0][4] = tx_cfg[0][4] & 0x7F ;    // 01111111
                    case 8: //cell 9
                        tx_cfg[0][5] = tx_cfg[0][5] & 0xFE;    // 11111110
                    case 9: //cell 10
                        tx_cfg[0][5] = tx_cfg[0][5] & 0xFD;    // 11111101
                }
            }
        }
    }
    //print_cells2();
    LTC6804_wrcfg(TOTAL_IC,tx_cfg);
}

void check_discharging_voltage()
{
    wakeup_idle();
    LTC6804_adcv();
    wait_ms(10);
    wakeup_idle();
    err = LTC6804_rdcv(0, TOTAL_IC,cell_codes);
    if (err == -1) {
        pec_error();
    }/*
    for (int current_ic = 0 ; current_ic < TOTAL_IC; current_ic++) {
        for (int i=0; i<11; i++) {
            //printf("%f\t", cell_codes[current_ic][i]*0.0001);
            if(cell_codes[current_ic][i]*0.0001  < 2.7) {
                txMsg.clear();
                txMsg.id = 1;
                printf("%f\t", cell_codes[current_ic][i]*0.0001);

                txMsg << cell_codes[current_ic][i]*0.0001;
                can.write(txMsg);
                wait(0.1);
            }
        }
    }*/
    //print_cells2();
    cells_left = 12;
    tx_cfg[0][4] = tx_cfg[0][4] & 0b00000000;  //para desactivar balanceamento durante a descarga
    tx_cfg[0][5] = tx_cfg[0][5] & 0b11110000;
    //print_cells2();
    LTC6804_wrcfg(TOTAL_IC,tx_cfg);
}

AnalogIn MUXA_Read(PC_1);   
DigitalOut MUXA_0(PB_10);   
DigitalOut MUXA_1(PB_2);   
DigitalOut MUXA_2(PB_0);   
DigitalOut MUXA_3(PB_1);   
AnalogIn MUXB_Read(PC_2);   
DigitalOut MUXB_0(PC_7);   
DigitalOut MUXB_1(PC_6);   
DigitalOut MUXB_2(PB_14);   
DigitalOut MUXB_3(PB_15);

/*
void check_temperatures()
{               
   int i=14;
   MUXA_3=0; MUXA_2=0; MUXA_1=0; MUXA_0=1;   //(escolha do NTC on board)
   temp_codes[i]= MUXA_Read.read()*3300;
   temps_left = 32;
}
*/

void alarm(char alarm_code){
            txMsg.clear();
            txMsg.id = 8;     //BMS1=>ID:11; BMS2=>ID:12; BMS3=>ID:13.
            txMsg.len = 1;
            txMsg.data[0] = alarm_code;  //alarm_code                  
            if(!(can.write(txMsg))) {   //se nao conseguiu transmitir continua a tentar transmitir a tensão dessa celula
                pec_error();
            }
    }


float temp;
void check_temperatures()
{
    for (int i=0; i<32; i++){
        switch (i) {
                    case 0: //ntc 1                             //from MUXA
                        MUXA_3=0; MUXA_2=0; MUXA_1=0; MUXA_0=0; break;
                    case 1: //ntc 2
                        MUXA_3=0; MUXA_2=0; MUXA_1=0; MUXA_0=1; break;
                    case 2: //ntc 3
                        MUXA_3=0; MUXA_2=0; MUXA_1=1; MUXA_0=0; break;
                    case 3: //ntc 4
                        MUXA_3=0; MUXA_2=0; MUXA_1=1; MUXA_0=1; break;
                    case 4: //ntc 5
                        MUXA_3=0; MUXA_2=1; MUXA_1=0; MUXA_0=0; break;
                    case 5: //ntc 6
                        MUXA_3=0; MUXA_2=1; MUXA_1=0; MUXA_0=1; break;
                    case 6: //ntc 7
                        MUXA_3=0; MUXA_2=1; MUXA_1=1; MUXA_0=0; break;
                    case 7: //ntc 8
                        MUXA_3=0; MUXA_2=1; MUXA_1=1; MUXA_0=1; break;
                    case 8: //ntc 9
                        MUXA_3=1; MUXA_2=0; MUXA_1=0; MUXA_0=0; break;
                    case 9: //ntc 10
                        MUXA_3=1; MUXA_2=0; MUXA_1=0; MUXA_0=1; break;
                    case 10: //ntc 11
                        MUXA_3=1; MUXA_2=0; MUXA_1=1; MUXA_0=0; break;
                    case 11: //ntc 12
                        MUXA_3=1; MUXA_2=0; MUXA_1=1; MUXA_0=1; break;
                    case 12: //ntc 13
                        MUXA_3=1; MUXA_2=1; MUXA_1=0; MUXA_0=0; break;
                    case 13: //ntc 14
                        MUXA_3=1; MUXA_2=1; MUXA_1=0; MUXA_0=1; break;
                    case 14: //ntc 15
                        MUXA_3=1; MUXA_2=1; MUXA_1=1; MUXA_0=0; break;
                    case 15: //ntc 16
                        MUXA_3=1; MUXA_2=1; MUXA_1=1; MUXA_0=1; break;
                    case 16: //ntc 17                             //from MUXB
                        MUXB_3=0; MUXB_2=0; MUXB_1=0; MUXB_0=0; break;
                    case 17: //ntc 18
                        MUXB_3=0; MUXB_2=0; MUXB_1=0; MUXB_0=1; break;
                    case 18: //ntc 19
                        MUXB_3=0; MUXB_2=0; MUXB_1=1; MUXB_0=0; break;
                    case 19: //ntc 20
                        MUXB_3=0; MUXB_2=0; MUXB_1=1; MUXB_0=1; break;
                    case 20: //ntc 21
                        MUXB_3=0; MUXB_2=1; MUXB_1=0; MUXB_0=0; break;
                    case 21: //ntc 22
                        MUXB_3=0; MUXB_2=1; MUXB_1=0; MUXB_0=1; break;
                    case 22: //ntc 23
                        MUXB_3=0; MUXB_2=1; MUXB_1=1; MUXB_0=0; break;
                    case 23: //ntc 24
                        MUXB_3=0; MUXB_2=1; MUXB_1=1; MUXB_0=1; break;
                    case 24: //ntc 25
                        MUXB_3=1; MUXB_2=0; MUXB_1=0; MUXB_0=0; break;
                    case 25: //ntc 26
                        MUXB_3=1; MUXB_2=0; MUXB_1=0; MUXB_0=1; break;
                    case 26: //ntc 27
                        MUXB_3=1; MUXB_2=0; MUXB_1=1; MUXB_0=0; break;
                    case 27: //ntc 28
                        MUXB_3=1; MUXB_2=0; MUXB_1=1; MUXB_0=1; break;
                    case 28: //ntc 29
                        MUXB_3=1; MUXB_2=1; MUXB_1=0; MUXB_0=0; break;
                    case 29: //ntc 30
                        MUXB_3=1; MUXB_2=1; MUXB_1=0; MUXB_0=1; break;
                    case 30: //ntc 31
                        MUXB_3=1; MUXB_2=1; MUXB_1=1; MUXB_0=0; break;
                    case 31: //ntc 32
                        MUXB_3=1; MUXB_2=1; MUXB_1=1; MUXB_0=1; break;
                }
                wait_ms(100); //tempo para a tensao á saida do mux estabilisar
            if(i<16){  // Converts and read the analog input value (value from 0.0 to 1.0)
             temp_codes[i] = MUXA_Read.read()*3300;
            }else{
             temp_codes[i] = MUXB_Read.read()*3300;    
            }       
            
        temp=temp_codes[i]/1000;
        temp=(temp*10000)/(3.3-temp);
        temp = 3380/log(temp/0.119228);
        temp_codes[i] = temp-273.15;
//            //--------------------------
//    if(i==0||i==1||i==2||i==3||i==4||i==5||i==6||i==7||i==8||i==9||i==10||i==11||i==14||i==30){
//       if(temp_codes[i]>23){
//       // if(temp_codes[i]>30||temp_codes[i]<-20){
//        //disable interrupts
//        alarm();//temperature alarm
//        //enable interrupts
//        } 
//    }
//            //--------------------------            
        }
        temps_left = 32;
}

void onMsgReceived()
{
    msgAvailable = true;
}


bool to_charge_or_not_to_charge=false;           // false = discharge
bool charging = false;
bool discharging = false;

void monitor()
{
    led = !led;
    if(to_charge_or_not_to_charge) {
        charging = 1;
        discharging = 0;
    } else {
        discharging = 1;
        charging = 0;
    }
}


uint8_t motostate=0;

int main()
{
    data data;
    //printf("starting\n\r");
    led =1;
    wait(1);
    pec_error();
    to_charge_or_not_to_charge=0;
    charging = 0;
    discharging = 1;
    ticker.attach(&monitor, 10);
    LTC6804_initialize();
    init_cfg();
//write configuration
    wakeup_sleep();
    __disable_irq();    // Disable Interrupts
    LTC6804_wrcfg(TOTAL_IC,tx_cfg);
    __enable_irq();
    wait(1);
//read configuration: may differ from written config
    wakeup_sleep();
    __disable_irq();
    err = LTC6804_rdcfg(TOTAL_IC,rx_cfg);
    __enable_irq();
    if (err == -1) {
        pec_error();
    }
    wait(0.5);
    wakeup_idle();
    __disable_irq();
    LTC6804_adcv();
    __enable_irq();
    wait_ms(10);
    wakeup_idle();
    __disable_irq();
    err = LTC6804_rdcv(0, TOTAL_IC,cell_codes);
    __enable_irq();
    if (err == -1) {
        pec_error();
    }
    can.frequency(1000000);                     // set bit rate to 1Mbps
    can.attach(&onMsgReceived);
    //print_cells2();
    while(1) {
        if(charging) {
            charging = 0;
            check_charging_voltage();
            check_temperatures();
            sender.attach(&message_trigger,0.1);
        }
        if(discharging) {
            discharging = 0;
            check_discharging_voltage();
            check_temperatures();
            sender.attach(&message_trigger,0.1);
        }
        if(to_send) {
            to_send=0;
            //-----------------1º send cell voltages
            
//------------------------------  
            if(cells_left>0){                
if(cells_left==1||cells_left==2||cells_left==3||cells_left==4||cells_left==5||cells_left==7||cells_left==8||cells_left==9||cells_left==10){
    if(cell_codes[0][cells_left-1]<30000||cell_codes[0][cells_left-1]>42000){
         //   if(cell_codes[0][cells_left-1]<0||cell_codes[0][cells_left-1]>70000){ //for debug
        __disable_irq();    // Disable Interrupts
         alarm('v');
        __enable_irq();
        }
    }
//------------------------------          
            
            txMsg.clear();
            txMsg.id = 13;     //BMS1=>ID:11; BMS2=>ID:12; BMS3=>ID:13.
            txMsg.len = 5;
            data.f[0] = cell_codes[0][cells_left-1]*0.0001;
            txMsg.data[0] = data.bytes[0];
            txMsg.data[1] = data.bytes[1];
            txMsg.data[2] = data.bytes[2];
            txMsg.data[3] = data.bytes[3];
            txMsg.data[4] = cells_left;
            cells_left--;
            if(!(can.write(txMsg))) {   //se nao conseguiu transmitir continua a tentar transmitir a tensão dessa celula
                pec_error();
                cells_left++;
                //to_send=1;
            }
            }

            //-----------------2º send cell temperatures    
  //          wait_ms(200);      falha se houver aqui um delay deste tamanho 
       
       if(temps_left>0){
//------------------------------
if(temps_left==1||temps_left==2||temps_left==3||temps_left==4||temps_left==5||
temps_left==6||temps_left==7||temps_left==8||temps_left==9||temps_left==10||
temps_left==11||temps_left==12||temps_left==15||temps_left==31){
       if(temp_codes[temps_left-1]>65||temp_codes[temps_left-1]<-20){   //4-49(ambiente)
     //if(temp_codes[temps_left-1]>25||temp_codes[temps_left-1]<-300){   //for debug
       // if(temp_codes[i]>30||temp_codes[i]<-20){
        __disable_irq();    // Disable Interrupts
        alarm('t');   //temperature alarm
        __enable_irq();
        } 
    }
//------------------------------            
            txMsg.clear();
            txMsg.id = 23;     //BMS1=>ID:21; BMS2=>ID:22; BMS3=>ID:23.
            txMsg.len = 5;
                 
            data.f[0] = temp_codes[temps_left-1];
           // data.f[0] = temp_codes[14];


            txMsg.data[0] = data.bytes[0];
            txMsg.data[1] = data.bytes[1];
            txMsg.data[2] = data.bytes[2];
            txMsg.data[3] = data.bytes[3];       
                        
            txMsg.data[4] = temps_left;
            temps_left--;
            if(!(can.write(txMsg))) {   //se nao conseguiu transmitir continua a tentar transmitir a tensão dessa celula
                pec_error();
                temps_left++;
                //to_send=1;
            }  
            }          

        }
        if(msgAvailable) {
            int len = can.read(rxMsg);
            if(rxMsg.id==9){
                motostate = rxMsg.data[0];
                //motostate: (0|0|0|0|0|0|to_charge_or_not_to_charge|key_switch)
                to_charge_or_not_to_charge=((motostate & 0b00000010)>>1);
                msgAvailable = false;
            }
        }
    }
}