具体是项目工程代码。
(Var)=((Var)>=(Max))?(Max):(Var)//意思是if var>=max,则var+max,否则,var=var
k |= SW1_VALUE//位或,意思是把k的值和SW1_VALUE位按位或后,然后再赋值给SW1_VALUE。
if (ShadowScanState.bit.ScanFlag)是什么意思?shadowcanstate是阴影面积扫描吗
计算Id_reference的时候,首先是计算f32VboostErr,然后对gain进行限定,然后通过BusCon_Reg.f32BusErr_New = f32VboostGain * f32VboostErr计算出Bus_error;然后计算出Bus_ Err_new,就算这个是为了得到BusIL-ref,如果说放电状态,则把BusIL-ref赋值给IL_Peak_ref,这个在以后计算currentPID的时候会用到;
- 关于平均值和有效值的计算:
有效值:
AD_Acc.f32RmsGFCI += ADValue.f32GFCI * ADValue.f32GFCI;
AD_Sum.f32RmsGFCI = AD_Acc.f32RmsGFCI;
RealValue.f32RmsGFCI = sqrt(AD_Sum.f32RmsGFCI * f32rcnt);
通过上面的三次转换就知道rms值是怎么计算得到的了。其他的都一样;
平均值:
平均值的计算就比较简单了;
AD_Acc.f32GFCI += ADValue.f32GFCI;
AD_Sum.f32GFCI = AD_Acc.f32GFCI;
RealValue.f32GFCI = (AD_Sum.f32GFCI * f32rcnt);
CAN通信,data unpack部分。
if(data0==0X7E) // 判断标志位==7E;
{
for(index=1;index<5;index++) // 提取data1、2、3/4
{
switch(index)
{
case 1:
ucRXMsgData[index] = CanaRegs.CAN_IF2DATA.bit.Data_1;
break;
case 2:
ucRXMsgData[index] = CanaRegs.CAN_IF2DATA.bit.Data_2;
break;
case 3:
ucRXMsgData[index] = CanaRegs.CAN_IF2DATA.bit.Data_3;
break;
case 4:
ucRXMsgData[index] = CanaRegs.CAN_IF2DATB.bit.Data_4;
break;
}
}
//dataunpack;
result+=ucRXMsgData[1];
result+=(ucRXMsgData[2]<<8);
result+=(ucRXMsgData[3]<<16);
result+=(ucRXMsgData[4]<<24);
}
记录一下数据流(CAN通信发电量)
g_i32ExternalPvPower = getCANMessage(CAN_RX_MSG_OBJ);
g_i32ExternalPvPower = g_i32ExternalPvPower*0.1; //单位转换成W;
if(g_i32ExternalPvPower<0)
{
g_i32ExternalPvPower = -g_i32ExternalPvPower;
// flag=0;
}
这里是提取can发来的数据,并且存在 g_i32ExternalPvPower这个变量里。
g_u16SpiTxBuf[18] = (int16)g_i32ExternalPvPower;
我们的主DSP和副DSP是通过SPI通信的。这里讲 g_i32ExternalPvPower传到Buff[18]。
并且在PMU里也会用到:
if (/*fabs(RealValue.f32BatChgDischgPower) < 50.0*/
(!(g_MPPTState.bit.PV1ON || g_MPPTState.bit.PV2ON)&&(g_i32ExternalPvPower<45))
&& ( (RealValue.f32PowerAC - (RealValue.f32PowerUtility/*-f32PCCPowerSet*/)) < 40)
&& (fabs(f32PCCPowerSet) < 0.1f))
这里是如果PV1 on或者PV2 on或者接了外置PV逆变器的情况下,电池都不会出现standby的情况;
注意这里小于45,这个45是随便取的一个很小的值,意思是只要外置PV功率小于45W我们都认为没有外接PV,因为正常情况下,这个外置的PV会大于这个值。
接下来是副DSP里的处理。
M_CalcResultRms.i16ExternalPvPower = g_SpiRxBuf[18];
副DSP接收数据。
i16temp_1 = ADCalc_EnergyPow.i16PowerAC - ADCalc_EnergyPow.i16GridPower + M_CalcResultRms.i16ExternalPvPower; //能量守恒
if(i16temp_1 < 0) //默认负载不放电,只耗电
{
i16temp_1 = 0;
}
ADCalc_EnergyPow.i16LoadPower = i16temp_1;
这里是计算显示屏上面的负载的功率,计算方式是PowerAC - GridPower + i16ExternalPvPower。
然后,
ADCalc_EnergyPow.i16PVGenPower = M_CalcResultRms.i16Input1Watt + M_CalcResultRms.i16Input2Watt
+ M_CalcResultRms.i16ExternalPvPower ;
这里是计算显示屏上面PV发电量,PV发电量为内接PV和外置PV发电量之和。
最后是监控板上面的逻辑:
#if 1
if(rtdb.i16PVGenPower <= (rtdb.PV1Power+rtdb.PV2Power))
{
// 防止AC采样误差造成负载计算成负的
// 假设了负载不会输出功率 且 电网功率是准确的
if (Inverter_Information.i16PowerAC < Inverter_Information.Outputactivepower)
{
Inverter_Information.i16PowerAC = Inverter_Information.Outputactivepower;
}
// PV 等于 Inv
if (1 != inputInvState.bit.Bat && 2 != inputInvState.bit.Bat
&& inputInvState.bit.PVReady)
{
Inverter_Information.i16PVGenPower = Inverter_Information.i16PowerAC;
if (Inverter_Information.i16PVGenPower < 0)
{
Inverter_Information.i16PVGenPower = 0;
}
}
// Bat 等于 Inv
else if (0 == inputInvState.bit.PVReady
&& (1 == inputInvState.bit.Bat || 2 == inputInvState.bit.Bat))
{
Inverter_Information.i16BatPower = -Inverter_Information.i16PowerAC;
}
// 全部工作
else if (1 == inputInvState.bit.PVReady
&& (1 == inputInvState.bit.Bat || 2 == inputInvState.bit.Bat))
{
i32Ptmp = Inverter_Information.i16PVGenPower;
Inverter_Information.i16PVGenPower = (i32Ptmp * 251) >> 8; // 0.981
// 如果电池符号改变,强制为0
i32Ptmp = Inverter_Information.i16PVGenPower - Inverter_Information.i16PowerAC;
if ((i32Ptmp > 0 && Inverter_Information.i16BatPower < 0)
|| (i32Ptmp < 0 && Inverter_Information.i16BatPower > 0))
{
i32Ptmp = 0;
}
Inverter_Information.i16BatPower = i32Ptmp;
}
}
rtdb.i16PVGenPower = Inverter_Information.i16PVGenPower / 10;
rtdb.i16BatChgDischgPower = Inverter_Information.i16BatPower / 10;
#endif
小记一下;
这里的关于PowerPV1计算的时候用到了IIR FILTER
#define IIR_FILTER(s,x,n) do{(s)=(s)-((s)>>(n))+(x);}while(0)
下次来了再看一下。