📄 charge.c
字号:
}
if (Jkmk.temp[24] == 1)
{
SetVoltaget();
return;
}
#endif
#ifdef HARD_XK
Jkmk.temp[25] = step;
#endif
switch (step)
{
case 0://floating charge
//set voltage current limit
ChargeTimerStop(3); //停止均充保护计时器
ChargeTimerStop(5); //停止转均充延时计时器
ChargeTimerPlay(2); // 运行均充周期计时器
#ifdef HARD_XK
X_SetChargeState(1);
X_Charge();
#endif
break;
case 1://floating charge to equipoise charge
//set voltage current limit
ChargeTimerStart(5); //启动转均充延时计时器
#ifdef HARD_XK
X_SetChargeState(1);
#endif
break;
case 2://equipoise charge
//set voltage current limit
ChargeTimerStop(5); //停止转均充延时计时器
ChargeTimerStart(3); //启动均充保护计时器
#ifdef HARD_XK
X_SetChargeState(1);
#endif
break;
case 3://equipoise charge to floating charge
//set voltage current limit
ChargeTimerStart(4); //启动稳流均充计时器
#ifdef HARD_XK
X_SetChargeState(1);
#endif
break;
case 4://discharge power cut
//启动停电计时器
//set voltage current limit
Jkmk.ao_cfg[0] = Jkmk.mk_cfg[6];
break;
case 5://batt test
ChargeTimerStart(6); //启动电池测试计时器
#ifdef HARD_XK
X_SetChargeState(2);
X_Discharge();
#endif
break;
case 6://IS STOP
#ifdef HARD_XK
X_SetChargeState(0);
X_Stop();
#endif
break;
}
SetVoltaget();
}
/****************************************************************************/
void SetLimitI(int limit)
{
long ltemp;
Cha.i_limit = limit;
Cha.i_rating = RatingCurrent();
Cha.i_batt = Jkmk.ai_v[17];
Cha.i_out = Jkmk.ai_v[7];
Cha.i_outratio = Jkmk.ao_cfg[1];
if (Cha.i_batt > 0)
{
ltemp = (long)Cha.i_out * 1000 / Cha.i_rating; //实际输出比率
Cha.unit_p = (long)ltemp * 1000 / Cha.i_outratio; //充电模块响应系数
Jkmk.temp[31] = Cha.unit_p; //debug
Cha.unit_p = 1200;
if (Cha.i_da > 0)
{
Cha.unit_p = (long)Cha.i_out *1000 /Cha.i_da;
}
else
{
Cha.unit_p = 1000;
}
}
else
{
Cha.unit_p = 1000;
}
Cha.i_load = Cha.i_out - Cha.i_batt;
// Cha.i_da = Cha.i_load + Cha.i_limit; //i_out edit to i_da
if (Cha.i_load < 0)
{
Cha.i_load = 0;
}
if (Cha.i_batt > Cha.i_limit)
{
Cha.i_low = Cha.i_limit + Cha.i_load;
}
else
{
Cha.i_low = Cha.i_limit;
}
Cha.i_high = Cha.i_limit + Cha.i_load;
if (Cha.i_high > Cha.i_rating)
{
Cha.i_high = Cha.i_rating;
}
Cha.i_high = Cha.i_rating; //debug
Cha.i_e = Cha.i_limit - Cha.i_batt;
//根据电池电流调节 电流偏离限流值0。2A开始调节
if ((Cha.i_e < -1) || (Cha.i_e > 1))
{
Cha.i_da += Cha.i_e/2 ;
if (Cha.i_da > Cha.i_high)
{
Cha.i_da = Cha.i_high;
}
if (Cha.i_da < Cha.i_low)
{
Cha.i_da = Cha.i_low;
}
ltemp = Cha.i_da;
Cha.i_outratio = (long)ltemp * 1000 / Cha.i_rating;
SetOutI(Cha.i_outratio); //设置输出电流比率
}
/*
Jkmk.temp[37] = Cha.i_e; //debug
Jkmk.temp[38] = Cha.i_low; //debug
Jkmk.temp[39] = Cha.i_da; //debug
Jkmk.temp[28] = Cha.i_high; //debug
Jkmk.temp[29] = Cha.i_out; //debug
Jkmk.temp[18] = Cha.i_load; //debug
Jkmk.temp[19] = Cha.i_outratio; //debug
*/
}
/*
所有充电状态充电电流都不可超过限流值,
当充电电流大于限流值,则减小充电模块输出限流点,这样将导致充电电压下降。
当充电电流小于限流值,则增大充电模块输出限流点,
系统母线故障时将打开限流点,不限流
*/
void LimitCurrent(void)
{
int step;
/*
Jkmk.ai_v[17] 1路电池电流
Jkmk.ai_v[19] 2路电池电流
Jkmk.temp[36] 转浮充电流
Jkmk.temp[35] 转均充电流
Jkmk.mk_cfg[51] 模块数量
Jkmk.mk_cfg[52] 模块容量
Jkmk.temp[34] 限流
Jkmk.temp[30] 允许输出电流
*/
if (Jkmk.temp[24] != 0)
{//手动
return;
}
Jkmk.temp[34] = Jkmk.mk_cfg[10] * Jkmk.mk_cfg[30]/10; //100mA充电限流值
step = GetChargeStep();
switch (step)
{
case 0://floating charge
SetOutI(1000);//打开限流
break;
case 1://floating charge to equipoise charge
case 2://equipoise charge
SetLimitI(Jkmk.temp[34]);
break;
case 3://equipoise charge to floating charge
case 4://power cut discharge
SetOutI(1000);//打开限流
break;
case 5://batt test
break;
case 6://batt alarm
SetOutI(1000);//打开限流
break;
}
}
/****************************************************************************/
/**
2路DAC输出过程
//1 判断输出给定值是否合法 给定值判断在设置时处理过了
2 根据各自量程换算输出DAC值
3 输出
控制方式有两种
1 直接控制电压和电流,
2 控制2路电压,通过电压间接控制电流
序号
ao_v
0 电压 1路电压
1 电流 1路电流
2 电压
3
ao_cfg
0 电压缓冲
1 电流缓冲
2 2路电压缓冲
3 2路电流缓冲
4 1路电压量程
5 1路电流量程
7 2路电压量程
8 2路电流量程
*/
void DaOutU(int value)
{
#ifdef HARD_XK
int da_value;
Jkmk.ao_v[0] = value;
//相控电压换算成DA值,再输出到DA控制PI板
//判断量程是否为零
if (Jkmk.ao_cfg[4] > 0)
{
da_value = (long)((long)value * MAX_DAVALUE)/(long)Jkmk.ao_cfg[4];
}
else
{
da_value = 0;
}
DA_Out1(da_value);
#endif
}
void DaOutI(int value)
{
#ifdef HARD_XK
int da_value;
Jkmk.ao_v[1] = value;
//相控电流换算成DA值,再输出到DA控制PID板
//判断量程是否为零
if (Jkmk.ao_cfg[5] > 0)
{
da_value = (long)((long)value * MAX_DAVALUE)/(long)Jkmk.ao_cfg[5];
}
else
{
da_value = 0;
}
DA_Out2(da_value);
#endif
}
/****************************************************************************/
void SetOutI(int value)
{
int i_limit;
long int ltemp;
if (value > 1000)
{
value = 1000;
}
if (value < 10)
{
value = 10;
}
Jkmk.ao_cfg[1] = value;
i_limit = CdmkCurrentLimit();
if (i_limit != value)
{
Jkmk.ao_v[1] = Jkmk.ao_cfg[1];
TranOutI();
}
// BeepSet(1);
}
/****************************************************************************/
/****************************************************************************/
void SetCurrent(void)
{
#ifdef HARD_GP
LimitCurrent();
#endif
#ifdef HARD_XK
X_Current();
#endif
}
/****************************************************************************/
//adjust
//定时时执行持函数,维持设定电压
void SetVoltaget(void)//adjust
{
int step;
step = GetChargeStep();
//温度补偿
if (Jkmk.mk_cfg[21])
{
Cha.v_compensate = Jkmk.mk_cfg[13] * (Jkmk.ai_v[25]-Jkmk.mk_cfg[14])/100;
Cha.v_compensate = 0;
}
else
{
Cha.v_compensate = 0;
}
switch (step)
{
//set out is floating charge voltage
case 0:
case 1:
case 4:
case 5:
//浮充电压
Jkmk.ao_cfg[0] = Jkmk.mk_cfg[6] + Cha.v_compensate;
break;
//set out is equipoise charge voltage
case 2:
case 3:
if (Jkmk.mk_cfg[8] == 0)
{
Jkmk.ao_cfg[0] = Jkmk.mk_cfg[6] + Cha.v_compensate;
SetChargeStep(0);
}
else
{
//均充电压
Jkmk.ao_cfg[0] = Jkmk.mk_cfg[7] + Cha.v_compensate;
}
break;
}
#ifdef HARD_GP
TranOutV();
#endif
#ifdef HARD_XK
X_Voltaget();
#endif
}
/****************************************************************************/
void Capacity(void)
{
/*按充电效率和放电曲线分别计算充电放电时电池当前容量 每10秒运行一次
**充电 按充电效率累加电池容量 到100%饱和
**放电 按放电曲线计算失去容量 到0%停止
**充电
** capc
** y * cck * x = capc ==> x = -------
** cck * y
**
**放电
** x1 < x < x2 y1 > y > y2
**
** x-x1 y1-y (x2-x1)(y1-y)
** ----- = ------ ==> x = ------------- + x1
** x2-x1 y1-y2 y1-y2
**
** 原始单位
** 标称容量 1 = 1Ah, 容量比 1 = 0.1%, 充电效率 1 = 0.1%,
** 电流 1 = 0.1A, 电压 1 = 0.1V, 放电曲线时间 1 = 0.1小时
** 计算中单位统一为
** 电流 1 = 0.1A, 电压 1 = 0.1V, 时间 1 = 10秒, 比值 1 = 0.1%;
** 0x7FFFFFFF = 2147483647 即2.14E9
*/
static long diff_capac = 0;
int i;
long x, x1, x2, y1_y2, cck, y;
y = (long)Jkmk.ai_v[17]*10; /* 电池电流 */
y1_y2 = (long)Jkmk.mk_cfg[10]; /* 0.1C电流值 0.1A数 即电池容量 */
if (y == 0)
return;
/* 电池状态 4 放电 5测试 */
if ((Jkmk.temp[25] == 4) || (Jkmk.temp[25] == 5))
{
cck = (long)Jkmk.mk_cfg[16]; /* 充电效率 1 = 0.1% */
x = (long)((long)360 * (long)100 * (long)Jkmk.mk_cfg[10]);
cck = (cck * y / 100);
x = x/cck;
/* 电池按当前电流充电 预计充电时间*/
diff_capac += MAX_DIFF_CAPAC * 100 / x;
}
else /* 放电 */
{
/* 0.1C=10h 0.2C=4.9h 0.3C=3.0h 0.4C=2.0h 0.5C=1.4h
0.6C=1.2h 0.7C=1.1h 0.8C=0.9h 0.9C=0.7h 1.0C=0.5h */
y = -y;
for ( i = 1; i < 9; i++ )
if ( y <= ((i+1) * y1_y2) ) break;
x1 = (long)Jkmk.mk_cfg[20+i] * 36; /* 放电曲线值1放电10秒数 */
x2 = (long)Jkmk.mk_cfg[20+i - 1] * 36; /* 放电曲线值2放电10秒数 */
x = (x2 - x1) * ((i+1) * y1_y2 - y) / (y1_y2) + x1;
/* 电池按当前电流放电 预计放电时间*/
diff_capac -= MAX_DIFF_CAPAC * 100 / x;
}
if (i) /*电压过低 容量不计算*/
{
diff_capac = 0;
}
/* 容量累积到够0.1%加入容量*/
if ((diff_capac < -MAX_DIFF_CAPAC) || (diff_capac > MAX_DIFF_CAPAC))
{
Jkmk.mk_cfg[11] += diff_capac / MAX_DIFF_CAPAC;
diff_capac -= (diff_capac / MAX_DIFF_CAPAC) * MAX_DIFF_CAPAC;
/* 防止当前容量异常值*/
if (Jkmk.mk_cfg[11] > 100)
{
Jkmk.mk_cfg[11] = 100;
}
if (Jkmk.mk_cfg[11] < 0)
{
Jkmk.mk_cfg[11] = 0;
}
SaveModuleData(MODULE_JKMK|DATA_MKCFG, 11, 0);
}
}
/****************************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -