478 lines
12 KiB
C
478 lines
12 KiB
C
#include "kit_data.h"
|
||
#include "kit_debug.h"
|
||
#include "bsp_task.h"
|
||
|
||
#include "iso_check.h"
|
||
#include "soc_calculate.h"
|
||
#include "adc_manager.h"
|
||
#include "gpio_manager.h"
|
||
#include "eeprom_manager.h"
|
||
#include "hv_adc_manager.h"
|
||
#include "table_comm.h"
|
||
|
||
//#include "drv_mcp3208.h"
|
||
#include "drv_ads8688.h"
|
||
|
||
#define CUR_FILTER_ENABLE (0u)
|
||
#define ADCIC_SAMPLE_CNT (20u)
|
||
#define MCP3208_SAMPLE_CNT (10u)
|
||
|
||
ADS8688_STATIC_INIT(ads8688, kSpiDev_2, kGpioType_ADC_Cs);
|
||
|
||
typedef enum
|
||
{
|
||
kAdIc_Hv1,
|
||
kAdIc_HvBat,
|
||
kAdIc_Cur,
|
||
kAdIc_HvIso,
|
||
kAdIc_HvIsoNagtive,
|
||
kAdIc_End
|
||
} AdIcEnum;
|
||
|
||
typedef struct
|
||
{
|
||
bool is_simulate;
|
||
uint8_t filter_pos;
|
||
uint8_t ad_buf_pos[kAdIc_End];
|
||
int16_t current;
|
||
uint16_t en_temp[kEnTemp_End];
|
||
int32_t can_current;
|
||
int16_t show_current;
|
||
#if CUR_FILTER_ENABLE
|
||
int16_t filter_current[MCP3208_SAMPLE_CNT];
|
||
#endif
|
||
int32_t value[kAdIc_End];
|
||
int32_t ad_avg[kAdIc_End];
|
||
int32_t ad_buf[kAdIc_End][ADCIC_SAMPLE_CNT];
|
||
|
||
} CurHvItem;
|
||
|
||
CurHvItem cur_hv_item;
|
||
|
||
typedef enum
|
||
{
|
||
kCurSensor_Shunt,
|
||
kCurSensor_SigHall,
|
||
kCurSensor_DualHall,
|
||
kCurSensor_SigHall_Base,
|
||
kCurSensor_End,
|
||
} CurSensorType;
|
||
|
||
typedef struct
|
||
{
|
||
int8_t dir;
|
||
CurSensorType type;
|
||
int16_t filter;
|
||
int16_t offset;
|
||
int32_t scale;
|
||
} CurProp;
|
||
|
||
typedef struct
|
||
{
|
||
uint8_t shunt_volt;
|
||
int8_t chg_cur_dir;
|
||
CurChannel channel;
|
||
int16_t swing_volt;
|
||
CurProp prop[kCurChannel_End];
|
||
} CurItem;
|
||
|
||
CurItem cur_item;
|
||
|
||
void bms_init_current(void)
|
||
{
|
||
cur_item.swing_volt = get_eeprom_data(kEep_HallSwingVolt, kEepromDataType_Full);
|
||
cur_item.shunt_volt = get_eeprom_data(kEep_ChgCurDir_ShuntRatedVolt, kEepromDataType_Low);
|
||
|
||
cur_item.prop[0].filter = cur_item.prop[1].filter = 0;
|
||
// 上位机下发时缩小10倍,分流器量程 乘了 10
|
||
cur_item.prop[0].scale = get_eeprom_data(kEep_CurSensor2_1Range, kEepromDataType_Low) * 10;
|
||
cur_item.prop[1].scale = get_eeprom_data(kEep_CurSensor2_1Range, kEepromDataType_High) * 10;
|
||
|
||
cur_item.prop[0].type = (CurSensorType)get_eeprom_data(kEep_CurSensor2_1Type, kEepromDataType_Low);
|
||
cur_item.prop[1].type = (CurSensorType)get_eeprom_data(kEep_CurSensor2_1Type, kEepromDataType_High);
|
||
|
||
cur_item.prop[0].offset = cur_item.prop[1].offset = 0;
|
||
// 电流方向
|
||
cur_item.chg_cur_dir = 1 - (int8_t)((get_eeprom_data(kEep_ChgCurDir_ShuntRatedVolt, kEepromDataType_High) & 0x01) << 1);
|
||
cur_item.prop[0].dir = 1 - (int8_t)((get_eeprom_data(kEep_CurSensor2_1Dir, kEepromDataType_High) & 0x01) << 1);
|
||
cur_item.prop[1].dir = 1 - (int8_t)((get_eeprom_data(kEep_CurSensor2_1Dir, kEepromDataType_Low) & 0x01) << 1);
|
||
}
|
||
|
||
void bms_adjust_cur(void)
|
||
{
|
||
uint32_t i;
|
||
int32_t cur, max_cur = INT32_MIN, min_cur = INT32_MAX;
|
||
|
||
for (i = 0; i < 20; i++)
|
||
{
|
||
bms_poll_adc(10);
|
||
cur = bms_poll_cur_hv(0);
|
||
if (cur > max_cur)
|
||
{
|
||
max_cur = cur;
|
||
}
|
||
|
||
if (cur < min_cur)
|
||
{
|
||
min_cur = cur;
|
||
}
|
||
|
||
kit_time_dly_ms(5);
|
||
}
|
||
|
||
cur = 0;
|
||
if ((min_cur > -500) && (max_cur < 500))
|
||
{
|
||
// 计算滤波 + 0.1A
|
||
cur = ((max_cur - min_cur) >> 1) + 10;
|
||
}
|
||
// 电流滤波单位 0.1A/bit 计算电流0.01A/bit 需要*10
|
||
cur_item.prop[0].filter = get_eeprom_data(kEep_ZeroFilter2_1Filter, kEepromDataType_Low) * 10;
|
||
cur_item.prop[1].filter = get_eeprom_data(kEep_ZeroFilter2_1Filter, kEepromDataType_High) * 10;
|
||
if (cur_item.prop[0].filter == 0)
|
||
{
|
||
cur_item.prop[0].filter = cur;
|
||
}
|
||
|
||
if (cur_item.prop[1].filter == 0)
|
||
{
|
||
cur_item.prop[1].filter = cur;
|
||
}
|
||
|
||
bsp_eeprom_set_data(kEep_ZeroFilter2_1Filter, cur / 10, kEepromDataType_Low);
|
||
bsp_eeprom_set_data(kEep_ZeroFilter2_1Filter, cur / 10, kEepromDataType_High);
|
||
|
||
cur = 0;
|
||
if ((min_cur > -500) && (max_cur < 500))
|
||
{
|
||
// 计算偏移
|
||
cur = ((max_cur + min_cur) >> 1);
|
||
}
|
||
// 电流偏移单位 0.1A/bit,偏移12A 计算电流0.01A/bit 需要*10
|
||
cur_item.prop[0].offset = ((int8_t)get_eeprom_data(kEep_CurSensor2_1Offset, kEepromDataType_Low)) * 10;
|
||
cur_item.prop[1].offset = ((int8_t)get_eeprom_data(kEep_CurSensor2_1Offset, kEepromDataType_High)) * 10;
|
||
|
||
if (cur_item.prop[0].offset == 0)
|
||
{
|
||
cur_item.prop[0].offset = cur;
|
||
}
|
||
|
||
if (cur_item.prop[1].offset == 0)
|
||
{
|
||
cur_item.prop[1].offset = cur;
|
||
}
|
||
|
||
bsp_eeprom_set_data(kEep_CurSensor2_1Offset, cur / 10, kEepromDataType_Low);
|
||
bsp_eeprom_set_data(kEep_CurSensor2_1Offset, cur / 10, kEepromDataType_High);
|
||
|
||
// 根据校准值再计算下电流
|
||
bms_poll_adc(10);
|
||
bms_poll_cur_hv(10);
|
||
}
|
||
|
||
// 分流器转换
|
||
uint32_t HighResCurTrans(int32_t voldata)
|
||
{
|
||
uint16_t Rsense = 39;
|
||
uint32_t highResCurdata = 0;
|
||
|
||
highResCurdata = voldata * Rsense * 100;//扩大100倍
|
||
|
||
return highResCurdata;
|
||
}
|
||
|
||
// 计算电流单位
|
||
int16_t bms_caculate_current(uint32_t base_time)
|
||
{
|
||
#if CUR_FILTER_ENABLE
|
||
static uint16_t dly = 0;
|
||
#endif
|
||
int32_t tmp, tmp1, current ,volval = 0;
|
||
CurProp *prop;
|
||
if (cur_item.channel < kCurChannel_End)
|
||
{
|
||
prop = &cur_item.prop[cur_item.channel];
|
||
switch (prop->type)
|
||
{
|
||
case kCurSensor_Shunt:
|
||
// 分流器 cur_hv_item.cur_volt_avg / cur_prop.shunt_volt * cur_prop.cur_scale;
|
||
current = (int32_t)cur_hv_item.value[kAdIc_Cur] * prop->scale / cur_item.shunt_volt;
|
||
//current = HighResCurTrans(cur_hv_item.value[kAdIc_Cur]);
|
||
break;
|
||
case kCurSensor_SigHall:
|
||
// 霍尔电流
|
||
tmp = bms_get_adc_data(kAdcData_Hall1);
|
||
if(tmp<20)tmp = 0;
|
||
volval = tmp * 3300 /4095;
|
||
//current = (int32_t)(tmp - 250000) * prop->scale / cur_item.swing_volt;
|
||
current = tmp;
|
||
break;
|
||
case kCurSensor_DualHall:
|
||
// 霍尔电流
|
||
tmp = bms_get_adc_data(kAdcData_Hall1);
|
||
volval = tmp * 3300 /4095;
|
||
//current = (int32_t)(tmp - 250000) * prop->scale / cur_item.swing_volt;
|
||
current = tmp;
|
||
if (KIT_ABS(current) > (int32_t)prop->scale * 90)
|
||
{
|
||
tmp = bms_get_adc_data(kAdcData_Hall2);
|
||
//current = (int32_t)(tmp - 250000) * cur_item.prop[1].scale / cur_item.swing_volt;
|
||
current = tmp;
|
||
}
|
||
break;
|
||
case kCurSensor_SigHall_Base:
|
||
// 单量程带基准
|
||
tmp = bms_get_adc_data(kAdcData_Hall1);
|
||
tmp1 = bms_get_adc_data(kAdcData_Hall2);
|
||
current = (int32_t)(tmp - tmp1) * prop->scale / cur_item.swing_volt;
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
//测试用 SFJ 7.30,2-18,注释
|
||
//current = volval * 100 / 10;
|
||
|
||
// 电流方向
|
||
current *= prop->dir;
|
||
// 零点偏移
|
||
current -= prop->offset;
|
||
// 零点滤波
|
||
if (KIT_ABS(current) < prop->filter)
|
||
{
|
||
current = 0;
|
||
}
|
||
current = (int64_t)current * get_eeprom_data(kEep_Hall1CalFactor, kEepromDataType_Full) / 1000;
|
||
|
||
//调试
|
||
bms_integral_soc(current, base_time);
|
||
|
||
cur_hv_item.current = current / 10;//转为 0.1
|
||
|
||
#if CUR_FILTER_ENABLE
|
||
dly += base_time;
|
||
if (dly >= 500)
|
||
{
|
||
dly = 0;
|
||
cur_hv_item.filter_current[cur_hv_item.filter_pos] = cur_hv_item.current;
|
||
if (++cur_hv_item.filter_pos >= MCP3208_SAMPLE_CNT)
|
||
{
|
||
cur_hv_item.filter_pos = 0;
|
||
}
|
||
cur_hv_item.show_current = kit_get_avg_filter_max_min(cur_hv_item.filter_current, MCP3208_SAMPLE_CNT) * cur_item.chg_cur_dir;
|
||
}
|
||
#else
|
||
cur_hv_item.show_current = cur_hv_item.current * cur_item.chg_cur_dir;
|
||
#endif
|
||
return current;
|
||
}
|
||
|
||
uint32_t HighVolTrans(uint16_t voldata)
|
||
{
|
||
// 10M 16.5K
|
||
float Rsense = 10000;
|
||
float Rvol = 16.5;
|
||
uint32_t highvoldata = 0;
|
||
|
||
highvoldata = voldata * (Rsense + Rvol) / Rvol;
|
||
|
||
return highvoldata;
|
||
}
|
||
|
||
|
||
AdjustValue adIc_adjust_value[kAdIc_End];
|
||
uint16_t adIc_reg_map[kAdIc_End] = {MAN_Ch_0, MAN_Ch_1, MAN_Ch_2, MAN_Ch_3, MAN_Ch_4};
|
||
|
||
|
||
void get_ad_sample(void)
|
||
{
|
||
static uint16_t outputdata[16] = {0};
|
||
int32_t i =0;
|
||
uint16_t ad =0;
|
||
|
||
#if ADC_AUTO_MODE
|
||
//auto scan mode
|
||
drv_enter_auto_rst_mode_Data(outputdata, 6);
|
||
#else
|
||
outputdata[i] = drv_get_ads8688_ch_data(MAN_Ch_0);
|
||
|
||
// i += 1;
|
||
// outputdata[i] = drv_get_ads8688_ch_data(MAN_Ch_1);
|
||
// i += 1;
|
||
// outputdata[i] = drv_get_ads8688_ch_data(MAN_Ch_2);
|
||
// i += 1;
|
||
// outputdata[i] = drv_get_ads8688_ch_data(MAN_Ch_3);
|
||
// i += 1;
|
||
// outputdata[i] = drv_get_ads8688_ch_data(MAN_Ch_4);
|
||
// i += 1;
|
||
// outputdata[i] = drv_get_ads8688_ch_data(MAN_Ch_5);
|
||
// i += 1;
|
||
#endif
|
||
|
||
for (i = 0; i < kAdIc_End; i++)
|
||
{
|
||
//ad = drv_get_ads8688_ch_data(adIc_reg_map[i]);
|
||
cur_hv_item.ad_buf[i][cur_hv_item.ad_buf_pos[i]++] = drv_ads8688_value(outputdata[i]);
|
||
ad = cur_hv_item.ad_avg[i] = kit_get_int32_avg_filter_max_min(cur_hv_item.ad_buf[i], ADCIC_SAMPLE_CNT);
|
||
|
||
if (i == kAdIc_HvIso)
|
||
{
|
||
//cur_hv_item.value[i] = HighVolTrans2(ad)/100;
|
||
bms_set_iso_volt_ad(kIsoVolt_Other, ad);
|
||
}
|
||
if(i == kAdIc_HvIsoNagtive)
|
||
{
|
||
|
||
}
|
||
if (i == kAdIc_HvBat)
|
||
{
|
||
cur_hv_item.value[i] = (376 * ad * 512 * 10 / (0x01 << 15)) / 100; //单位是mv
|
||
bms_set_iso_volt_ad(kIsoVolt_TotalVolt, cur_hv_item.value[i]);
|
||
}
|
||
if(i == kAdIc_Hv1)
|
||
{
|
||
cur_hv_item.value[i] = (376 * ad * 512 * 10 / (0x01 << 15)) / 100; //单位是mv
|
||
}
|
||
if(i == kAdIc_Cur)
|
||
{
|
||
ad = ad - adIc_adjust_value[i].zero;
|
||
ad = (ad * 5120 * 10 / (0x01 << 15)) / 82; //单位是mv
|
||
|
||
// 防止eeprom中没有设置电压校准系数
|
||
if (get_eeprom_data(kEep_Volt1CalFactor, kEepromDataType_Full) <= 900 || get_eeprom_data(kEep_Volt1CalFactor, kEepromDataType_Full) >= 1100)
|
||
{
|
||
bsp_eeprom_save_data(kEep_Volt1CalFactor, 1000, kEepromDataType_Full);
|
||
}
|
||
cur_hv_item.value[i] = ad ;/// 1000 * adIc_adjust_value[i].rate *get_eeprom_data(kEep_Volt1CalFactor, kEepromDataType_Full) / 1000;//转为V
|
||
}
|
||
|
||
if (cur_hv_item.ad_buf_pos[i] >= ADCIC_SAMPLE_CNT)
|
||
{
|
||
cur_hv_item.ad_buf_pos[i] = 0;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
int16_t bms_poll_cur_hv(uint32_t base_time)
|
||
{
|
||
get_ad_sample();
|
||
return bms_caculate_current(base_time);
|
||
}
|
||
|
||
// A
|
||
int16_t bms_get_current(void)
|
||
{
|
||
return cur_hv_item.current;
|
||
}
|
||
|
||
// 单位0.01A/bit
|
||
void bms_set_current(int32_t cur)
|
||
{
|
||
cur_hv_item.can_current = cur;
|
||
}
|
||
|
||
void bms_set_current_channel(CurChannel channel)
|
||
{
|
||
if (channel < kCurChannel_End)
|
||
{
|
||
cur_item.channel = channel;
|
||
}
|
||
}
|
||
|
||
int16_t bms_get_show_current(void)
|
||
{
|
||
return cur_hv_item.show_current;
|
||
}
|
||
|
||
// V
|
||
int16_t bms_get_high_volt(HvType type)
|
||
{
|
||
int16_t tmp = 0;
|
||
|
||
KIT_ASSERT_PARAM(type < kHvType_End);
|
||
|
||
if (type < kHvType_End)
|
||
{
|
||
tmp = cur_hv_item.value[type];
|
||
}
|
||
|
||
return tmp;
|
||
}
|
||
|
||
void bms_set_high_volt(HvType type, uint16_t value)
|
||
{
|
||
KIT_ASSERT_PARAM(type < kHvType_End);
|
||
|
||
if ((cur_hv_item.is_simulate == false) && (type < kHvType_End))
|
||
{
|
||
cur_hv_item.value[type + 3] = value;
|
||
}
|
||
}
|
||
|
||
void bms_set_sim_high_volt(HvType type, uint16_t value)
|
||
{
|
||
KIT_ASSERT_PARAM(type < kHvType_End);
|
||
|
||
if (type < kHvType_End)
|
||
{
|
||
cur_hv_item.is_simulate = true;
|
||
cur_hv_item.value[type] = value;
|
||
}
|
||
}
|
||
|
||
bool bms_is_high_volt_sim(void)
|
||
{
|
||
return cur_hv_item.is_simulate;
|
||
}
|
||
|
||
uint16_t bms_get_en_temp(EnTemp idx)
|
||
{
|
||
uint16_t tmp = 0;
|
||
if (idx < kEnTemp_End)
|
||
{
|
||
tmp = cur_hv_item.en_temp[idx];
|
||
}
|
||
return tmp;
|
||
}
|
||
|
||
void bms_set_en_temp(EnTemp idx, uint16_t temp)
|
||
{
|
||
if (idx < kEnTemp_End)
|
||
{
|
||
cur_hv_item.en_temp[idx] = temp;
|
||
}
|
||
}
|
||
|
||
const uint32_t adIc_default_rate[kAdIc_End] = {1, 1, 1, 1, 1};
|
||
|
||
//
|
||
void bms_init_cur_hv(void)
|
||
{
|
||
static uint8_t errcnt = 0;
|
||
uint32_t i = 0, cnt = 30;
|
||
#ifdef ADS_8688_EN
|
||
while(drv_ads8688_Init() && errcnt < 30)
|
||
{
|
||
errcnt++;
|
||
OSTimeDly(20);
|
||
}
|
||
|
||
for (i = 0; i < kAdIc_End; i++)
|
||
{
|
||
adIc_adjust_value[i].zero = 0;
|
||
adIc_adjust_value[i].rate = adIc_default_rate[i];
|
||
}
|
||
|
||
#endif
|
||
// 填充buf
|
||
for (i = 0; i < cnt; i++)
|
||
{
|
||
bms_poll_adc(10);
|
||
// 时间参数为0,防止时间增加误校准SOC
|
||
bms_poll_cur_hv(0);
|
||
bsp_task_delay_ms(100);
|
||
}
|
||
bms_init_current();
|
||
}
|