forked from gary/BCU
2
0
Fork 0
BCU/app/stm32fxxx_app/app/hv_adc_manager.c

478 lines
12 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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();
}