iv_measure.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. #include "iv_measure.h"
  2. #include "bsp/ml5238.h"
  3. #include "bsp/cs1180.h"
  4. #include "bsp/gd32_adc.h"
  5. #include "bsp/clock.h"
  6. #include "bsp/gpio.h"
  7. #include "bsp/temp_lookup_tab.h"
  8. /* measure the temp & current & voltage for battery pack by using
  9. * ms5238 & cs1180(only used when bms is in small current loading)
  10. */
  11. /* this is the inited gain set to the ms5238, but the really gain is calibrated
  12. * by measure_system_calibrate
  13. */
  14. static float imon_gain_10x = 10.0f;
  15. static float imon_gain_50x = 50.0f;
  16. static float imon_gain_now;
  17. static float vim0_10x = 0.0f;
  18. static float vim0_50x = 0.0f;
  19. static float vim0_now;
  20. #define r_resistor 1.0f // 1ºÁÅ·
  21. #define r_pcb_resistor 0.0f // pcb resistor
  22. static const float r_sense = r_resistor + r_pcb_resistor;
  23. static const float v_ref = 3300.0f; //adc ref = 3.3v
  24. static const float max_adc = 65535.0f;
  25. static const float small_cur_r_sense = 360.0f;//mo
  26. static void __inline__ select_gain_10x(int select){
  27. if (select){
  28. ML5238_IMON_OUT_10X();
  29. imon_gain_now = imon_gain_10x;
  30. vim0_now = vim0_10x;
  31. }else {
  32. ML5238_IMON_OUT_50X();
  33. imon_gain_now = imon_gain_50x;
  34. vim0_now = vim0_50x;
  35. }
  36. }
  37. static int __inline__ _is_x10_gain(void){
  38. return imon_gain_now == imon_gain_10x;
  39. }
  40. /*calibrate when startup && temperature is changed more than 5? degree
  41. * calibrate the ms5238's IMON output voltage gain
  42. */
  43. void current_calibrate(void){
  44. /* calibrate the 10x gain */
  45. ML5238_IMON_OUT_ZERO_10X();
  46. vim0_10x = adc_sample(ADC_CHAN_IMON ,TRUE);
  47. ML5238_IMON_OUT_V2000_10X();
  48. float vim1 = adc_sample(ADC_CHAN_IMON, FALSE);
  49. ML5238_IMON_OUT_V100_10X();
  50. float vr = adc_sample(ADC_CHAN_IMON, FALSE);
  51. imon_gain_10x = ML5238_GAIN(vim0_10x, vim1, vr);
  52. /* calibrate the 50x gain */
  53. ML5238_IMON_OUT_ZERO_50X();
  54. vim0_50x = adc_sample(ADC_CHAN_IMON ,TRUE);
  55. ML5238_IMON_OUT_V2000_50X();
  56. vim1 = adc_sample(ADC_CHAN_IMON, FALSE);
  57. ML5238_IMON_OUT_V100_50X();
  58. vr = adc_sample(ADC_CHAN_IMON, FALSE);
  59. imon_gain_50x = ML5238_GAIN(vim0_50x, vim1, vr);
  60. select_gain_10x(0);//default gain is 50x, if 50x overflow, use 10x
  61. }
  62. void measure_system_init(void){
  63. adc_init();
  64. ml5238_init();
  65. cs1180_init();
  66. current_calibrate();
  67. }
  68. /* get battery pack's current (mA) */
  69. float get_imon_current(int calibration){
  70. float adc = adc_sample(ADC_CHAN_IMON, calibration);
  71. if (adc >= 0xFFF0 && (!_is_x10_gain())){//overflow, use 10x gain
  72. select_gain_10x(1);
  73. adc = adc_sample(ADC_CHAN_IMON, calibration);
  74. }else if (adc <= 0x1F && (_is_x10_gain())){// is too small, select 50x gain
  75. select_gain_10x(0);
  76. adc = adc_sample(ADC_CHAN_IMON, calibration);
  77. }
  78. float cali_adc = ML5238_V_RSENSER(adc, vim0_now, imon_gain_now);
  79. return (cali_adc / max_adc) * v_ref / r_sense * 1000;
  80. }
  81. /* get cell's voltage (mV) */
  82. float get_vmon_voltage(int cell, int calibration){
  83. ml5238_select_cell_to_vmon(cell);
  84. delay_us(50);
  85. float adc = adc_sample(ADC_CHAN_VMON, calibration);
  86. return (adc / max_adc) * v_ref * 1000;
  87. }
  88. /* get battery pack's aux current (mA) */
  89. float get_small_current(int calibration){
  90. float adc = adc_sample(ADC_CHAN_AUX_CURR, calibration);
  91. return (adc / max_adc * v_ref) / small_cur_r_sense * 1000;
  92. }
  93. int get_pcb_temperature(int calibration){
  94. TEMP_OPEN(1);
  95. delay_us(100);
  96. uint16_t adc = adc_sample(ADC_CHAN_TEMPERATURE_4, calibration);
  97. TEMP_OPEN(0);
  98. return get_temp_by_adc(adc);
  99. }
  100. /*
  101. * index : 0...2
  102. */
  103. int get_pack_temperature(int index, int calibration){
  104. TEMP_OPEN(1);
  105. delay_us(100);
  106. uint16_t adc = adc_sample(ADC_CHAN_TEMPERATURE_1 + index, calibration);
  107. TEMP_OPEN(0);
  108. return get_temp_by_adc(adc);
  109. }