Files
CHJ/user/Compute/FlowRateCompute.c

364 lines
11 KiB
C
Raw Normal View History

2026-03-20 21:16:58 +08:00
#include "../main/SystemInclude.h"
//==============================================================================
#define FR_FILTER_MAX 8
#define FR_FILTER_SHIFT 3
#define FR_FILTER_MASK (FR_FILTER_MAX-1)
u32 flowSample[8], DisSample[8];
u16 FIndexSample[8];
u16 DisIndex, FRIndex, FIndex, filterShift, dataMask, filterDepth;
u32 maxAlarmFlowRate;
#ifndef ENABLE_LEAK_DETECT
#pragma message("[undefined] ENABLE_LEAK_DETECT")
#elif(ENABLE_LEAK_DETECT)
u16 leakDetectLowCounter, leakDetectHighCounter, leakDetectCounter;
#endif
/******************************************************************************/
u32 GetFlowRate(u16 flowIndex, u16 curveType)
{
u16 indexL, dataCompFac;
u8 temp[12];
switch(curveType)
{
case CURVE_1ST:
if(flowIndex > 32767) return 0;
2026-03-20 21:19:53 +08:00
else if(flowIndex < zeroSuppression) return 0;
else if(flowIndex >= CALIB_MAX_INDEX) flowIndex = CALIB_MAX_INDEX;
2026-03-20 21:16:58 +08:00
dataCompFac = CALIB_COMP_FAC;
2026-03-20 21:19:53 +08:00
indexL = CALI_DATA_ADDR;
2026-03-20 21:16:58 +08:00
break;
//------------------------------------------------------------------------
#ifndef ENABLE_2ND_CURVE
#pragma message("[undefined] ENABLE_2ND_CURVE")
#elif(ENABLE_2ND_CURVE)
case CURVE_2ND:
2026-03-20 21:19:53 +08:00
dataCompFac = CALIB_COMP_FAC2;
indexL = CALI_DATA2_ADDR;
2026-03-20 21:16:58 +08:00
break;
#endif
//------------------------------------------------------------------------
#ifndef ENABLE_3RD_CURVE
#pragma message("[undefined] ENABLE_3RD_CURVE")
#elif(ENABLE_3RD_CURVE)
case CURVE_3RD:
if(flowIndex > 32767) return 0;
else if(flowIndex < zeroSuppression) return 0;
2026-03-20 21:19:53 +08:00
else if(flowIndex >= CALIB_MAX_INDEX3) flowIndex = CALIB_MAX_INDEX;
dataCompFac = CALIB_COMP_FAC3;
2026-03-20 21:16:58 +08:00
indexL = CALI_DATA3_ADDR;
break;
2026-03-20 21:19:53 +08:00
#endif
2026-03-20 21:16:58 +08:00
default: return 0;
}
2026-03-20 21:19:53 +08:00
//240000-3*4 2*4096*6=48828-6*4
if(flowIndex > (CALIB_MAX_INDEX - dataCompFac*4)) {
indexL += (CALIB_MAX_INDEX / dataCompFac - 1)*3;
ReadCalbrationDataFromMemory(indexL, &tempDev.Byte[0], 3);
2026-03-20 21:16:58 +08:00
tempDev.Byte[3] = 0;
return tempDev.DWord[0];
}
u16 index0, indexD, IndexA, IndexB, J=0, K;
u32 tempFR[4];
//u32
index0 = flowIndex / dataCompFac;
indexL += index0*3;
2026-03-20 21:19:53 +08:00
ReadCalbrationDataFromMemory(indexL-3, temp, 12);
2026-03-20 21:16:58 +08:00
tmpLA = 0;
tmpLB = 0xffffffff;
2026-03-20 21:19:53 +08:00
for(K=0, J=0; K<4; K++) {
2026-03-20 21:16:58 +08:00
tempL.Byte[0] = temp[J++];
tempL.Byte[1] = temp[J++];
tempL.Byte[2] = temp[J++];
tempL.Byte[3] = 0;
tempFR[K] = tempL.DWord;
2026-03-20 21:19:53 +08:00
if(tempL.DWord > tmpLA) {
2026-03-20 21:16:58 +08:00
tmpLA = tempL.DWord;
IndexA = K;
}
2026-03-20 21:19:53 +08:00
if(tempL.DWord < tmpLB) {
2026-03-20 21:16:58 +08:00
tmpLB = tempL.DWord;
IndexB = K;
}
}
2026-03-20 21:19:53 +08:00
for(K=0, J=0; K<4; K++) {
2026-03-20 21:16:58 +08:00
if(K == IndexA) continue;
if(K == IndexB) continue;
temp[J] = K;
J++;
}
IndexA = temp[0];
IndexB = temp[1];
tmpSLA = (u32)tempFR[IndexA];
tmpSLB = (u32)tempFR[IndexB];
IndexB = (IndexB - IndexA)*dataCompFac;
IndexA *= dataCompFac;
// (tmpLB-tmpLA)*indexD/dataCompFac + tmpLA
indexD = flowIndex - index0 * dataCompFac;
indexD += dataCompFac;
tmpSLB -= tmpSLA;
2026-03-20 21:19:53 +08:00
if(indexD > IndexA) {
2026-03-20 21:16:58 +08:00
tmpSLB *= (u32)(indexD-IndexA);
tmpSLB /= (u32)IndexB;
tmpSLA += tmpSLB;
}
2026-03-20 21:19:53 +08:00
else {
2026-03-20 21:16:58 +08:00
tmpSLB *= (u32)(IndexA-indexD);
tmpSLB /= (u32)IndexB;
tmpSLA -= tmpSLB;
}
if(tmpSLA < 0) return 0;
else return (u32)tmpSLA;
}
//******************************************************************************
u16 HalfWordMovingAverage(u16 *TPFilter, u16 shiftCompare, u16 updateScale)
{
u16 I, tempDelta;
//for(I=0; I<sumLen; I++) tempSum += (u32)*TPFilter++;
//return tempSum >> shiftBit;
tmpLA = 0;
for(I=0; I<filterDepth; I++) tmpLA += (u32)*(TPFilter+I);
tmpIA = (u16)(tmpLA >> filterShift);
if(shiftCompare > tmpIA) tempDelta = shiftCompare - tmpIA;
else tempDelta = tmpIA - shiftCompare;
tmpLA = (u32)tmpIA;
tmpLA *= (u32)updateScale;
tmpLA >>= 10;
if(tempDelta < (u16)tmpLA) return tmpIA;
for(I=0; I<filterDepth; I++) *TPFilter++ = shiftCompare;
return shiftCompare;
}
//******************************************************************************
u32 WordMovingAverage(u32 *TPFilter, u32 shiftCompare, u16 updateScale)
{
u16 I;
u32 tempDelta;
tmpLA = 0;
for(I=0; I<filterDepth; I++) tmpLA += (u32)*(TPFilter+I);
tmpLA >>= filterShift;
if(shiftCompare > tmpLA) tempDelta = shiftCompare - tmpLA;
else tempDelta = tmpLA - shiftCompare;
tmpLB = (u32)tmpLA;
tmpLB *= (u32)updateScale;
tmpLB >>= 10;
if(tempDelta < (u16)tmpLB) return tmpLA;
for(I=0; I<filterDepth; I++) *TPFilter++ = shiftCompare;
return shiftCompare;
}
//******************************************************************************
void GetFilterDepth(u16 timeIndex)
{
filterDepth = FilterMax[timeIndex] / FilterMax[samplingInterval];
switch(filterDepth)
{
case 1: filterShift = 0; break;
case 2: filterShift = 1; break;
case 4: filterShift = 2; break;
case 8: filterShift = 3; break;
case 16: filterShift = 4; break;
case 32: filterShift = 5; break;
default:
filterDepth = 1;
filterShift = 0;
break;
}
dataMask = filterDepth-1;
}
//******************************************************************************
u16 FlowRateIndexFilter(u16 filterANX, u16 updateScale)
{
FIndex++;
FIndex &= dataMask;
FIndexSample[FIndex] = voltageDetected[filterANX];
return HalfWordMovingAverage(&FIndexSample[0], voltageDetected[filterANX], updateScale);
}
/******************************************************************************/
void FlowRateMoving(void)
{
FRIndex++;
FRIndex &= dataMask;
flowSample[FRIndex] = flowRate;
flowRate = WordMovingAverage(&flowSample[0], flowRate, FLOWRATE_UPDATE_SCALE); // 1.5%
#ifndef ENABLE_LCD_DISPLAY
#pragma message("[undefined] ENABLE_LCD_DISPLAY")
#elif(ENABLE_LCD_DISPLAY)
GetFilterDepth(DISPLAY_FILTER_DEFAULT);
DisIndex++;
DisIndex &= dataMask;
DisSample[DisIndex] = displayUpdate;
displayUpdate = WordMovingAverage(&DisSample[0], displayUpdate, FLOWRATE_UPDATE_SCALE);
#endif
}
/******************************************************************************/
void CurrentFlowRateMoving(void)
{
FRIndex++;
FRIndex &= dataMask;
flowSample[FRIndex] = currentFlowRate;
currentFlowRate = WordMovingAverage(&flowSample[0], currentFlowRate, FLOWRATE_UPDATE_SCALE); // 1.5%
}
/******************************************************************************/
void DisplayFlowRateMoving(void)
{
GetFilterDepth(DISPLAY_FILTER_DEFAULT);
DisIndex++;
DisIndex &= dataMask;
DisSample[DisIndex] = displayUpdate;
displayUpdate = WordMovingAverage(&DisSample[0], displayUpdate, FLOWRATE_UPDATE_SCALE);
}
//******************************************************************************
void FlowRateAlarmJudgment(void)
{
u32 minAlarmFlowRate;
unsigned long long int alarmFlowRate;
// float tempFlow;
//maxFlowRate = 3500000;
// tempFlow = (float)maxFlowRate;
// tempFlow *= (float)MAX_ALRAM_FR_DEFAULT;
// maxAlarmFlowRate = (u32)tempFlow;
//===========================================================================
// <20>ж<EFBFBD><D0B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>У׼ʱ<D7BC><CAB1><EFBFBD><EFBFBD><EFBFBD>ķŴ<C4B7><C5B4><EFBFBD><EFBFBD><EFBFBD>
//maxAlarmFlowRate = maxFlowRate;
//maxAlarmFlowRate *= (u32)MAX_ALRAM_FR_DEFAULT; // 1.25*128 = 160;
//maxAlarmFlowRate >>= 7;
alarmFlowRate = (unsigned long long int)maxFlowRate;
alarmFlowRate *= (unsigned long long int)MAX_ALRAM_FR_DEFAULT;
alarmFlowRate >>= 7;
maxAlarmFlowRate = (u32)alarmFlowRate;
minAlarmFlowRate = minFlowRate;
//===========================================================================
#ifndef ENABLE_FLOW_GAIN
#pragma message("[undefined] ENABLE_FLOW_GAIN")
#elif(ENABLE_FLOW_GAIN)
maxAlarmFlowRate *= calibFlowGain;
minAlarmFlowRate *= calibFlowGain;
#endif
//===========================================================================
systemAlarm.Bit.FRAlarm = 0;
if(currentFlowRate > maxAlarmFlowRate) //1.25Qmax
{
systemAlarm.Bit.FRAlarm = 1;
currentFlowRate = maxAlarmFlowRate;
}
else if(currentFlowRate < minAlarmFlowRate) currentFlowRate = 0; // V2004
}
//******************************************************************************
#ifndef ENABLE_LEAK_DETECT
#pragma message("[undefined] ENABLE_LEAK_DETECT")
#elif(ENABLE_LEAK_DETECT)
void FlowRateLeakDetect(void)
{
if((alarmState1 & LEAK_ALARM)== LEAK_ALARM)
{
leakDetectCounter = 0;
leakDetectHighCounter = 0;
leakDetectLowCounter = 0;
#ifndef ENABLE_ERROR_PIN_FOR_VALVE_CONTROL
#pragma message("[undefined] ENABLE_ERROR_PIN_FOR_VALVE_CONTROL")
#elif(ENABLE_ERROR_PIN_FOR_VALVE_CONTROL)
ERROR_PIN_OUTPUT();
TURN_OFF_VALVE();
alarmState1 |= VALVE_OFF_ALARM;
#endif
return;
}
2026-03-20 21:19:53 +08:00
// if((leakDetectTime == 0) || (sampleState.EnableRoughTest))
// {
// leakDetectCounter = 0;
// leakDetectHighCounter = 0;
// leakDetectLowCounter = 0;
// return;
// }
2026-03-20 21:16:58 +08:00
//---------------------------------------------------------------------------
if(flowRate < minLeakFlowRate)
{
leakDetectLowCounter++;
leakDetectHighCounter = 0;
if(leakDetectLowCounter > 4)
{
leakDetectLowCounter = 0;
leakDetectCounter = 0;
}
return;
}
else if(flowRate > maxLeakFlowRate)
{
leakDetectHighCounter++;
leakDetectLowCounter = 0;
if(leakDetectHighCounter > 4)
{
leakDetectHighCounter = 0;
leakDetectCounter = 0;
}
return;
}
leakDetectHighCounter = 0;
leakDetectLowCounter = 0;
if(leakDetectCounter > leakDetectTime)
{
leakDetectCounter = leakDetectTime;
alarmState1 |= LEAK_ALARM;
#ifndef ENABLE_ERROR_PIN_FOR_VALVE_CONTROL
#pragma message("[undefined] ENABLE_ERROR_PIN_FOR_VALVE_CONTROL")
#elif(ENABLE_ERROR_PIN_FOR_VALVE_CONTROL)
ERROR_PIN_OUTPUT();
TURN_OFF_VALVE();
alarmState1 |= VALVE_OFF_ALARM;
#endif
}
}
#endif