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

417 lines
12 KiB
C
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 = DATA_COMP_FAC;
// indexL = CALI_DATA_ADDR;
if(flowIndex > 32767) return 0;
// else if(flowIndex < zeroSuppression) return 0;
else if(flowIndex >= CALIB_MAX_INDEX) flowIndex = CALIB_MAX_INDEX; //MAX_INDEX
dataCompFac = CALIB_COMP_FAC;
//indexL = (CORRECT_DATA_ADDR&0xFFFF);
indexL = 0 ;//从CORRECT_DATA[0]开始相当于从0地址开始取
break;
//------------------------------------------------------------------------
#ifndef ENABLE_2ND_CURVE
#pragma message("[undefined] ENABLE_2ND_CURVE")
#elif(ENABLE_2ND_CURVE)
case CURVE_2ND:
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 >= MAX_INDEX3) flowIndex = CALIB_MAX_INDEX;
dataCompFac = DATA_COMP_FAC3;
indexL = CALI_DATA3_ADDR;
break;
#endif
default: return 0;
}
if(flowIndex > (CALIB_MAX_INDEX - dataCompFac*4))//240000-3*4 2*4096*6=48828-6*4
{
indexL += (CALIB_MAX_INDEX / dataCompFac - 1)*3;
//ReadMultiByteFromEEPROM(indexL, &tempDev.Byte[0], 3, PARA_EEPROM);
ReadDataFromFlash(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;
//ReadMultiByteFromEEPROM(indexL-3, temp, 12, PARA_EEPROM);
ReadDataFromFlash(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;
//===========================================================================
// 判断最大流量门限值,考虑校准时流量的放大倍数
//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
//******************************************************************************
#ifndef ENABLE_USER_UART
#pragma message("[undefined] ENABLE_USER_UART")
#elif(ENABLE_FLOW_GAIN)
u16 JudgeFlowRateGain(u16 flowGain)
{
switch(flowGain)
{
case 1: return 0;
//--------------------------------------------------------------------------
#ifndef FLOW_GAIN_MAX
#pragma message("[undefined] FLOW_GAIN_MAX")
#elif(FLOW_GAIN_MAX >= 10)
case 10: return 0;
#endif
//--------------------------------------------------------------------------
#ifndef FLOW_GAIN_MAX
#pragma message("[undefined] FLOW_GAIN_MAX")
#elif(FLOW_GAIN_MAX >= 100)
case 100: return 0;
#endif
//--------------------------------------------------------------------------
#ifndef FLOW_GAIN_MAX
#pragma message("[undefined] FLOW_GAIN_MAX")
#elif(FLOW_GAIN_MAX >= 1000)
case 1000: return 0;
#endif
default: return 1;
}
}
#endif