2026-03-20 21:16:58 +08:00
|
|
|
|
#include "../main/SystemInclude.h"
|
|
|
|
|
|
//==============================================================================
|
|
|
|
|
|
u32 dcoefNode[DCOEF_MAX];
|
|
|
|
|
|
u16 dcoef, dcoefVal[DCOEF_MAX];
|
|
|
|
|
|
float GCFParaA, GCFParaB, GCFParaC;
|
2026-03-20 21:19:53 +08:00
|
|
|
|
u16 GCFCoefB;
|
2026-03-20 21:16:58 +08:00
|
|
|
|
s32 GCFCoefA, GCFCoefC;
|
|
|
|
|
|
float GCFParaA, GCFParaB, GCFParaC;
|
|
|
|
|
|
//u16 dcoefNum;
|
|
|
|
|
|
//******************************************************************************
|
|
|
|
|
|
// Routines for device coefficients
|
|
|
|
|
|
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߽ڵ<DFBD><DAB5><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
|
void StoreDevCoefNodeAndValue(unsigned char I)
|
|
|
|
|
|
{
|
|
|
|
|
|
tempL.DWord= dcoefNode[I];
|
|
|
|
|
|
tempDev.Word[2] = tempL.Word[1];
|
|
|
|
|
|
tempDev.Word[1] = tempL.Word[0];
|
|
|
|
|
|
tempDev.Word[0] = dcoefVal[I];
|
|
|
|
|
|
|
2026-03-20 21:19:53 +08:00
|
|
|
|
WriteMultiByteToMemory(DCOEF_BASE+I*DCOEF_WIDTH, tempDev.Byte, DCOEF_WIDTH);
|
2026-03-20 21:16:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//******************************************************************************
|
|
|
|
|
|
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߽ڵ<DFBD><DAB5><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
|
bool ReadDevCoefNodeAndValue(unsigned char I)
|
|
|
|
|
|
{
|
2026-03-20 21:19:53 +08:00
|
|
|
|
ReadMultiByteFromMemory(DCOEF_BASE + I * DCOEF_WIDTH, tempDev.Byte, DCOEF_WIDTH);
|
2026-03-20 21:16:58 +08:00
|
|
|
|
if(tempDev.Byte[DCOEF_CRC] == CRC8(tempDev.Byte, DCOEF_CRC))
|
|
|
|
|
|
{
|
|
|
|
|
|
tempDev.Byte[DCOEF_CRC] = 0;
|
|
|
|
|
|
|
|
|
|
|
|
dcoefVal[I] = tempDev.Word[0];
|
|
|
|
|
|
tempL.Word[0] = tempDev.Word[1];
|
|
|
|
|
|
tempL.Word[1] = tempDev.Word[2];
|
|
|
|
|
|
dcoefNode[I] = tempL.DWord;
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
dcoefNode[I] = 0;
|
|
|
|
|
|
dcoefVal[I] = 0;
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
//******************************************************************************
|
|
|
|
|
|
//Ĭ<>ϵĶ<CFB5><C4B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߲<EFBFBD><DFB2><EFBFBD>
|
|
|
|
|
|
void DefaultDevCoef(void)
|
|
|
|
|
|
{
|
|
|
|
|
|
unsigned char I;
|
|
|
|
|
|
//u32 flowRateMax;
|
|
|
|
|
|
|
|
|
|
|
|
dcoefNode[0] = (maxFlowRate * 1) / 100; // 1% 1028
|
|
|
|
|
|
dcoefNode[1] = 1000;
|
|
|
|
|
|
dcoefNode[2] = (maxFlowRate * 10) / 100; // 10%
|
|
|
|
|
|
//dcoefNode[3] = (maxFlowRate * 20) / 100;
|
|
|
|
|
|
//dcoefNode[4] = (maxFlowRate * 40) / 100;
|
|
|
|
|
|
dcoefNode[3] = maxFlowRate >> 1; // 50%
|
|
|
|
|
|
dcoefNode[4] = maxFlowRate; // 100%
|
|
|
|
|
|
|
|
|
|
|
|
if(dcoefNode[0] < 500) dcoefNode[0] = 500;
|
|
|
|
|
|
if(dcoefNode[1] <= dcoefNode[0]) dcoefNode[1] = (maxFlowRate * 5) / 100; //dcoefNode[1] = (dcoefNode[0] + dcoefNode[2])>>1;
|
|
|
|
|
|
if(dcoefNode[2] <= dcoefNode[1]) dcoefNode[2] = (dcoefNode[1] + dcoefNode[3]) >> 1;
|
|
|
|
|
|
if(dcoefNode[3] <= dcoefNode[2]) dcoefNode[3] = (dcoefNode[2] + dcoefNode[4]) >> 1;
|
|
|
|
|
|
|
|
|
|
|
|
dcoefNum = 5;
|
|
|
|
|
|
tempL.Byte[0] = dcoefNum;
|
2026-03-20 21:19:53 +08:00
|
|
|
|
// WriteShortParameterToEEPROM(DCOEF_NUM, DCOEF_NUM_WIDTH);
|
|
|
|
|
|
WriteShortParameterToEEPROM(DCOEF_NUM);
|
2026-03-20 21:16:58 +08:00
|
|
|
|
|
|
|
|
|
|
for (I = 0; I < dcoefNum; I++)
|
|
|
|
|
|
{
|
|
|
|
|
|
dcoefVal[I] = METER_PARAMETER_DEFAULT;
|
|
|
|
|
|
//dcoefNode[I] = ConvertFlowrate(dcoefNode[I]);
|
|
|
|
|
|
|
|
|
|
|
|
StoreDevCoefNodeAndValue(I);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//******************************************************************************
|
|
|
|
|
|
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߲<EFBFBD><DFB2><EFBFBD>
|
|
|
|
|
|
void RetriveDevCoef(void)
|
|
|
|
|
|
{
|
2026-03-20 21:19:53 +08:00
|
|
|
|
u32 I;
|
2026-03-20 21:16:58 +08:00
|
|
|
|
// u32 flowRateMax;
|
|
|
|
|
|
|
2026-03-20 21:19:53 +08:00
|
|
|
|
ReadShortParameterFromMemory(DCOEF_NUM, PARA_EEPROM);
|
|
|
|
|
|
// if(tempL.Byte[1] != CRC8(tempL.Byte, 1)) goto RetResetDevCoef;
|
2026-03-20 21:16:58 +08:00
|
|
|
|
|
|
|
|
|
|
dcoefNum = tempL.Byte[0];
|
|
|
|
|
|
if((dcoefNum > DCOEF_MAX)||(dcoefNum < 3)) goto RetResetDevCoef;
|
|
|
|
|
|
|
|
|
|
|
|
if(ReadDevCoefNodeAndValue(0)) goto RetResetDevCoef;
|
|
|
|
|
|
for (I = 1; I < dcoefNum; I++)
|
|
|
|
|
|
{
|
|
|
|
|
|
if(ReadDevCoefNodeAndValue(I)) goto RetResetDevCoef;
|
|
|
|
|
|
if(dcoefNode[I] <= dcoefNode[I-1]) goto RetResetDevCoef;
|
|
|
|
|
|
// if(dcoefNode[I] > flowRateMax) goto RetResetDevCoef;
|
|
|
|
|
|
}
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
RetResetDevCoef:
|
|
|
|
|
|
DefaultDevCoef();
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
//******************************************************************************
|
|
|
|
|
|
void JudgeDevCoef(void)
|
|
|
|
|
|
{
|
|
|
|
|
|
u16 I;
|
|
|
|
|
|
|
|
|
|
|
|
for (I = 1; I < dcoefNum; I++)
|
|
|
|
|
|
{
|
|
|
|
|
|
if(dcoefNode[I] <= dcoefNode[I-1]) { RetriveDevCoef(); return; }
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
//******************************************************************************
|
|
|
|
|
|
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ
|
|
|
|
|
|
u16 GetDevCoefFactor(u32 dcoefFlowRate)
|
|
|
|
|
|
{
|
|
|
|
|
|
// u32 tmp;
|
|
|
|
|
|
u16 nodeVal = METER_PARAMETER_DEFAULT;
|
|
|
|
|
|
u32 nodeFR = 0;
|
|
|
|
|
|
unsigned char I;
|
|
|
|
|
|
|
|
|
|
|
|
for(I = 0; I < dcoefNum; I++)
|
|
|
|
|
|
{
|
|
|
|
|
|
if(dcoefNode[I] < dcoefFlowRate) continue;
|
|
|
|
|
|
if(I != 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
nodeVal = dcoefVal[I-1];
|
|
|
|
|
|
nodeFR = dcoefNode[I-1];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
tmpSLA = (u32)dcoefVal[I];
|
|
|
|
|
|
tmpSLA -= (u32)nodeVal;
|
|
|
|
|
|
|
|
|
|
|
|
tmpSLB = (u32)dcoefFlowRate;
|
|
|
|
|
|
tmpSLB -= (u32)nodeFR;
|
|
|
|
|
|
tmpSLA *= tmpSLB;
|
|
|
|
|
|
|
|
|
|
|
|
tmpSLB = (u32)dcoefNode[I];
|
|
|
|
|
|
tmpSLB -= (u32)nodeFR;
|
|
|
|
|
|
tmpSLA /= tmpSLB;
|
|
|
|
|
|
|
|
|
|
|
|
tmpSLA += (u32)nodeVal;
|
|
|
|
|
|
|
|
|
|
|
|
return (u16)tmpSLA;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return dcoefVal[dcoefNum-1];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//******************************************************************************
|
|
|
|
|
|
// Routines for calculating the following expression without overflow:
|
|
|
|
|
|
u32 CorrectionExpression(u32 target, u16 factor, u16 base)
|
|
|
|
|
|
{
|
|
|
|
|
|
float tempF;
|
|
|
|
|
|
|
|
|
|
|
|
tempF = (float)target;
|
|
|
|
|
|
|
|
|
|
|
|
#ifndef CORRECT_METHOD
|
|
|
|
|
|
#pragma message("[undefined] CORRECT_METHOD")
|
|
|
|
|
|
#elif(CORRECT_METHOD)
|
|
|
|
|
|
|
|
|
|
|
|
tempF *= (float)base;
|
|
|
|
|
|
tempF /= (float)factor;
|
|
|
|
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
|
|
|
|
tempF /= (float)base;
|
|
|
|
|
|
tempF *= (float)factor;
|
|
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
return (u32)tempF;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//******************************************************************************
|
|
|
|
|
|
void GCFCorrection(void)
|
|
|
|
|
|
{
|
|
|
|
|
|
if(currentMode.Bit.CalibMode) return;
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
|
|
#ifndef ENABLE_GAS_RECOGNITION
|
|
|
|
|
|
#pragma message("[undefined] ENABLE_GAS_RECOGNITION")
|
|
|
|
|
|
#elif(ENABLE_GAS_RECOGNITION)
|
|
|
|
|
|
//FY if(!isCurrentGas) return;
|
|
|
|
|
|
#endif
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
float floatA, floatB;
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
|
|
#ifndef ENABLE_A_TYPE_FLOWRATE
|
|
|
|
|
|
#pragma message("[undefined] ENABLE_A_TYPE_FLOWRATE")
|
|
|
|
|
|
#elif(ENABLE_A_TYPE_FLOWRATE)
|
|
|
|
|
|
if(FRType == ATYPE_FR)
|
|
|
|
|
|
{
|
|
|
|
|
|
floatA = (float)GDCFactorAType;
|
|
|
|
|
|
floatA *= (float)currentFlowRate;
|
|
|
|
|
|
floatA /= (float)GCF_PARAMETER_STD;
|
|
|
|
|
|
currentFlowRate = (u32)floatA;
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
#endif
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
#ifndef ENABLE_GCF_POWER_CORR
|
|
|
|
|
|
#pragma message("[undefined] ENABLE_GCF_POWER_CORR")
|
|
|
|
|
|
#elif(ENABLE_GCF_POWER_CORR)
|
|
|
|
|
|
// Power function correction
|
|
|
|
|
|
// GCF
|
|
|
|
|
|
if(GCFCoefC == 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
floatB = (float)currentFlowRate;
|
|
|
|
|
|
floatB = (float)GCFParaB;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
floatA = GCFParaC; // GCFParaC : area m2
|
|
|
|
|
|
floatB = (float)currentFlowRate;
|
|
|
|
|
|
if(FR_STD_UNIT == SL) floatA *= 60000000; // 0000SLPM - 0.000 m3/s (3bit): (FR/1000)
|
|
|
|
|
|
else floatA *= 3600000; // 0000m3/H - 0.000 m3/s (3bit): (FR/1000)
|
|
|
|
|
|
floatA = floatB/floatA; // 0.000 m/s
|
|
|
|
|
|
floatA = pow(floatA, GCFParaA); // compute GCF
|
|
|
|
|
|
floatA *= GCFParaB;
|
|
|
|
|
|
floatB *= floatA;
|
|
|
|
|
|
}
|
|
|
|
|
|
currentFlowRate = (u32)floatB;
|
|
|
|
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
|
|
|
|
// Quadratic correction coefficient
|
|
|
|
|
|
// GCF
|
|
|
|
|
|
floatB = (float)currentFlowRate;
|
|
|
|
|
|
floatA = floatB * floatB;
|
|
|
|
|
|
floatA *= (float)GCFParaA;
|
|
|
|
|
|
floatB *= (float)GCFParaB;
|
|
|
|
|
|
floatA += floatB;
|
|
|
|
|
|
floatA += (float)GCFParaC;
|
|
|
|
|
|
currentFlowRate = (u32)floatA;
|
|
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//******************************************************************************
|
|
|
|
|
|
void FlowRateSecondaryCorrection(void)
|
|
|
|
|
|
{
|
|
|
|
|
|
// retrieve the GDCF factor & device coefficients
|
|
|
|
|
|
// account in the GDCF factor & device coefficients
|
|
|
|
|
|
#ifndef ENABLE_DCOEF
|
|
|
|
|
|
#pragma message("[undefined] ENABLE_DCOEF")
|
|
|
|
|
|
#elif(ENABLE_DCOEF)
|
|
|
|
|
|
if(HWState.EnableCheckCorr) JudgeDevCoef();
|
|
|
|
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
|
|
#ifndef ENABLE_FLOW_GAIN
|
|
|
|
|
|
#pragma message("[undefined] ENABLE_FLOW_GAIN")
|
|
|
|
|
|
#elif(ENABLE_FLOW_GAIN)
|
|
|
|
|
|
dcoef = GetDevCoefFactor(currentFlowRate/(u32)calibFlowGain);
|
|
|
|
|
|
#else
|
|
|
|
|
|
dcoef = GetDevCoefFactor(currentFlowRate);
|
|
|
|
|
|
#endif
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
currentFlowRate = CorrectionExpression(currentFlowRate, dcoef, METER_PARAMETER_STD);
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
currentFlowRate = CorrectionExpression(currentFlowRate, MeterFactor, METER_PARAMETER_STD);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
|
|
void ComputeGCFFactor(void)
|
|
|
|
|
|
{
|
|
|
|
|
|
// Quadratic correction coefficient
|
|
|
|
|
|
// GCF
|
|
|
|
|
|
GCFParaA = (float)GCFCoefA;
|
|
|
|
|
|
GCFParaA /= (float)GCF_A_DOT;
|
|
|
|
|
|
|
|
|
|
|
|
GCFCoefB = GDCFactor;
|
|
|
|
|
|
GCFParaB = (float)GCFCoefB;
|
|
|
|
|
|
GCFParaB /= (float)GCF_B_DOT;
|
|
|
|
|
|
|
|
|
|
|
|
GCFParaC = (float)GCFCoefC;
|
|
|
|
|
|
GCFParaC /= (float)GCF_C_DOT;
|
|
|
|
|
|
}
|