📄 charge.c
字号:
/*
* Filename : charge.c
* Author : Li Dawen
* Copyright (c): Coslight Group .co
* Create Date : 2002.04.27
* Version : 0.1.0
*/
#include "includes.h"
#include "charge.h"
#include "module.h"
#include "protocol.h"
/****************************************************************************/
/****************************************************************************/
/*
蓄电池工作可分为均充、稳流均充、浮充、放电、测试五个状态
所有充电状态充电电流都不可超过限流值,
如充电电流过大则由于系统限流作用,充电电压将低于设定值,保持充电电流恒定
均充 限流恒压充电,均充电压
稳流均充 恒压充电,均充电压
浮充 恒压充电,浮充电压
放电 充电电流为负数
测试 为测试电池,人为的放电
状态转换如下
均充 -> 稳流均充
1电流条件 充电电流小于限值
2时间条件 均充保护时间到
3容量条件 当前容量大于转换点
稳流均充 -> 浮充
1电流条件 充电电流大于转换点
2时间条件 该状态充电持续时间大于稳流均充时间
浮充 -> 转均充过渡均充
1电流条件 充电电流大于转均充电流
2时间条件 系统未定时均充充电持续时间大于定时均充时间
3容量条件 当前容量小于转均充容量
转均充过渡 -> 均充
1电流条件 充电电流大于转均充电流
2时间条件 过渡时间到
转均充过渡 -> 浮充
1电流条件 充电电流小于转均充电流
测试 -> 浮充
1电压条件 电池电压小于测试终止电压
2容量条件 电池容量小于测试终止容量
3时间条件 测试时间大于最大测试时间
->放电
1电流条件 非测试状态,充电电流为负数
->测试
1启动条件 手动启动
放电
|
v
均充 -> 稳流均充 -> 浮充 <-> 转均充过渡 ->均充
^
|
测试
运行 电压 电流 时间
----------------------------------------------------
浮充
*/
/*
tm_cfg
0系统延时 fen
1屏幕保护 fen
2均充周期时间 hour
3均充保护时间 fen
4稳流均充时间 fen
5转均充延时 fen
6电池测试时间 fen
*/
int Charge_Step;
int minute_count;
CHARGE Cha;
DA I_Contrl;
/****************************************************************************/
void ChargeInit(void)
{
Cha.i_buf[0] = 0;
Cha.i_buf[1] = 0;
Cha.i_buf[2] = 0;
Cha.i_da = 0;
I_Contrl.da_v = 0;
I_Contrl.da_max = 0;
I_Contrl.da_min = 0;
I_Contrl.da_timer = 0;
I_Contrl.da_stepsize = 0;
Jkmk.temp[25] = 0;
ChargeTimerInit();
#ifdef HARD_GP
Jkmk.ao_cfg[0] = 2400;
Jkmk.ao_cfg[1] = 1000;
SetChargeStep(0); //设置成浮充
#endif
#ifdef HARD_XK
Jkmk.ao_cfg[0] = 2400;
Jkmk.ao_cfg[1] = 0;
SetChargeStep(6); //设置成停止
#endif
}
void ChargeTimerInit(void)
{
int i;
minute_count = 0;
for (i = 2; i < 6; i++)
{
Jkmk.tm_v[i] = Jkmk.tm_cfg[i];
}
for (i = 2; i < 6; i++)
{
if (Jkmk.tm_v[i] > Jkmk.tm_cfg[i])
{
Jkmk.tm_v[i] = Jkmk.tm_cfg[i];
}
}
ChargeTimerStop(3); //停止均充保护计时器
ChargeTimerStop(5); //停止转均充延时计时器
}
/* 每分钟调用一次用于运行计时器*/
void ChargeTimerTick(void)
{
int i;
if (++minute_count > 60)
{
minute_count = 0;
Jkmk.tm_v[2]--;
}
//分钟计时
for (i = 3; i < 7; i++)
{
if (Jkmk.tm_v[i] > 0)
{
Jkmk.tm_v[i]--;
}
}
}
void ChargeTimerPlay(int index)
{
if (Jkmk.tm_v[index] < 0)
{
Jkmk.tm_v[index] = -Jkmk.tm_v[index];
}
}
void ChargeTimerPause(int index)
{
if (Jkmk.tm_v[index] > 0)
{
Jkmk.tm_v[index] = -Jkmk.tm_v[index];
}
}
void ChargeTimerStart(int index)
{
Jkmk.tm_v[index] = Jkmk.tm_cfg[index];
}
void ChargeTimerStop(int index)
{
Jkmk.tm_v[index] = 0;
}
int ChargeTimerCount(int index)
{
return Jkmk.tm_v[index];
}
/****************************************************************************/
void X_ChargeIdentifyt(void)
{
}
/****************************************************************************/
void ChargeIdentifyt(void)
{
int step;
int i_zero = 0;
//根据电压电流判断电池充电状态 浮充 均充 放电 测试 故障
//相控用的补丁,被动识别充电状态
/*
Jkmk.mk_cfg[10] 电池容量
Jkmk.mk_cfg[32] 转均充电流比
Jkmk.mk_cfg[31] 转浮充电流比
Jkmk.mk_cfg[7] 均充电压
Jkmk.ai_v[16] 电池电压
Jkmk.ai_v[17] 电池电流
Jkmk.temp[24] 自动 手动
*/
Jkmk.temp[34] = Jkmk.mk_cfg[10]*Jkmk.mk_cfg[30]/10; //100m充电限流值
Jkmk.temp[35] = Jkmk.mk_cfg[10]*Jkmk.mk_cfg[32]/10; //100m转均充电流
Jkmk.temp[36] = Jkmk.mk_cfg[10]*Jkmk.mk_cfg[31]/10; //100m转浮充电流
step = GetChargeStep();
//检查均充电压安全性
if (Jkmk.mk_cfg[7] < Jkmk.mk_cfg[6])
{
Jkmk.mk_cfg[7] = Jkmk.mk_cfg[6];
}
//电池测试 逆变 不判断
if (6 == step || 5 == step)
{
return;
}
// if (Jkmk.temp[24] == 0)
// {//自动运行 根据电池电压和电流判断电池是否在放电
//加入电压条件防止无连接时状态抖动,但效果不好,去掉电压条件,只判断电流
// if ((Jkmk.ai_v[16] > Jkmk.ai_cfg[16*3+2]/2) && (Jkmk.ai_v[17] < -5))
#ifdef HARD_GP
if (Jkmk.ai_cfg[17*3] > 700)
{
i_zero = -2;
}
else
{
i_zero = -1;
}
if ((Jkmk.ai_v[17] < i_zero))
{
//放电
SetChargeStep(4);
}
else
{
if (step == 4)
{
SetChargeStep(0);
}
}
#endif
}
/****************************************************************************/
//相控充电机控制函数
//DA1 电压控制 XX:控制 0:停止
//DA2 电流控制 XX:控制 0:停止
//JK1 DA开关 1:通 0:断
//JK2 脉冲封锁 1:封锁 0:打开
void X_Discharge(void)
{
//DA输出控制值 接通DA 允许脉冲
//DA1=X DA2=X JK1 =1 JK2=0
Cha.i_ctltimer = CHARGE_SOFTSTART_TIME;
Cha.v_da = Cha.v_set;
Cha.i_da = Cha.i_sigzero;//启动时去除死区
Cha.v_da = Cha.v_high;
// HardOut(5, 1);
// HardOut(6, 0);
SetModuleData(MODULE_JKMK|DATA_DO, 4, 0, 1);
SetModuleData(MODULE_JKMK|DATA_DO, 5, 0, 0);
X_Voltaget();
X_Current();
}
void X_Charge(void)
{
//DA输出控制值 接通DA 允许脉冲
//DA1=X DA2=X JK1 =1 JK2=0
Cha.i_ctltimer = CHARGE_SOFTSTART_TIME;
Cha.v_da = Cha.v_high;
Cha.i_da = Cha.i_sigzero;//启动时去除死区
// HardOut(5, 1);
// HardOut(6, 0);
SetModuleData(MODULE_JKMK|DATA_DO, 4, 0, 1);
SetModuleData(MODULE_JKMK|DATA_DO, 5, 0, 0);
X_Voltaget();
X_Current();
}
void X_Stop(void)
{
//DA输出0 封锁脉冲 断开DA
//DA1=0 DA2=0 JK1 =0 JK2=0
Cha.i_timer = CHARGE_SOFTSTOP_TIME; //停止延时定时器启动30S
SetModuleData(MODULE_JKMK|DATA_DO, 4, 0, 1);
X_Voltaget();
X_Current();
}
/****************************************************************************/
//da输出线性平滑函数
void X_IDaSet(int v)
{
I_Contrl.da_target = v;
if (I_Contrl.da_target == I_Contrl.da_v)
{
return;
}
I_Contrl.da_timer = 10;
I_Contrl.da_stepsize = I_Contrl.da_v - I_Contrl.da_target;
//判断变化方向,去掉死区
if (I_Contrl.da_stepsize > 0)
{
I_Contrl.da_stepsize /= 8;
if (I_Contrl.da_stepsize > 10)
I_Contrl.da_stepsize = 10;
if (0 == I_Contrl.da_stepsize)
I_Contrl.da_stepsize = 1;
}
else
{
I_Contrl.da_stepsize /= 8;
if (I_Contrl.da_stepsize < -10)
I_Contrl.da_stepsize = -10;
if (0 == I_Contrl.da_stepsize)
I_Contrl.da_stepsize = -1;
}
}
/****************************************************************************/
//平滑输出da值
void X_IDaUpdata(void)
{
if (I_Contrl.da_timer > 0)
{
I_Contrl.da_timer--;
//减小超调
if (I_Contrl.da_stepsize > 0)
{//输出变小
if (I_Contrl.da_v <= I_Contrl.da_target )
{
I_Contrl.da_stepsize = 0;
I_Contrl.da_v = I_Contrl.da_target;
}
}
else
{//输出变大
if (I_Contrl.da_v >= I_Contrl.da_target )
{
I_Contrl.da_stepsize = 0;
I_Contrl.da_v = I_Contrl.da_target;
}
}
if ((Cha.v_e > (Cha.v_ezero+2)) && (I_Contrl.da_stepsize < 0))
{//电压偏高 不调节
//I_Contrl.da_v;
I_Contrl.da_stepsize = 0;
}
else
{
I_Contrl.da_v -= I_Contrl.da_stepsize;
}
if (I_Contrl.da_v < 0)
{
I_Contrl.da_v = 0;
}
DaOutI(I_Contrl.da_v);
}
}
/****************************************************************************/
//根据电压判断当前要改动的充电状态是否安全
int X_SafeState(int value)
{
int step;
if (0 == value)
{
return 1;
}
step = X_GetChargeState();
if (0 == step)
{
if (0 == GetModuleData(MODULE_JKMK|DATA_DO, 5, 0))
{//脉冲没有封锁 不能操作
return 0;
}
if (1 == GetModuleData(MODULE_JKMK|DATA_DI, 13, 0))
{//在停止档 不能操作
return 0;
}
if (1 == value)
{//希望充电 判断输出电压极性为正 可以充电
if (Jkmk.ai_v[6] > -50)
return 1;
else
return 0;
}
if (2 == value)
{//希望放电 输出电压极性为负 可以放电
if (Jkmk.ai_v[6] < -1000)
return 1;
else
return 0;
}
}
else
{
if(value == step)
return 1;
}
return 0;
}
/****************************************************************************/
void X_Updata(void)
{
Cha.v_out = Jkmk.ai_v[6]; //输出电压
Cha.i_out = Jkmk.ai_v[7]; //输出电流
//根据电池开关状态判断当前电池是 1组或2组
if (Jkmk.di_v[15])
{
// Cha.v_batt = Jkmk.ai_v[18];
Cha.i_batt = Jkmk.ai_v[19];
}
if (Jkmk.di_v[14])
{//1组
// Cha.v_batt = Jkmk.ai_v[16];
Cha.i_batt = Jkmk.ai_v[17];
}
Cha.i_batt = ABS(Cha.i_batt);
#ifdef HARD_GP
Cha.i_batt = Jkmk.ai_v[17];
#endif
//只使用1组电池数据
Cha.v_batt = Jkmk.ai_v[16];
Cha.v_ezero = Jkmk.mk_cfg[64]; //电压调节误差
Cha.v_lowtohigh = 20; //Jkmk.mk_cfg[65]; //电压调节范围
Cha.i_ezero = Jkmk.mk_cfg[66]; //电流调节误差
Cha.i_max = Jkmk.mk_cfg[68]; //最大输出电流
Cha.i_sigzero = Jkmk.mk_cfg[67]; //SIG零点
Cha.v_set = Jkmk.ao_cfg[0]; //浮充或均充电压
if (Cha.i_ezero <= 2)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -