| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341 |
- #include "measure.h"
- #include "bsp/ml5238.h"
- #include "bsp/cs1180.h"
- #include "bsp/gd32_adc.h"
- #include "bsp/clock.h"
- #include "bsp/gpio.h"
- #include "bsp/temp_lookup_tab.h"
- #include "bsp/shark_bsp.h"
- #include "libs/logger.h"
- #include "Least_Square.h"
- #include "app/sox/state.h"
- /* measure the temp & current & voltage for battery pack by using
- * ms5238 & cs1180(only used when bms is in small current loading)
- */
- /*
- 1. 小电流
- cs1180(32x):0.305-0.315, 0.277-0.286, 0.255-0.264, 0.220-0.228, 0.184-0.190, 0.137-0.142, 0.062-0.064, 0.011-0.009:0.012
- ml5289(50x):0.307-0.313:0.330,0.277-0.275:0.290,0.254-0.251:0.271,0.221-0.208:0.253,0.183-0.170:0.196,0.136-0.121:0.155,0.061-0.072:0.096, 0.011-0.033:0.060
- 2. 大电流
- cs1180(32x):1.861-2.082
- ml5238(50x):1.869-1.865-1.890
- */
- /* 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;
- static linear_ceoff_t ml5238_10x_ceoff = {.Ka = 1.0f, .Cb = 0.0f};
- static linear_ceoff_t ml5238_50x_ceoff = {.Ka = 1.0f, .Cb = 0.0f};
- static linear_ceoff_t ml5238_now_ceoff;
- static linear_ceoff_t cs1180_ceoff = {.Ka = 1.0f, .Cb = 0.0f};
- #define gain_default_50x 1
- #define CS1180_MAX_CURRENT 4500 //MA, cs1180的最大电流,超过这个使用ML5238
- #define r_pcb_resistor 0.0f // pcb resistor
- static const float r_sense = r_resistor + r_pcb_resistor;
- static const float v_gd_ref = 3300.0f; //adc ref = 3.3v
- static const float max_gd_adc = 4095.0f;//65536.0f;
- static const float v_cs1180_ref = 1235.0f;//cs1180 vref = 1.235v
- static const float max_cs1180_adc = 0x7FFFF;//
- static const float small_cur_r_sense = 0.360f;//欧姆
- uint32_t check_gain_error = 0;
- static u64 check_gain_time = 0;
- u32 dgain_switch_count = 0;
- u32 cgain_switch_count = 0;
- static least_square_t adc_cali[2]; // y = ax + b
- #define GD32_ADC_READ_TIMES 128
- static int __inline__ is_x10_gain(void){
- return imon_gain_now == imon_gain_10x;
- }
- static int __inline__ is_x50_gain(void){
- return imon_gain_now == imon_gain_50x;
- }
- static void __inline__ check_gain(void){
- int count = 5;
- while (is_x10_gain() && !ML5238_IS_10X()){
- ML5238_IMON_OUT_10X();
- check_gain_error ++;
- if (count-- <= 0) {
- break;
- }
- }
- count = 5;
- while (is_x50_gain() && !ML5238_IS_50X()){
- ML5238_IMON_OUT_50X();
- check_gain_error ++;
- if (count-- <= 0) {
- break;
- }
- }
- }
- static void __inline__ _select_gain_10x(int select){
- if (select){
- ML5238_IMON_OUT_10X();
- imon_gain_now = imon_gain_10x;
- vim0_now = vim0_10x;
- ml5238_now_ceoff = ml5238_10x_ceoff;
- }else {
- ML5238_IMON_OUT_50X();
- imon_gain_now = imon_gain_50x;
- vim0_now = vim0_50x;
- ml5238_now_ceoff = ml5238_50x_ceoff;
- }
- check_gain();
- }
- static void __inline select_gain_10x(void) {
- _select_gain_10x(1);
- }
- static void __inline select_gain_50x(void) {
- _select_gain_10x(0);
- }
- float get_ml5238_gain(void){
- return imon_gain_now;
- }
- float get_ml5238_vos(void){
- return vim0_now;
- }
- static void current_10x_calibrate(void){
- /* calibrate the 10x gain */
- ML5238_IMON_OUT_ZERO_10X();
- vim0_10x = adc_sample_avg(ADC_CHAN_IMON, GD32_ADC_READ_TIMES);
- #if 0
- ML5238_IMON_OUT_V2000_10X();
- float vim1 = adc_sample_avg(ADC_CHAN_IMON, GD32_ADC_READ_TIMES);
- ML5238_IMON_OUT_V100_10X();
- float vr = adc_sample_avg(ADC_CHAN_IMON, GD32_ADC_READ_TIMES);
- imon_gain_10x = ML5238_GAIN(vim0_10x, vim1, vr);
- #else
- imon_gain_10x = 10.0f;
- #endif
- }
- static void current_50x_calibrate(void){
- /* calibrate the 50x gain */
- ML5238_IMON_OUT_ZERO_50X();
- vim0_50x = adc_sample_avg(ADC_CHAN_IMON, GD32_ADC_READ_TIMES);
- #if 0
- ML5238_IMON_OUT_V2000_50X();
- float vim1 = adc_sample_avg(ADC_CHAN_IMON, GD32_ADC_READ_TIMES);
- ML5238_IMON_OUT_V20_50X();
- float vr = adc_sample_avg(ADC_CHAN_IMON, GD32_ADC_READ_TIMES);
- imon_gain_50x = ML5238_GAIN(vim0_50x, vim1, vr) * 0.948f;
- #else
- imon_gain_50x = 50.0f;
- #endif
- }
- /*calibrate when startup && temperature is changed more than 5? degree
- * calibrate the ms5238's IMON output voltage gain
- */
- void current_calibrate(void){
- current_10x_calibrate();
- current_50x_calibrate();
- #ifdef gain_default_50x
- select_gain_50x();
- #else
- select_gain_10x();
- #endif
- }
- void measure_adc_init(void){
- ml5238_init();
- gd32_adc_init();
- current_calibrate();
- cs1180_adc_init();
- }
- static float get_current_by_ml5238(void){
- float adc = adc_sample_avg(ADC_CHAN_IMON, GD32_ADC_READ_TIMES);
- float cali_adc = ML5238_V_RSENSER(adc, vim0_now, imon_gain_now);
- return (int)((cali_adc / max_gd_adc) * v_gd_ref / r_sense * 1000);
- }
- /* get battery pack's current (mA) */
- static float get_pack_current_by_gd(void){
- static u64 debounce_change_10xgain = 0;
- static u64 debounce_change_50xgain = 0;
- u64 time_now = shark_get_mseconds();
- if (time_now - check_gain_time >= 1000) {
- check_gain();
- check_gain_time = time_now;
- }
- float adc = adc_sample_avg(ADC_CHAN_IMON, GD32_ADC_READ_TIMES);
- if (is_x10_gain()) { //is x10 gian
- debounce_change_50xgain = shark_get_mseconds();
- if ((adc < vim0_now) && (vim0_now - adc) <= 200) { //charging below about 16A, changed to 50x gain
- select_gain_50x();
- adc = adc_sample_avg(ADC_CHAN_IMON, GD32_ADC_READ_TIMES);
- cgain_switch_count ++;
- }else if (adc > vim0_now) { //discharging below about 20A, changed to 50x gain(after 5s, avoid change gain freqencely)
- if ((adc - vim0_now) <= 250) {
- if ((shark_get_mseconds() - debounce_change_10xgain) >= 5*1000) {
- select_gain_50x();
- adc = adc_sample_avg(ADC_CHAN_IMON, GD32_ADC_READ_TIMES);
- debounce_change_10xgain = shark_get_mseconds();
- dgain_switch_count ++;
- }
- }else {
- debounce_change_10xgain = shark_get_mseconds();
- }
- }
- }else { //is x50 gain
- debounce_change_10xgain = shark_get_mseconds();
- if (vim0_now - adc >= 1120){//charging >= 18A, full is 1241(20A)
- select_gain_10x();
- adc = adc_sample_avg(ADC_CHAN_IMON, GD32_ADC_READ_TIMES);
- cgain_switch_count ++;
- }else if (adc - vim0_now >= 2170) { //discharing >= 35A, full is 2850(46A)
- if ((shark_get_mseconds() - debounce_change_50xgain) >= 500) { //after 500ms
- select_gain_10x();
- adc = adc_sample_avg(ADC_CHAN_IMON, GD32_ADC_READ_TIMES);
- debounce_change_50xgain = shark_get_mseconds();
- dgain_switch_count ++;
- }
- }else {
- debounce_change_50xgain = shark_get_mseconds();
- }
- }
- float cali_adc = ML5238_V_RSENSER(adc, vim0_now, imon_gain_now);
- return (int)((cali_adc / max_gd_adc) * v_gd_ref / r_sense * 1000);
- }
- static float get_pack_current_by_cs1180(int *valid){
- float adc = cs1180_adc_sample(valid);
- float vol = (adc / max_cs1180_adc) * v_cs1180_ref;
- return (vol / r_sense) * 1000 - 5.0f;//板子固定5MA,cs1180无法测量到
- }
- static __inline__ float get_caliberated_current(linear_ceoff_t *cof, float x) {
- return (x * cof->Ka) + cof->Cb;
- }
- float get_pack_current(int *current_5238){
- float current = get_pack_current_by_gd();
- current = get_caliberated_current(&ml5238_now_ceoff, current);
- if (current_5238 != NULL){
- *current_5238 = (int)current;
- }
- if (cs1180_change_gain(current) == 1) {
- int valid = 1;
- float cs1180_current = get_pack_current_by_cs1180(&valid);
- if (valid == 1) {
- current = get_caliberated_current(&cs1180_ceoff, cs1180_current);
- }
- }
- return current;
- }
- /* get cell's voltage (mV) */
- float get_cell_voltage(int cell){
- ML5238_SELECT_CELL(cell);
- delay_us(100);
- float adc = adc_sample_avg(ADC_CHAN_VMON, GD32_ADC_READ_TIMES);
- return cell_real_vol((adc / max_gd_adc) * v_gd_ref);
- }
- /* get battery pack's aux current (MA) */
- float get_small_current(void){
- float adc = adc_sample_avg(ADC_CHAN_AUX_CURR, 16);
- return ((adc / max_gd_adc * v_gd_ref)) / small_cur_r_sense;
- }
- /* 用来判断小电流的情况下,电压小于某一个值认为小电流真正短路,比如16v*/
- float get_small_current_voltage(void){
- float s_current_a = get_small_current();//MA
- return s_current_a * (small_cur_r_sense + SMALL_CURRENT_R);//28欧姆是mos的D极两个56的并联
- }
- int get_pcb_temperature(void){
- TEMP_OPEN(1);
- delay_us(100);
- uint16_t adc = adc_sample_avg(ADC_CHAN_TEMPERATURE_4, 8);
- TEMP_OPEN(0);
- return get_temp_by_adc(adc);
- }
- /*
- * index : 0...3, 3 indicat pcb temp
- */
- int get_pack_temperature(int index){
- TEMP_OPEN(1);
- delay_us(100);
- uint16_t adc = adc_sample_avg(ADC_CHAN_TEMPERATURE_1 + index, 8);
- TEMP_OPEN(0);
- return get_temp_by_adc((adc<<4)&0xFFFF);
- }
- int measure_start_cali(uint8_t adc, uint8_t gain, uint8_t samples){
- bms_work_mode_set(WORK_MODE_CALIBRATE, 1);
- least_square_init(&adc_cali[adc], samples);
- sys_debug("start cali %d, %d, %d\n", adc, gain, samples);
- if (adc == GD32_ADC) {
- if (gain == 10) {
- select_gain_10x();
- }else if (gain == 50) {
- select_gain_50x();
- }else {
- return 0;
- }
- return 1;
- }
- return 1;
- }
- int measure_continue_cali(uint8_t adc, uint16_t voltage, int16_t current) {
- float x = 0;
- float y = current;
- sys_debug("continue cali %d, %d, %d\n", adc, voltage, current);
- if (adc == GD32_ADC) {
- x = get_current_by_ml5238();
- }else {
- x = get_pack_current_by_cs1180(NULL);
- }
- least_square_put(&adc_cali[adc], x, y);
- return 1;
- }
- int measure_stop_cali(uint8_t adc, uint8_t gain){
- bms_work_mode_set(WORK_MODE_CALIBRATE, 0);
- sys_debug("continue stop %d, %d\n", adc, gain);
- if (adc_cali[adc].finished ) {
- if (adc == GD32_ADC) {
- if (gain == 10) {
- ml5238_10x_ceoff = adc_cali[adc].coeff;
- }else if (gain == 50) {
- ml5238_50x_ceoff = adc_cali[adc].coeff;
- }
- }else {
- cs1180_ceoff = adc_cali[adc].coeff;
- }
- sys_debug("stop %f, %f\n", adc_cali[adc].coeff.Ka, adc_cali[adc].coeff.Cb);
- }
- select_gain_50x();
- return adc_cali[adc].finished;
- }
|