#include "iv_measure.h" #include "bsp/ml5238.h" #include "bsp/cs1180.h" #include "bsp/gd32_adc.h" #include "bsp/clock.h" /* measure the current & voltage for battery pack by using * ms5238 & cs1180(only used when bms is in small current loading) */ /* this is the inited gain set to the ms5238, but the really gain is calibrated * by measure_system_calibrate */ static float imon_gain_10x = 10.0f; static float imon_gain_50x = 50.0f; static float imon_gain_now; static float vim0_10x = 0.0f; static float vim0_50x = 0.0f; static float vim0_now; #define r_resistor 1.0f // 1ΊΑΕ· #define r_pcb_resistor 2.0f // pcb resistor static float r_sense = r_resistor + r_pcb_resistor; static float v_ref = 3300.0f; //adc ref = 3.3v static float max_adc = 65535.0f; static void __inline__ select_gain_10x(int select){ if (select){ ML5238_IMON_OUT_10X(); imon_gain_now = imon_gain_10x; vim0_now = vim0_10x; }else { ML5238_IMON_OUT_50X(); imon_gain_now = imon_gain_50x; vim0_now = vim0_50x; } } /*calibrate when startup && temperature is changed more than 5? degree * calibrate the ms5238's IMON output voltage gain */ void current_calibrate(void){ /* calibrate the 10x gain */ ML5238_IMON_OUT_ZERO_10X(); vim0_10x = adc_sample(ADC_CHAN_IMON ,TRUE); ML5238_IMON_OUT_V2000_10X(); float vim1 = adc_sample(ADC_CHAN_IMON, FALSE); ML5238_IMON_OUT_V100_10X(); float vr = adc_sample(ADC_CHAN_IMON, FALSE); imon_gain_10x = ML5238_GAIN(vim0_10x, vim1, vr); /* calibrate the 50x gain */ ML5238_IMON_OUT_ZERO_50X(); vim0_50x = adc_sample(ADC_CHAN_IMON ,TRUE); ML5238_IMON_OUT_V2000_50X(); vim1 = adc_sample(ADC_CHAN_IMON, FALSE); ML5238_IMON_OUT_V100_50X(); vr = adc_sample(ADC_CHAN_IMON, FALSE); imon_gain_50x = ML5238_GAIN(vim0_50x, vim1, vr); select_gain_10x(0);//default gain is 50x, if 50x overflow, use 10x } void measure_system_init(void){ adc_init(); ml5238_init(); cs1180_init(); current_calibrate(); } float get_imon_current(bool calibration){ float adc = adc_sample(ADC_CHAN_IMON, calibration); if (adc >= 0xFFF0){ //overflow, use 10x if (imon_gain_now == imon_gain_50x){ select_gain_10x(1); adc = adc_sample(ADC_CHAN_IMON, calibration); } } float cali_adc = ML5238_V_RSENSER(adc, vim0_now, imon_gain_now); return (cali_adc/max_adc) * v_ref / r_sense; } float get_vmon_voltage(int cell, bool calibration){ ml5238_select_cell_to_vmon(cell); delay_us(50); float adc = adc_sample(ADC_CHAN_VMON, calibration); return adc/max_adc * v_ref; }