measure.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. #include "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. #include "bsp/shark_bsp.h"
  9. /* measure the temp & current & voltage for battery pack by using
  10. * ms5238 & cs1180(only used when bms is in small current loading)
  11. */
  12. /* this is the inited gain set to the ms5238, but the really gain is calibrated
  13. * by measure_system_calibrate
  14. */
  15. static float imon_gain_10x = 10.0f;
  16. static float imon_gain_50x = 50.0f;
  17. static float imon_gain_now;
  18. static float vim0_10x = 0.0f;
  19. static float vim0_50x = 0.0f;
  20. static float vim0_now;
  21. #define gain_default_50x 1
  22. #define r_pcb_resistor 0.0f // pcb resistor
  23. static const float r_sense = r_resistor + r_pcb_resistor;
  24. static const float v_gd_ref = 3300.0f; //adc ref = 3.3v
  25. static const float max_gd_adc = 65535.0f;
  26. static const float v_cs1180_ref = 1235.0f;//cs1180 vref = 1.235v
  27. static const float max_cs1180_adc = 0x7FFFF;//
  28. static const float small_cur_r_sense = 360.0f;//mo
  29. static uint8_t adc_used = GD32_ADC;////CS1180_ADC;
  30. static void __inline__ select_gain_10x(int select){
  31. if (select){
  32. ML5238_IMON_OUT_10X();
  33. imon_gain_now = imon_gain_10x;
  34. vim0_now = vim0_10x;
  35. }else {
  36. ML5238_IMON_OUT_50X();
  37. imon_gain_now = imon_gain_50x;
  38. vim0_now = vim0_50x;
  39. }
  40. }
  41. static int __inline__ _is_x10_gain(void){
  42. return imon_gain_now == imon_gain_10x;
  43. }
  44. static void current_10x_calibrate(void){
  45. /* calibrate the 10x gain */
  46. ML5238_IMON_OUT_ZERO_10X();
  47. vim0_10x = adc_sample_avg(ADC_CHAN_IMON, 10);
  48. ML5238_IMON_OUT_V2000_10X();
  49. float vim1 = adc_sample_avg(ADC_CHAN_IMON, 10);
  50. ML5238_IMON_OUT_V100_10X();
  51. float vr = adc_sample_avg(ADC_CHAN_IMON, 10);
  52. imon_gain_10x = ML5238_GAIN(vim0_10x, vim1, vr);
  53. }
  54. static void current_50x_calibrate(void){
  55. /* calibrate the 50x gain */
  56. ML5238_IMON_OUT_ZERO_50X();
  57. vim0_50x = adc_sample_avg(ADC_CHAN_IMON, 10);
  58. ML5238_IMON_OUT_V2000_50X();
  59. float vim1 = adc_sample_avg(ADC_CHAN_IMON, 10);
  60. ML5238_IMON_OUT_V100_50X();
  61. float vr = adc_sample_avg(ADC_CHAN_IMON, 10);
  62. imon_gain_50x = ML5238_GAIN(vim0_50x, vim1, vr);
  63. }
  64. /*calibrate when startup && temperature is changed more than 5? degree
  65. * calibrate the ms5238's IMON output voltage gain
  66. */
  67. void current_calibrate(void){
  68. #ifdef gain_default_50x
  69. current_50x_calibrate();
  70. select_gain_10x(0);
  71. #else
  72. current_10x_calibrate();
  73. select_gain_10x(1);
  74. #endif
  75. }
  76. void measure_system_init(void){
  77. ml5238_init();
  78. adc_init();
  79. cs1180_adc_init();
  80. current_calibrate();
  81. }
  82. /* get battery pack's current (mA) */
  83. static float get_pack_current_by_gd(void){
  84. float adc = adc_sample_avg(ADC_CHAN_IMON, 10);
  85. if (adc >= 0xFFF0 && (!_is_x10_gain())){//overflow, use 10x gain
  86. current_10x_calibrate();
  87. select_gain_10x(1);
  88. adc = adc_sample_avg(ADC_CHAN_IMON, 10);
  89. }else if (adc <= 0x1F && (_is_x10_gain())){// is too small, select 50x gain
  90. current_50x_calibrate();
  91. select_gain_10x(0);
  92. adc = adc_sample_avg(ADC_CHAN_IMON, 10);
  93. }
  94. float cali_adc = ML5238_V_RSENSER(adc, vim0_now, imon_gain_now);
  95. return (cali_adc / max_gd_adc) * v_gd_ref / r_sense * 1000;
  96. }
  97. static float get_pack_current_by_cs1180(void){
  98. float adc = cs1180_adc_sample();
  99. return (adc / max_cs1180_adc) * v_cs1180_ref / r_sense * 1000;
  100. }
  101. float get_pack_current(void){
  102. if (adc_used == CS1180_ADC){
  103. return get_pack_current_by_cs1180();
  104. }
  105. return get_pack_current_by_gd();
  106. }
  107. /*
  108. * select the gd32 internel adc or cs1180 adc
  109. */
  110. void adc_select_for_pack_current(int adc){
  111. if (adc != GD32_ADC && adc != CS1180_ADC){
  112. return;
  113. }
  114. adc_used = adc;
  115. }
  116. /* get cell's voltage (mV) */
  117. float get_cell_voltage(int cell){
  118. ML5238_SELECT_CELL(cell);
  119. delay_us(100);
  120. float adc = adc_sample_avg(ADC_CHAN_VMON, 34);
  121. return cell_real_vol((adc / max_gd_adc) * v_gd_ref);
  122. }
  123. /* get battery pack's aux current (mA) */
  124. float get_small_current(void){
  125. float adc = adc_sample(ADC_CHAN_AUX_CURR, TRUE);
  126. return (adc / max_gd_adc * v_gd_ref) / small_cur_r_sense * 1000;
  127. }
  128. int get_pcb_temperature(void){
  129. TEMP_OPEN(1);
  130. delay_us(100);
  131. uint16_t adc = adc_sample(ADC_CHAN_TEMPERATURE_4, TRUE);
  132. TEMP_OPEN(0);
  133. return get_temp_by_adc(adc);
  134. }
  135. /*
  136. * index : 0...2
  137. */
  138. int get_pack_temperature(int index){
  139. TEMP_OPEN(1);
  140. delay_us(100);
  141. uint16_t adc = adc_sample(ADC_CHAN_TEMPERATURE_1 + index, TRUE);
  142. TEMP_OPEN(0);
  143. return get_temp_by_adc(adc);
  144. }