00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00068 #include <intrinsics.h>
00069 #include <string.h>
00070 #include <stdio.h>
00071
00072 #include "MSP430.h"
00073 #include "main.h"
00074 #include "bq_pack.h"
00075 #include "spi_if.h"
00076 #include "data_flash.h"
00077 #include "USBCDC_constructs.h"
00078 #include "Common\types.h"
00079 #include "Common\hal_macros.h"
00080
00081
00082
00083
00084
00085
00086 bq_pack_t bq_pack;
00087
00088 unsigned char HOST_CONTROL_IN = 0;
00089
00090
00091
00092
00093
00094 static unsigned short cell_values[NUMBER_OF_CELLS];
00095
00102 short bq_pack_address_discovery(void)
00103 {
00104 unsigned short i, n;
00105 unsigned char reg_val[2];
00106
00107 i=NUMBER_OF_BQ_DEVICES;
00108 while (i>0)
00109 {
00110
00111 bq_dev_write_reg(BROADCAST_ADDR, RESET_REG, BQ76PL536_RESET);
00112
00113 n=0;
00114 while (n<NUMBER_OF_BQ_DEVICES)
00115 {
00116
00117 bq_dev_read_reg(DISCOVERY_ADDR, DEVICE_STATUS_REG, 1, DISCARD_CRC, reg_val);
00118
00119
00120 if (reg_val[0] & (1<<7))
00121 {
00122 n = NUMBER_OF_BQ_DEVICES;
00123 }
00124 else
00125 {
00126
00127
00128
00129 n++;
00130 bq_pack.bq_devs[n-1].device_address = n;
00131
00132
00133 bq_dev_write_reg(DISCOVERY_ADDR, ADDRESS_CONTROL_REG, n);
00134
00135
00136 bq_dev_read_reg(n, ADDRESS_CONTROL_REG, 1, DISCARD_CRC, reg_val);
00137 if ((reg_val[0]&0x3F) == n)
00138 {
00139
00140 if (n==NUMBER_OF_BQ_DEVICES)
00141 return n;
00142 }
00143 else
00144 {
00145
00146 n = NUMBER_OF_BQ_DEVICES;
00147 }
00148 }
00149 }
00150
00151 i--;
00152 }
00153
00154 return 0;
00155 }
00156
00164 short bq_pack_init(void)
00165 {
00166 unsigned char i;
00167
00168 for (i=0; i<NUMBER_OF_BQ_DEVICES; i++)
00169 {
00170
00171 bq_pack.bq_devs[i].cell_count = MAX_CELLS_NUMBER_IN_BQ;
00172
00173
00174 conf_bq_dev(&bq_pack.bq_devs[i]);
00175
00176
00177 init_bq_dev_data_structure(&bq_pack.bq_devs[i]);
00178
00179
00180 bq_dev_read_cell_voltage(&bq_pack.bq_devs[i]);
00181 }
00182
00183 bq_pack.op_mode = FAULT_MODE;
00184 bq_pack.error_status = 0;
00185 bq_pack.voltage = 0;
00186 bq_pack.timer_status = 0;
00187 bq_pack.eoc_eod_timer = 0;
00188 bq_pack.charge_taper_timer = 0;
00189 bq_pack.chg_dschg_op_timer = 0;
00190 bq_pack.balancing_timer = 0;
00191 bq_pack.max_balance_timer = 0;
00192 bq_pack.last_imbalanced_cell_idx = 0;
00193 bq_pack.cell_imbalance_fail_timer = 0;
00194
00195 update_op_mode(INITIAL_MODE);
00196 return 0;
00197 }
00198
00199
00207 void update_bq_pack_data(void)
00208 {
00209 unsigned char i, cell_cnt;
00210 unsigned short stack_voltage = 0;
00211
00212 for (i=0; i<NUMBER_OF_BQ_DEVICES; i++)
00213 {
00214
00215 bq_dev_read_status(&bq_pack.bq_devs[i]);
00216
00217
00218 bq_dev_read_cell_voltage(&bq_pack.bq_devs[i]);
00219
00220
00221 if (i == 0)
00222 {
00223 bq_pack.lowest_cell_volts = bq_pack.bq_devs[i].cell_voltage[0];
00224 bq_pack.highest_cell_volts = bq_pack.bq_devs[i].cell_voltage[0];
00225 }
00226
00227 for (cell_cnt=0; cell_cnt<bq_pack.bq_devs[i].cell_count; cell_cnt++)
00228 {
00229 stack_voltage += bq_pack.bq_devs[i].cell_voltage[cell_cnt];
00230
00231 if (bq_pack.bq_devs[i].cell_voltage[cell_cnt]
00232 < bq_pack.lowest_cell_volts)
00233 {
00234 bq_pack.lowest_cell_volts = bq_pack.bq_devs[i].cell_voltage[cell_cnt];
00235 }
00236 else if (bq_pack.bq_devs[i].cell_voltage[cell_cnt]
00237 > bq_pack.highest_cell_volts)
00238 {
00239 bq_pack.highest_cell_volts = bq_pack.bq_devs[i].cell_voltage[cell_cnt];
00240 }
00241 }
00242
00243
00244 bq_dev_read_errors(&bq_pack.bq_devs[i]);
00245
00246
00247 bq_dev_read_temps(&bq_pack.bq_devs[i]);
00248 }
00249
00250
00251 bq_pack.voltage = stack_voltage;
00252
00253 return;
00254 }
00255
00262 void bq_pack_start_conv(void)
00263 {
00264
00265 bq_dev_write_reg(BROADCAST_ADDR, ADC_CONVERT_REG, ADC_CONVERT_VAL);
00266
00267 }
00268
00275 void CheckFaultConditions(void)
00276 {
00277
00278 if (check_for_pot() || check_for_cov())
00279 {
00280 bq_pack.error_status |= STATUS_ERROR_POT_COV;
00281
00282
00283 update_op_mode(FAULT_MODE);
00284
00285 }
00286
00287 if (check_for_cuv())
00288 {
00289 bq_pack.error_status |= STATUS_ERROR_CUV;
00290
00291
00292 update_op_mode(FAULT_MODE);
00293 }
00294 }
00295
00296
00303 void CheckChargeDischargeModes(void)
00304 {
00305
00306 if (bq_pack.timer_status & START_CHG_DSCHG_OP_TIMER)
00307 {
00308 if (bq_pack.chg_dschg_op_timer >= (get_u32_value(CHARGE_DISCHARGE_TIME)))
00309 {
00310 if (check_for_charge_op())
00311 {
00312
00313 update_op_mode(CHARGE_OP);
00314 }
00315 else if (check_for_discharge_op())
00316 {
00317
00318 update_op_mode(DISCHARGE_OP);
00319 }
00320
00321
00322 bq_pack.chg_dschg_op_timer = 0;
00323
00324
00325 copy_cell_voltage_values();
00326 }
00327 }
00328 }
00329
00337 #if CELL_BALANCING_EN
00338 void CellBalancing(void)
00339 {
00340
00341 unsigned short dev_id;
00342
00343
00344 if (bq_pack.timer_status & START_CELL_BALANCE_TIMER)
00345 {
00346
00347
00348 if (HOST_CONTROL_IN & IN_HOST_CHG_OP)
00349 {
00350
00351 if (bq_pack.balancing_timer >= (get_u32_value(BALANCE_TIME)-2))
00352 {
00353
00354 if ((bq_pack.highest_cell_volts - bq_pack.lowest_cell_volts) >=
00355 get_u32_value(BALANCE_VOLTS_THRESHOLD))
00356 {
00357
00358 for (dev_id=0; dev_id<NUMBER_OF_BQ_DEVICES; dev_id++)
00359 {
00360
00361 enable_bypass_resistor(dev_id, (~find_imbalanced_cell(dev_id)));
00362
00363 }
00364
00365 bq_pack.balancing_timer = 0;
00366
00367 }
00368 else
00369 {
00370
00371
00372 bq_pack.timer_status &= ~START_CELL_BALANCE_TIMER;
00373
00374
00375 disable_all_bypass_resistors();
00376 }
00377 }
00378
00379 if (bq_pack.max_balance_timer > get_u32_value(MAX_BALANCE_TIME))
00380 {
00381
00382 bq_pack.error_status |= STATUS_ERROR_MAX_BALANCE_TIME;
00383 update_op_mode(SOV_MODE);
00384 }
00385
00386
00387 if(bq_pack.cell_imbalance_fail_timer
00388 > get_u32_value(CELL_IMBALANCE_FAIL_TIME))
00389 {
00390
00391 bq_pack.error_status |= STATUS_ERROR_IMBALANCE_FAIL;
00392 update_op_mode(SOV_MODE);
00393 }
00394 }
00395 else
00396 {
00397
00398 bq_pack.timer_status &= ~START_CELL_BALANCE_TIMER;
00399
00400 bq_pack.balancing_timer=0;
00401 bq_pack.max_balance_timer=0;
00402 bq_pack.cell_imbalance_fail_timer=0;
00403
00404
00405 disable_all_bypass_resistors();
00406 }
00407 }
00408 else
00409 {
00410
00411 if (HOST_CONTROL_IN & IN_HOST_CHG_OP)
00412 {
00413
00414 if (((bq_pack.highest_cell_volts - bq_pack.lowest_cell_volts) >=
00415 get_u32_value(BALANCE_VOLTS_THRESHOLD)))
00416 {
00417
00418 if(bq_pack.lowest_cell_volts > get_u32_value(MIN_BALANCE_VOLTS))
00419 {
00420
00421 bq_pack.timer_status |= START_CELL_BALANCE_TIMER;
00422
00423 bq_pack.balancing_timer = 0;
00424 bq_pack.max_balance_timer = 0;
00425 bq_pack.cell_imbalance_fail_timer = 0;
00426
00427
00428 for (dev_id=0; dev_id<NUMBER_OF_BQ_DEVICES; dev_id++)
00429 {
00430
00431 enable_bypass_resistor(dev_id, (~find_imbalanced_cell(dev_id)));
00432
00433 }
00434 }
00435 }
00436 }
00437 }
00438 }
00439 #endif
00440
00448 void CheckEndOfChargeOrDischargeModes(void)
00449 {
00450
00451 if (bq_pack.op_mode < FAULT_MODE)
00452 {
00453 if (bq_pack.voltage < get_u32_value(PACK_END_OF_DISCHARGE_VOLTAGE))
00454 {
00455 update_op_mode(END_OF_DISCHARGE);
00456
00457 }
00458 else if (bq_pack.voltage > get_u32_value(PACK_END_OF_CHARGE_VOLTAGE))
00459 {
00460 update_op_mode(END_OF_CHARGE);
00461
00462 }
00463 }
00464 }
00465
00472 void BatteryPackManager(void)
00473 {
00474
00475 CheckFaultConditions();
00476 CheckChargeDischargeModes();
00477 CheckEndOfChargeOrDischargeModes();
00478 #if CELL_BALANCING_EN
00479 CellBalancing();
00480 #endif
00481
00482 }
00483
00490 unsigned short get_bq_pack_voltage(void)
00491 {
00492 return bq_pack.voltage;
00493 }
00494
00502 unsigned short get_bq_pack_timer(void)
00503 {
00504 return bq_pack.eoc_eod_timer;
00505 }
00506
00513 void update_bq_pack_timer(void)
00514 {
00515 if (bq_pack.timer_status & START_END_OF_CHG_DSCHG_TIMER)
00516 {
00517 bq_pack.eoc_eod_timer++;
00518 }
00519
00520 if (bq_pack.timer_status & START_CHARGE_TAPER_TIMER)
00521 {
00522 bq_pack.charge_taper_timer++;
00523 }
00524
00525
00526 if (bq_pack.timer_status & START_CHG_DSCHG_OP_TIMER)
00527 {
00528 bq_pack.chg_dschg_op_timer++;
00529 }
00530
00531
00532 #if CELL_BALANCING_EN
00533 if (bq_pack.timer_status & START_CELL_BALANCE_TIMER)
00534 {
00535 bq_pack.balancing_timer++;
00536 bq_pack.max_balance_timer++;
00537
00538
00539
00540 if (cell_imbalance_threshold_reached())
00541 {
00542 bq_pack.cell_imbalance_fail_timer++;
00543 }
00544 else
00545 {
00546 bq_pack.cell_imbalance_fail_timer = 0;
00547 }
00548 }
00549 #endif
00550
00551 return;
00552 }
00553
00554
00561 op_modes_t get_bq_pack_mode(void)
00562 {
00563 return bq_pack.op_mode;
00564 }
00565
00566 void set_bq_pack_mode(op_modes_t mode)
00567 {
00568 bq_pack.op_mode = mode;
00569
00570 return;
00571 }
00572
00573
00574
00575
00576
00583 void conf_bq_dev(bq_dev_t* this)
00584 {
00585 unsigned short temp;
00586
00587 bq_dev_write_reg(this->device_address, ADC_CONTROL_REG, ADC_CONTROL_VAL_6);
00588
00589 bq_dev_write_reg(this->device_address, IO_CONTROL_REG, IO_CONTROL_VAL);
00590
00591 bq_dev_write_reg(this->device_address, CB_CTRL_REG, CB_CTRL_VAL);
00592 bq_dev_write_reg(this->device_address, CB_TIME_REG, CB_TIME_VAL);
00593
00594 bq_dev_write_reg(this->device_address, SHDW_CTRL_REG, SHDW_CTRL_ACCESS_EN_VAL);
00595
00596 bq_dev_write_reg(this->device_address, FUNCTION_CONFIG_REG, FUNC_CONFIG_VAL_6);
00597
00598 bq_dev_write_reg(this->device_address, SHDW_CTRL_REG, SHDW_CTRL_ACCESS_EN_VAL);
00599 bq_dev_write_reg(this->device_address, IO_CONFIG_REG, IO_CONFIG_VAL);
00600
00601 temp = get_u32_value(COV_THRESHOLD);
00602 if (temp > 2000)
00603 temp = (temp - 2000)/50;
00604 else
00605 temp = 0;
00606
00607 bq_dev_write_reg(this->device_address, SHDW_CTRL_REG, SHDW_CTRL_ACCESS_EN_VAL);
00608 bq_dev_write_reg(this->device_address, CONFIG_COV_REG, CONFIG_COV_VAL | temp);
00609 bq_dev_write_reg(this->device_address, SHDW_CTRL_REG, SHDW_CTRL_ACCESS_EN_VAL);
00610 bq_dev_write_reg(this->device_address, CONFIG_COVT_REG,
00611 CONFIG_COVT_VAL | COV_TIME);
00612
00613 temp = get_u32_value(CUV_THRESHOLD);
00614 if (temp > 700)
00615 temp = (temp - 700)/100;
00616 else
00617 temp = 13;
00618 bq_dev_write_reg(this->device_address, SHDW_CTRL_REG, SHDW_CTRL_ACCESS_EN_VAL);
00619
00620 bq_dev_write_reg(this->device_address, CONFIG_CUV_REG, CONFIG_CUV_VAL | temp);
00621 bq_dev_write_reg(this->device_address, SHDW_CTRL_REG, SHDW_CTRL_ACCESS_EN_VAL);
00622 bq_dev_write_reg(this->device_address, CONFIG_CUVT_REG, CONFIG_CUVT_VAL
00623 | CUV_TIME);
00624
00625 bq_dev_write_reg(this->device_address, SHDW_CTRL_REG, SHDW_CTRL_ACCESS_EN_VAL);
00626
00627 bq_dev_write_reg(this->device_address, CONFIG_OT_REG, CONFIG_OT_VAL);
00628 bq_dev_write_reg(this->device_address, SHDW_CTRL_REG, SHDW_CTRL_ACCESS_EN_VAL);
00629
00630 bq_dev_write_reg(this->device_address, CONFIG_OTT_REG, CONFIG_OTT_VAL);
00631
00632 return;
00633 }
00634
00642 void init_bq_dev_data_structure(bq_dev_t* this)
00643 {
00644 bq_dev_read_reg(this->device_address, DEVICE_STATUS_REG, 1, DISCARD_CRC,
00645 (unsigned char*) &this->device_status);
00646
00647 bq_dev_read_reg(this->device_address, TEMPERATURE1_L_REG, 2, DISCARD_CRC,
00648 (unsigned char*) &this->temperature1);
00649 bq_dev_read_reg(this->device_address, TEMPERATURE2_L_REG, 2, DISCARD_CRC,
00650 (unsigned char*) &this->temperature2);
00651
00652
00653 bq_dev_read_reg(this->device_address, ALERT_STATUS_REG, 1, DISCARD_CRC,
00654 (unsigned char*) &this->alert_status);
00655 bq_dev_read_reg(this->device_address, FAULT_STATUS_REG, 1, DISCARD_CRC,
00656 (unsigned char*) &this->fault_status);
00657 bq_dev_read_reg(this->device_address, COV_FAULT_REG, 1, DISCARD_CRC,
00658 (unsigned char*) &this->cov_fault);
00659 bq_dev_read_reg(this->device_address, CUV_FAULT_REG, 1, DISCARD_CRC,
00660 (unsigned char*) &this->cuv_fault);
00661
00662
00663 bq_dev_clear_alerts(this);
00664 bq_dev_clear_faults(this);
00665
00666 return;
00667 }
00668
00669
00676 short bq_dev_read_cell_voltage(bq_dev_t* this)
00677 {
00678 unsigned char* pPtr;
00679 unsigned char temp;
00680 short i, ret_val;
00681 unsigned long voltage_comput;
00682
00683 ret_val = bq_dev_read_reg(this->device_address, VCELL1_L_REG,
00684 (MAX_CELLS_NUMBER_IN_BQ<<1) , DISCARD_CRC,
00685 (unsigned char *) &this->cell_voltage[0]);
00686
00687 for (i=0; i<MAX_CELLS_NUMBER_IN_BQ; i++)
00688 {
00689
00690 pPtr = (unsigned char *)(&this->cell_voltage[i]);
00691 temp = *pPtr;
00692 *(pPtr) = *(pPtr+1);
00693 *(pPtr+1) = temp;
00694
00695
00696 voltage_comput = this->cell_voltage[i] * (unsigned long)(adc_step_mul);
00697 this->cell_voltage[i] = voltage_comput/((unsigned long)(adc_step_div));
00698 }
00699
00700 return ret_val;
00701 }
00702
00703
00704
00711 void bq_dev_clear_alerts(bq_dev_t* this)
00712 {
00713 unsigned char Value;
00714
00715
00716 bq_dev_read_reg(this->device_address, DEVICE_STATUS_REG, 1, DISCARD_CRC,
00717 (unsigned char*) &Value);
00718 Value |= BIT5;
00719
00720 bq_dev_write_reg(this->device_address, DEVICE_STATUS_REG, Value);
00721 Value &= ~BIT5;
00722
00723 bq_dev_write_reg(this->device_address, DEVICE_STATUS_REG, Value);
00724
00725
00726 bq_dev_read_reg(this->device_address, ALERT_STATUS_REG, 1, DISCARD_CRC,
00727 (unsigned char*) &Value);
00728
00729 bq_dev_write_reg(this->device_address, ALERT_STATUS_REG, Value);
00730
00731 Value = 0x00;
00732
00733 bq_dev_write_reg(this->device_address, ALERT_STATUS_REG, Value);
00734
00735 }
00736
00737
00744 void bq_dev_clear_faults(bq_dev_t* this)
00745 {
00746 unsigned char Value;
00747
00748
00749 bq_dev_read_reg(this->device_address, DEVICE_STATUS_REG, 1, DISCARD_CRC,
00750 (unsigned char*) &Value);
00751 Value |= BIT6;
00752
00753 bq_dev_write_reg(this->device_address, DEVICE_STATUS_REG, Value);
00754 Value &= ~BIT6;
00755
00756 bq_dev_write_reg(this->device_address, DEVICE_STATUS_REG, Value);
00757
00758
00759 bq_dev_read_reg(this->device_address, FAULT_STATUS_REG, 1, DISCARD_CRC,
00760 (unsigned char*) &Value);
00761
00762 bq_dev_write_reg(this->device_address, FAULT_STATUS_REG, Value);
00763
00764 Value = 0x00;
00765
00766 bq_dev_write_reg(this->device_address, FAULT_STATUS_REG, Value);
00767
00768
00769 }
00770
00771
00779 short bq_dev_read_errors(bq_dev_t* this)
00780 {
00781 bq_dev_read_reg(this->device_address, DEVICE_STATUS_REG, 1, DISCARD_CRC,
00782 (unsigned char*) &this->device_status);
00783 bq_dev_read_reg(this->device_address, ALERT_STATUS_REG, 1, DISCARD_CRC,
00784 (unsigned char*) &this->alert_status);
00785 bq_dev_read_reg(this->device_address, FAULT_STATUS_REG, 1, DISCARD_CRC,
00786 (unsigned char*) &this->fault_status);
00787 bq_dev_read_reg(this->device_address, COV_FAULT_REG, 1, DISCARD_CRC,
00788 (unsigned char*) &this->cov_fault);
00789 bq_dev_read_reg(this->device_address, CUV_FAULT_REG, 1, DISCARD_CRC,
00790 (unsigned char*) &this->cuv_fault);
00791
00792 return 0;
00793 }
00794
00795
00802 short bq_dev_read_temps(bq_dev_t* this)
00803 {
00804 unsigned char data[2];
00805
00806
00807 bq_dev_read_reg(this->device_address, TEMPERATURE1_L_REG, 2, DISCARD_CRC,
00808 (unsigned char*) &data[0]);
00809 this->temperature1 = ((data[0] << 8) | data[1]);
00810 bq_dev_read_reg(this->device_address, TEMPERATURE2_L_REG, 2, DISCARD_CRC,
00811 (unsigned char*) &data[0]);
00812 this->temperature2 = ((data[0] << 8) | data[1]);
00813
00814 return 0;
00815 }
00816
00817
00824 short bq_dev_read_status(bq_dev_t* this)
00825 {
00826 return bq_dev_read_reg(this->device_address, DEVICE_STATUS_REG, 1,
00827 DISCARD_CRC, (unsigned char*) &this->device_status);
00828 }
00829
00830
00837 void update_op_mode(op_modes_t new_mode)
00838 {
00839
00840 if (bq_pack.op_mode == new_mode)
00841 return;
00842
00843 bq_pack.op_mode = new_mode;
00844
00845 switch (new_mode)
00846 {
00847 case CHARGE_OP:
00848
00849 strcpy(OutputString,"\r\nThe battery pack is in CHARGE_OP Mode\r\n");
00850 #ifdef USB_COMM
00851
00852 sendData_waitTilDone((BYTE*)OutputString,strlen(OutputString),1,10);
00853 #endif
00854 #ifdef UART_COMM
00855
00856 putsUART((BYTE*)OutputString,strlen(OutputString));
00857 #endif
00858
00859 break;
00860
00861 case END_OF_CHARGE:
00862
00863 strcpy(OutputString,"\r\nThe battery pack is in END_OF_CHARGE Mode\r\n");
00864 #ifdef USB_COMM
00865
00866 sendData_waitTilDone((BYTE*)OutputString,strlen(OutputString),1,10);
00867 #endif
00868 #ifdef UART_COMM
00869
00870 putsUART((BYTE*)OutputString,strlen(OutputString));
00871 #endif
00872
00873 break;
00874
00875 case DISCHARGE_OP:
00876
00877 strcpy(OutputString,"\r\nThe battery pack is in DISCHARGE_OP Mode\r\n");
00878 #ifdef USB_COMM
00879
00880 sendData_waitTilDone((BYTE*)OutputString,strlen(OutputString),1,10);
00881 #endif
00882 #ifdef UART_COMM
00883
00884 putsUART((BYTE*)OutputString,strlen(OutputString));
00885 #endif
00886
00887 break;
00888
00889 case END_OF_DISCHARGE:
00890
00891 strcpy(OutputString,"\r\nThe battery pack is in END_OF_DISCHARGE Mode\r\n");
00892 #ifdef USB_COMM
00893
00894 sendData_waitTilDone((BYTE*)OutputString,strlen(OutputString),1,10);
00895 #endif
00896 #ifdef UART_COMM
00897
00898 putsUART((BYTE*)OutputString,strlen(OutputString));
00899 #endif
00900
00901 break;
00902
00903 case FAULT_MODE:
00904
00905 strcpy(OutputString,"\r\nThe battery pack is in FAULT_MODE Mode\r\n");
00906 #ifdef USB_COMM
00907
00908 sendData_waitTilDone((BYTE*)OutputString,strlen(OutputString),1,10);
00909 #endif
00910 #ifdef UART_COMM
00911
00912 putsUART((BYTE*)OutputString,strlen(OutputString));
00913 #endif
00914
00915
00916 bq_pack.timer_status &= ~START_CELL_BALANCE_TIMER;
00917 break;
00918
00919 case SOV_MODE:
00920
00921 strcpy(OutputString,"\r\nThe battery pack is in SOV_MODE Mode\r\n");
00922 #ifdef USB_COMM
00923
00924 sendData_waitTilDone((BYTE*)OutputString,strlen(OutputString),1,10);
00925 #endif
00926 #ifdef UART_COMM
00927
00928 putsUART((BYTE*)OutputString,strlen(OutputString));
00929 #endif
00930
00931 bq_pack.timer_status &= ~START_CELL_BALANCE_TIMER;
00932 break;
00933
00934 case INITIAL_MODE:
00935
00936
00937 bq_pack.error_status = 0;
00938
00939
00940 bq_pack.chg_dschg_op_timer = 0;
00941
00942
00943 bq_pack.timer_status |= START_CHG_DSCHG_OP_TIMER;
00944
00945
00946 BQ76PL536_DRDY_PxIE &= ~IN_BQ_DRDY;
00947
00948
00949 bq_pack_start_conv();
00950
00951
00952 while(!(BQ76PL536_DRDY_PxIN & IN_BQ_DRDY))
00953 ;
00954
00955
00956 update_bq_pack_data();
00957
00958 copy_cell_voltage_values();
00959
00960
00961 BQ76PL536_DRDY_PxIFG &= ~IN_BQ_DRDY;
00962 BQ76PL536_DRDY_PxIE |= IN_BQ_DRDY;
00963
00964
00965 strcpy(OutputString,"\r\nThe battery pack is in INITIAL_MODE Mode\r\n");
00966 #ifdef USB_COMM
00967
00968 sendData_waitTilDone((BYTE*)OutputString,strlen(OutputString),1,10);
00969 #endif
00970 #ifdef UART_COMM
00971
00972 putsUART((BYTE*)OutputString,strlen(OutputString));
00973 #endif
00974
00975 break;
00976
00977
00978 default:
00979 break;
00980 }
00981
00982 return;
00983 }
00984
00985
00992 short check_for_cov(void)
00993 {
00994
00995 unsigned short i, cell;
00996
00997 for (i=0; i<NUMBER_OF_BQ_DEVICES; i++)
00998 {
00999 if (bq_pack.bq_devs[i].fault_status & (1<<FAULT_COV_POS))
01000 {
01001
01002 for (cell=0; cell < bq_pack.bq_devs[i].cell_count; cell++)
01003 {
01004 if (bq_pack.bq_devs[i].cov_fault & (1<<cell))
01005 {
01006 if (bq_pack.bq_devs[i].cell_voltage[cell]
01007 > get_u32_value(COV_RECOVERY_THRESHOLD))
01008 {
01009
01010 return 1;
01011 }
01012 else
01013 {
01014
01015
01016 bq_dev_write_reg(bq_pack.bq_devs[i].device_address,
01017 FAULT_STATUS_REG, (1<<FAULT_COV_POS));
01018 bq_dev_write_reg(bq_pack.bq_devs[i].device_address,
01019 FAULT_STATUS_REG, (0<<FAULT_COV_POS));
01020
01021
01022 update_op_mode(INITIAL_MODE);
01023 }
01024 }
01025 }
01026 }
01027 }
01028
01029 return 0;
01030 }
01031
01032
01039 short check_for_cuv(void)
01040 {
01041 unsigned short i, cell;
01042
01043 for (i=0; i<NUMBER_OF_BQ_DEVICES; i++)
01044 {
01045 if (bq_pack.bq_devs[i].fault_status & (1<<FAULT_CUV_POS))
01046 {
01047
01048 for (cell=0; cell < bq_pack.bq_devs[i].cell_count; cell++)
01049 {
01050 if (bq_pack.bq_devs[i].cuv_fault & (1<<cell))
01051 {
01052 if (bq_pack.bq_devs[i].cell_voltage[cell]
01053 < get_u32_value(CUV_RECOVERY_THRESHOLD))
01054 {
01055
01056 return 1;
01057 }
01058 else
01059 {
01060
01061
01062 bq_dev_write_reg(bq_pack.bq_devs[i].device_address,
01063 FAULT_STATUS_REG, (1<<FAULT_CUV_POS));
01064 bq_dev_write_reg(bq_pack.bq_devs[i].device_address,
01065 FAULT_STATUS_REG, (0<<FAULT_CUV_POS));
01066
01067
01068 update_op_mode(INITIAL_MODE);
01069 }
01070 }
01071 }
01072 }
01073 }
01074
01075 return 0;
01076 }
01077
01078
01085 short check_for_pot(void)
01086 {
01087
01088 if (bq_pack.bq_devs[0].alert_status & (0x3<<ALERT_OT1_POS))
01089 {
01090 return 1;
01091 }
01092
01093 return 0;
01094 }
01095
01096
01104 unsigned short check_for_charge_op(void)
01105 {
01106 unsigned short i, j, cell_cnt;
01107
01108 j=0;
01109 for (i=0; i<NUMBER_OF_BQ_DEVICES; i++)
01110 {
01111
01112 for (cell_cnt=0; cell_cnt<bq_pack.bq_devs[i].cell_count; cell_cnt++)
01113 {
01114 if (bq_pack.bq_devs[i].cell_voltage[cell_cnt] > cell_values[j])
01115 {
01116 if ((bq_pack.bq_devs[i].cell_voltage[cell_cnt] - cell_values[j])
01117 > get_u32_value(DELTA_CHARGE_V))
01118 {
01119 return 1;
01120 }
01121 }
01122 j++;
01123 }
01124 }
01125
01126 return 0;
01127 }
01128
01129
01137 unsigned short check_for_discharge_op(void)
01138 {
01139 unsigned short i, j, cell_cnt;
01140
01141 j=0;
01142 for (i=0; i<NUMBER_OF_BQ_DEVICES; i++)
01143 {
01144
01145 for (cell_cnt=0; cell_cnt<bq_pack.bq_devs[i].cell_count; cell_cnt++)
01146 {
01147 if (cell_values[j] > bq_pack.bq_devs[i].cell_voltage[cell_cnt])
01148 {
01149 if ((cell_values[j] - bq_pack.bq_devs[i].cell_voltage[cell_cnt])
01150 > get_u32_value(DELTA_DISCHARGE_V))
01151 {
01152 return 1;
01153 }
01154 }
01155 j++;
01156 }
01157 }
01158
01159 return 0;
01160 }
01161
01162
01169 void copy_cell_voltage_values(void)
01170 {
01171 unsigned short i, j, cell_cnt;
01172
01173 j = 0;
01174 for (i=0; i<NUMBER_OF_BQ_DEVICES; i++)
01175 {
01176
01177 for (cell_cnt=0; cell_cnt<bq_pack.bq_devs[i].cell_count; cell_cnt++)
01178 {
01179 cell_values[j++] = bq_pack.bq_devs[i].cell_voltage[cell_cnt];
01180 }
01181 }
01182
01183 return;
01184 }
01185
01186
01193 unsigned short cell_imbalance_threshold_reached(void)
01194 {
01195 if ((bq_pack.highest_cell_volts - bq_pack.lowest_cell_volts)
01196 > get_u32_value(CELL_IMBALANCE_FAIL_THRESHOLD))
01197 return 1;
01198 else
01199 return 0;
01200 }
01201
01209 unsigned short find_imbalanced_cell(unsigned short in_dev_id)
01210 {
01211 unsigned short cell_id, imb_cells_mask, cnt;
01212
01213 cnt = 0;
01214 imb_cells_mask = 0xFFFF;
01215
01216
01217 for (cell_id=0; cell_id<bq_pack.bq_devs[in_dev_id].cell_count; cell_id++)
01218 {
01219 imb_cells_mask &= ~(1<<cnt);
01220
01221 if ((bq_pack.highest_cell_volts
01222 - bq_pack.bq_devs[in_dev_id].cell_voltage[cell_id]) >=
01223 get_u32_value(BALANCE_VOLTS_THRESHOLD))
01224 {
01225 imb_cells_mask |= (1<<cnt);
01226 }
01227 cnt++;
01228 }
01229
01230 return imb_cells_mask;
01231 }
01232
01239 void enable_bypass_resistor(unsigned short in_dev_id, unsigned short in_value)
01240 {
01241 bq_dev_write_reg(bq_pack.bq_devs[in_dev_id].device_address,
01242 CB_TIME_REG, get_u32_value(BALANCE_TIME));
01243 bq_dev_write_reg(bq_pack.bq_devs[in_dev_id].device_address,
01244 CB_CTRL_REG, (0x003F & in_value));
01245
01246 return;
01247 }
01248
01249
01256 void disable_bypass_resistor(unsigned short in_dev_id, unsigned short in_value)
01257 {
01258 unsigned char reg_val;
01259
01260 bq_dev_read_reg(bq_pack.bq_devs[in_dev_id].device_address, CB_CTRL_REG, 1,
01261 DISCARD_CRC, (unsigned char*) ®_val);
01262
01263
01264 reg_val &= ~(in_value);
01265 bq_dev_write_reg(bq_pack.bq_devs[in_dev_id].device_address,
01266 CB_CTRL_REG, reg_val);
01267
01268 return;
01269 }
01270
01271
01279 void disable_all_bypass_resistors(void)
01280 {
01281 unsigned short bq_dev_id;
01282
01283 for (bq_dev_id=0; bq_dev_id<NUMBER_OF_BQ_DEVICES; bq_dev_id++)
01284 {
01285 bq_dev_write_reg(bq_pack.bq_devs[bq_dev_id].device_address, CB_CTRL_REG, 0);
01286 }
01287
01288 return;
01289 }
01290
01291
01292
01293