iv_measure.c 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  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. /* measure the current & voltage for battery pack by using
  7. * ms5238 & cs1180(only used when bms is in small current loading)
  8. */
  9. /* this is the inited gain set to the ms5238, but the really gain is calibrated
  10. * by measure_system_calibrate
  11. */
  12. static float imon_gain_10x = 10.0f;
  13. static float imon_gain_50x = 50.0f;
  14. static float imon_gain_now;
  15. static float vim0_10x = 0.0f;
  16. static float vim0_50x = 0.0f;
  17. static float vim0_now;
  18. #define r_resistor 1.0f // 1ºÁÅ·
  19. #define r_pcb_resistor 2.0f // pcb resistor
  20. static float r_sense = r_resistor + r_pcb_resistor;
  21. static float v_ref = 3300.0f; //adc ref = 3.3v
  22. static float max_adc = 65535.0f;
  23. static void __inline__ select_gain_10x(int select){
  24. if (select){
  25. ML5238_IMON_OUT_10X();
  26. imon_gain_now = imon_gain_10x;
  27. vim0_now = vim0_10x;
  28. }else {
  29. ML5238_IMON_OUT_50X();
  30. imon_gain_now = imon_gain_50x;
  31. vim0_now = vim0_50x;
  32. }
  33. }
  34. /*calibrate when startup && temperature is changed more than 5? degree
  35. * calibrate the ms5238's IMON output voltage gain
  36. */
  37. void current_calibrate(void){
  38. /* calibrate the 10x gain */
  39. ML5238_IMON_OUT_ZERO_10X();
  40. vim0_10x = adc_sample(ADC_CHAN_IMON ,TRUE);
  41. ML5238_IMON_OUT_V2000_10X();
  42. float vim1 = adc_sample(ADC_CHAN_IMON, FALSE);
  43. ML5238_IMON_OUT_V100_10X();
  44. float vr = adc_sample(ADC_CHAN_IMON, FALSE);
  45. imon_gain_10x = ML5238_GAIN(vim0_10x, vim1, vr);
  46. /* calibrate the 50x gain */
  47. ML5238_IMON_OUT_ZERO_50X();
  48. vim0_50x = adc_sample(ADC_CHAN_IMON ,TRUE);
  49. ML5238_IMON_OUT_V2000_50X();
  50. vim1 = adc_sample(ADC_CHAN_IMON, FALSE);
  51. ML5238_IMON_OUT_V100_50X();
  52. vr = adc_sample(ADC_CHAN_IMON, FALSE);
  53. imon_gain_50x = ML5238_GAIN(vim0_50x, vim1, vr);
  54. select_gain_10x(0);//default gain is 50x, if 50x overflow, use 10x
  55. }
  56. void measure_system_init(void){
  57. adc_init();
  58. ml5238_init();
  59. cs1180_init();
  60. current_calibrate();
  61. }
  62. float get_imon_current(bool calibration){
  63. float adc = adc_sample(ADC_CHAN_IMON, calibration);
  64. if (adc >= 0xFFF0){
  65. //overflow, use 10x
  66. if (imon_gain_now == imon_gain_50x){
  67. select_gain_10x(1);
  68. adc = adc_sample(ADC_CHAN_IMON, calibration);
  69. }
  70. }
  71. float cali_adc = ML5238_V_RSENSER(adc, vim0_now, imon_gain_now);
  72. return (cali_adc/max_adc) * v_ref / r_sense;
  73. }
  74. float get_vmon_voltage(int cell, bool calibration){
  75. ml5238_select_cell_to_vmon(cell);
  76. delay_us(50);
  77. float adc = adc_sample(ADC_CHAN_VMON, calibration);
  78. return adc/max_adc * v_ref;
  79. }