Files
CHJ/user/Compute/FlowRateCompute.c
2026-03-20 21:16:58 +08:00

364 lines
11 KiB
C
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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;
else if(flowIndex < zeroSuppression) return 0;
else if(flowIndex >= CALIB_MAX_INDEX) flowIndex = CALIB_MAX_INDEX;
dataCompFac = CALIB_COMP_FAC;
indexL = CALI_DATA_ADDR;
break;
//------------------------------------------------------------------------
#ifndef ENABLE_2ND_CURVE
#pragma message("[undefined] ENABLE_2ND_CURVE")
#elif(ENABLE_2ND_CURVE)
case CURVE_2ND:
dataCompFac = CALIB_COMP_FAC2;
indexL = CALI_DATA2_ADDR;
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;
else if(flowIndex >= CALIB_MAX_INDEX3) flowIndex = CALIB_MAX_INDEX;
dataCompFac = CALIB_COMP_FAC3;
indexL = CALI_DATA3_ADDR;
break;
#endif
default: return 0;
}
//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);
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;
ReadCalbrationDataFromMemory(indexL-3, temp, 12);
tmpLA = 0;
tmpLB = 0xffffffff;
for(K=0, J=0; K<4; K++) {
tempL.Byte[0] = temp[J++];
tempL.Byte[1] = temp[J++];
tempL.Byte[2] = temp[J++];
tempL.Byte[3] = 0;
tempFR[K] = tempL.DWord;
if(tempL.DWord > tmpLA) {
tmpLA = tempL.DWord;
IndexA = K;
}
if(tempL.DWord < tmpLB) {
tmpLB = tempL.DWord;
IndexB = K;
}
}
for(K=0, J=0; K<4; K++) {
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;
if(indexD > IndexA) {
tmpSLB *= (u32)(indexD-IndexA);
tmpSLB /= (u32)IndexB;
tmpSLA += tmpSLB;
}
else {
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;
}
// if((leakDetectTime == 0) || (sampleState.EnableRoughTest))
// {
// leakDetectCounter = 0;
// leakDetectHighCounter = 0;
// leakDetectLowCounter = 0;
// return;
// }
//---------------------------------------------------------------------------
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