'* asngDataValue(0) = PV
'* asngDataValue(1) = SV
'* asngDataValue(2) = OP
'* asngDataValue(3) = P
'* asngDataValue(4) = I
'* asngDataValue(5) = D
' sngParP = 250 '* 比例系数P
' sngParI = 50 '* 积分系数I
' sngParD = 5 '* 微分系数D
' sngPvMin = 0 '* PV 值下限
' sngPvMax = 300 '* PV 值上限
' sngSvMin = 0 '* SV 值下限
' sngSvMax = 300 '* SV 值上限
' sngOpMin = 0 '* OP 值下限
' sngOpMax = 100 '* OP 值上限
' sngChangeMin = 1 '* 死区范围
' sngChangeMax = 10 '* 调节范围
' sngOutPutMax = 80 '* 超调时输出
' sngCtlDirection = 1 '* 调节方向
' sngControlT = 100 '* PID的调控周期,和设备的采集周期相同
' Dim sngPVRange '* PV值的量程
' Dim sngOutdx '* PID计算出的输出增加值
'
' '* 确保控制周期不为0
If sngControlT = 0 Then sngControlT = 1
' '* 计算PV值的量程,并确保其不为0
sngPVRange = sngPvMax - sngPvMin
If sngPVRange <= 0 Then sngPVRange = 1
' '* 把超调值由百分比转换成实际物理量
' sngChangeMax = sngPVRange * sngChangeMax / 100
'* ======================================================================================
' '* PV值和SV值必须在设定的限值范围之内
' If sngPv < sngPvMin Then sngPv = sngPvMin
' If sngPv > sngPvMax Then sngPv = sngPvMax
' If sngSv < sngSvMin Then sngSv = sngSvMin
' If sngSv > sngSvMax Then sngSv = sngSvMax
If sngPv < 0 Then sngPv = 0
If sngPv > 300 Then sngPv = 300
If sngSv < 0 Then sngSv = 0
If sngSv > 300 Then sngSv = 300
' * =================================================================================================
' * 计算SV和PV值的差值,第一次计算时,取m_sngSvPvdx1、m_sngSvPvdx2值和m_sngSvPvdx相同
' m_sngSvPvdx '* 本次调控时SV和PV值的差值
' m_sngSvPvdx1 '* 上次调控时SV和PV值的差值
' m_sngSvPvdx2 '* 调控过程中SV和PV值的差值的累计和
m_sngSvPvdx = sngSv - sngPv
'设定m_sngSvPvdx1的初值为111111;标记是否第一次进行PID计算,防止m_sngSvPvdx和1m_sngSvPvdx2的值为0
If m_sngSvPvdx1 = 111111 Then
m_sngSvPvdx1 = m_sngSvPvdx
m_sngSvPvdx2 = m_sngSvPvdx
EndIf
'* 进行PID运算,sngParI=0 和 sngParI<>0的算法不一样
'sngControlT :调节周期,和设备的采集周期相同(单位为:秒)
If sngParI <> 0 Then
sngOutdx = sngParP * (m_sngSvPvdx - m_sngSvPvdx1 + m_sngSvPvdx * sngControlT / sngParI + (m_sngSvPvdx - 2 * m_sngSvPvdx1 + m_sngSvPvdx2) * sngParD / sngControlT)
Else
sngOutdx = sngParP * (m_sngSvPvdx - m_sngSvPvdx1 + (m_sngSvPvdx - 2 * m_sngSvPvdx1 + m_sngSvPvdx2) * sngParD / sngControlT)
EndIf
m_sngSvPvdx2 = m_sngSvPvdx1
m_sngSvPvdx1 = m_sngSvPvdx
'* 处在死区范围,输出值保持不变
If !Abs(m_sngSvPvdx) < !Abs(sngChangeMin) Then sngOutdx = 0
'* 当PID控制的调节方向方向不一样时,输出值的处理方法不一致
If sngCtlDirection = 1 Then
sngOP = sngOP + sngOutdx
'* 正向控制时的超调处理
If !Abs(m_sngSvPvdx) >= sngChangeMax And sngChangeMax > 0 Then
If m_sngSvPvdx > 0 Then sngOP = sngOutPutMax
EndIf
Else
sngOP = sngOP - sngOutdx
'* 反向控制时的超调处理
If !Abs(m_sngSvPvdx) >= sngChangeMax And sngChangeMax > 0 Then
If m_sngSvPvdx < 0 Then sngOP = sngOutPutMax
EndIf
EndIf
'* OP值必须在设定的限值范围之内
'If sngOP < sngOpMin Then sngOP = sngOpMin
'If sngOP > sngOpMax Then sngOP = sngOpMax
If sngOP < 0 Then sngOP = 0
If sngOP > 100 Then sngOP = 100
!SaveDataInit()
!SaveSingleDataInit(sng1ParP)
!SaveSingleDataInit(sng1ParI)
!SaveSingleDataInit(sng1ParD)
!SaveData(sng1OP )
outputwater =sngOp/10
sngPv=sngPv+inputwater/100-outputwater
if sngPv>100 then
sngPv=100
endif
if sngPv<=0 then
sngPv=0
endif
k1=1
if inputwater <=0 then k1=0
k2=1
if outputwater<=0 then k2=0