PID CONT_C AVR

: 2015-03-15

:

:



pid avr



\ PLC ( Siemens S7-200..S7-400), () AVR.. (DS18B20 + ATTiny85) PID. Atmel (AVR221) . .



PID Control, , .



, FB41 SCL . ATTiny85 (!) . , . 8 FB41 0.8-1.2 . , , \, D ...



, . , , . 32-bit ARM .





readme.txt




1.
PVPER_ON
PV_PER ()
PV_FAC ()
PV_OFF ()
 
2.
LMN_PER ()
 
3.
DEADB_W
if (ErKp < (-DEADB_W))
ER = ErKp + DEADB_W; //
else if (ErKp > DEADB_W)
ER = ErKp - DEADB_W; // .
else
ER = 0.0; // .
 
4. sRestInt. 295 180uS
5. sRestDif. 435 320uS





FB41.c



//*****************************************************************************
// File Name : FB41.c
// Title : FB41 - PID
// Description : FUNCTION_BLOCK FB41
// FAMILY : ICONT
// NAME : CONT_C
// PID = 1.65mS
// PID = 1.3mS
// Author : SIMATIC. Reversed by komatic. Serj (phreak_ua@yahoo.com)
// Created : 06.12.2014
// Revised : 06.12.2014
// Version : 1.5
// Target MCU : Atmel AVR ATMega128
// Compiler : IAR C/C++ Compiler for AVR v.6.10.1 (6.10.1.50424)
// Editor Tabs : 2
//*****************************************************************************
#define FB41_C_
 
#include <ioavr.h>
//#include <intrinsics.h>
#include "avrlibtypes.h"
#include "FB41.h"
#include "debug.h"
 
 
//*****************************************************************************
/*
VAR_INPUT
COM_RST : BOOL ; //
MAN_ON : BOOL := TRUE; //
PVPER_ON : BOOL ; //
P_SEL : BOOL := TRUE; //
I_SEL : BOOL := TRUE; //
INT_HOLD : BOOL ; //
I_ITL_ON : BOOL ; //
D_SEL : BOOL ; //
CYCLE : TIME := T#1S; //
SP_INT : REAL ; //
PV_IN : REAL ; //
PV_PER : WORD ; // ()
MAN : REAL ; //
GAIN : REAL := 2.000000e+000; //
TI : TIME := T#20S; //
TD : TIME := T#10S; //
TM_LAG : TIME := T#2S; //
DEADB_W : REAL ; //
LMN_HLM : REAL := 1.000000e+002; //
LMN_LLM : REAL ; //
PV_FAC : REAL := 1.000000e+000; // ()
PV_OFF : REAL ; // ()
LMN_FAC : REAL := 1.000000e+000; // ()
LMN_OFF : REAL ; // ()
I_ITLVAL : REAL ; //
DISV : REAL ; //
END_VAR
VAR_OUTPUT
LMN : REAL ; //
LMN_PER : WORD ; // ()
QLMN_HLM : BOOL ; //
QLMN_LLM : BOOL ; //
LMN_P : REAL ; //
LMN_I : REAL ; //
LMN_D : REAL ; //
PV : REAL ; //
ER : REAL ; //
END_VAR
*/
 
//VAR
REAL sInvAlt ;//: REAL ;
REAL sIanteilAlt ;//: REAL ;
REAL sRestInt ;//: REAL ;
//REAL sRestDif ;//: REAL ; // sRestDif
REAL sRueck ;//: REAL ;
REAL sLmn ;//: REAL ;
BOOL sbArwHLmOn ;//: BOOL ; //
BOOL sbArwLLmOn ;//: BOOL ; //
BOOL sbILimOn = TRUE ;//: BOOL := TRUE;
REAL HALF_CYCLE ;
//END_VAR
 
//VAR_TEMP
///REAL rCycle ;//: REAL ; //Abtastzeit in real
REAL Diff ;//: REAL ; // (Anderungswert)
///REAL Istwert ;//: REAL ; //Istwert
REAL ErKp ;//: REAL ; //
REAL rTi ;//: REAL ; // (Integrationszeit) in real
REAL rTd ;//: REAL ; //Differentiationszeit in real
REAL rTmLag ;//: REAL ; // (Verzgerungszeit) in real
REAL Panteil ;//: REAL ; //P-Anteil
REAL Ianteil ;//: REAL ; //I-Anteil
REAL Danteil ;//: REAL ; //D-Anteil
REAL Verstaerk ;//: REAL ; // (Verstrkung)
REAL RueckDiff ;//: REAL ; // (Differenz des Rckkopplungswertes)
REAL RueckAlt ;//: REAL ; //, (Alter) (Rckkopplungswert)
REAL dLmn ;//: REAL ; // (Stellwert)
REAL gf ;//: REAL ; //Hilfwert
REAL rVal ;//: REAL ; //Real Hilfsvariable
//END_VAR
 
/*****************************************************************************************
*
* param:
*
* return:
*****************************************************************************************/
void FC41 (void)
{
T21;
if (COM_RST) {
//
sIanteilAlt = I_ITLVAL;
LMN = 0.0; //
QLMN_HLM = 0; //
QLMN_LLM = 0; //
LMN_P = 0.0; //
LMN_I = 0.0; //
LMN_D = 0.0; //
/// LMN_PER = 0; // ()
/// PV = 0.0; //
ER = 0.0; //
sInvAlt = 0.0;
sRestInt = 0.0;
// sRestDif = 0.0; // sRestDif
sRueck = 0.0;
sLmn = 0.0;
sbArwHLmOn = 0;
sbArwLLmOn = 0;
HALF_CYCLE = CYCLE * 0.5;
}
else {
T31;
if (SP_INT != PV_IN)
// ErKp = SP_INT - PV_IN; //
ER = SP_INT - PV_IN; //
else
// ErKp = 0.0;
ER = 0.0;
 
// if (ErKp < (-DEADB_W))
// ER = ErKp + DEADB_W; //
// else if (ErKp > DEADB_W)
// ER = ErKp - DEADB_W; // .
// else
// ER = 0.0; // .
T30;
T31;
ErKp = ER * GAIN; // ,
rTi = TI; //
rTd = TD; //
rTmLag = TM_LAG; // .
T30;
//
// IF rTi < (rCycle * 0.5) THEN rTi = rCycle * 0.5; END_IF; // - Cycle / 2
// IF rTd < rCycle THEN rTd = rCycle; END_IF; // - Cycle
// IF rTmLag < rCycle * 0.5 THEN rTmLag = rCycle * 0.5; END_IF; // ..- Cycle / 2
T31;
if (rTi < HALF_CYCLE)
rTi = HALF_CYCLE; // - Cycle / 2
if (rTd < CYCLE)
rTd = CYCLE; // - Cycle
if (rTmLag < HALF_CYCLE)
rTmLag = HALF_CYCLE; // ..- Cycle / 2
T30;
T20;//282uS
//---------------------------------------------------------------------------------------------
//
//---------------------------------------------------------------------------------------------
T21;
if (P_SEL)
Panteil = ErKp; //
else
Panteil = 0.0;
T20;//3.5uS
//---------------------------------------------------------------------------------------------
//
//---------------------------------------------------------------------------------------------
T21;
if (I_SEL) {
if (I_ITL_ON) { //
Ianteil = I_ITLVAL;
sRestInt = 0.0;
}
else {
if (MAN_ON) { //
Ianteil = sLmn - Panteil - DISV;
sRestInt = 0.0;
}
else { //
// Diff = CYCLE / rTi *(ErKp + sInvAlt) * 0.5 + sRestInt;
// Diff = HALF_CYCLE / rTi *(ErKp + sInvAlt) + sRestInt; // HALF_CYCLE (=CYCLE*0.5) 388 295uS
Diff = HALF_CYCLE / rTi *(ErKp + sInvAlt); // sRestInt. 295 180uS
if (( (Diff>0.0) && sbArwHLmOn || INT_HOLD) || ((Diff<0.0) && sbArwLLmOn))
Diff = 0.0;
Ianteil = sIanteilAlt + Diff;
// sRestInt = sIanteilAlt - Ianteil + Diff; // sRestInt.
}
}
}
else {
Ianteil = 0.0;
sRestInt = 0.0;
}
T20;//388uS => 180uS
//---------------------------------------------------------------------------------------------
//
//---------------------------------------------------------------------------------------------
T21;
Diff = ErKp;
if ((!MAN_ON) && D_SEL) {
T31;
Verstaerk = rTd / (HALF_CYCLE + rTmLag);
Danteil = (Diff - sRueck) * Verstaerk;
RueckAlt = sRueck;
// RueckDiff = CYCLE / rTd * Danteil + sRestDif;
RueckDiff = CYCLE / rTd * Danteil; // sRestDif. 435 320uS
sRueck = RueckDiff + RueckAlt;
// sRestDif = RueckAlt - sRueck + RueckDiff; // sRestDif
T30;
}
else {
Danteil = 0.0;
// sRestDif = 0.0; // sRestDif
sRueck = Diff;
}
T20;//435uS => 320uS
//---------------------------------------------------------------------------------------------
//
//---------------------------------------------------------------------------------------------
T21;
dLmn = Panteil + Ianteil + Danteil + DISV;
if (MAN_ON) { //
dLmn = MAN; //
}
else {
// IF (NOT I_ITL_ON) AND I_SEL
if ((!I_ITL_ON) && I_SEL) {
// IF (Ianteil > (LMN_HLM - DISV)) AND (dLmn > LMN_HLM) AND ((dLmn - LMN_D)> LMN_HLM)
if ((Ianteil > (LMN_HLM - DISV)) && (dLmn > LMN_HLM) && ((dLmn - LMN_D)> LMN_HLM)) {
rVal = LMN_HLM - DISV;
gf = dLmn - LMN_HLM;
rVal = Ianteil - rVal;
if (rVal > gf)
rVal = gf;
Ianteil = Ianteil - rVal;
}
else {
// IF (Ianteil < (LMN_LLM - DISV)) AND (dLmn < LMN_LLM) AND ((dLmn - LMN_D) < LMN_LLM)
if ((Ianteil < (LMN_LLM - DISV)) && (dLmn < LMN_LLM) && ((dLmn - LMN_D) < LMN_LLM)) {
rVal = LMN_LLM - DISV;
gf = dLmn - LMN_LLM;
rVal = Ianteil - rVal;
if (rVal < gf)
rVal = gf;
Ianteil = Ianteil - rVal;
}
}
}
}
T20;//89uS
T21;
LMN_P = Panteil;
LMN_I = Ianteil;
LMN_D = Danteil;
sInvAlt = ErKp;
sIanteilAlt = Ianteil;
sbArwHLmOn = 0;
sbArwLLmOn = 0;
 
if (dLmn >= LMN_HLM) {
QLMN_HLM = 1;
QLMN_LLM = 0;
dLmn = LMN_HLM;
sbArwHLmOn = 1;
}
else {
QLMN_HLM = 0;
if (dLmn <= LMN_LLM) {
QLMN_LLM = 1;
dLmn = LMN_LLM;
sbArwLLmOn = 1;
}
else {
QLMN_LLM = 0;
}
}
 
sLmn = dLmn;
dLmn = sLmn * LMN_FAC + LMN_OFF;
LMN = dLmn;
T20;//77uS
/*
//
// 0.0...100.0 => 0...27648
dLmn = LMN * 2.764800e+002;
 
if (dLmn >= 3.251100e+004)
dLmn = 3.251100e+004;
else
if (dLmn <= -3.251200e+004)
dLmn = -3.251200e+004;
 
LMN_PER = (int)dLmn;
*/
 
}
}
 
 
/*****************************************************************************************
*
* param:
*
* return:
*****************************************************************************************/
void FC41_Init (void)
{
COM_RST = FALSE ;//: BOOL ; //
MAN_ON = FALSE ;//: BOOL := TRUE; //
/// PVPER_ON = FALSE ;//: BOOL ; //
P_SEL = TRUE ;//: BOOL := TRUE; //
I_SEL = TRUE ;//: BOOL := TRUE; //
INT_HOLD = FALSE ;//: BOOL ; //
I_ITL_ON = FALSE ;//: BOOL ; //
D_SEL = TRUE ;//: BOOL ; //
CYCLE = 0.005 ;//: TIME := T#1S; //
SP_INT = 0.0 ;//: REAL ; //
PV_IN = 0.0 ;//: REAL ; //
/// PV_PER = 0 ;//: WORD ; // ()
MAN = 0.0 ;//: REAL ; //
GAIN = 0.52 ;//: REAL := 2.000000e+000; //
TI = 0.11 ;//: TIME := T#20S; //
TD = 0.25 ;//: TIME := T#10S; //
TM_LAG = 2.0 ;//: TIME := T#2S; //
DEADB_W = 0.0 ;//: REAL ; //
LMN_HLM = 100.0 ;//: REAL := 1.000000e+002; //
LMN_LLM = 0.0 ;//: REAL ; //
/// PV_FAC = 1.0 ;//: REAL := 1.000000e+000; // ()
/// PV_OFF = 0.0 ;//: REAL ; // ()
LMN_FAC = 1.0 ;//: REAL := 1.000000e+000; // ()
LMN_OFF = 0.0 ;//: REAL ; // ()
I_ITLVAL = 0.0 ;//: REAL ; //
DISV = 0.0 ;//: REAL ; //
HALF_CYCLE = CYCLE * 0.5;
}
 





(zip, 6Mb)

(pdf, 7Mb)


- mail







: 4241

:     : 2015-03-17

(DS18B20 + ATTiny85) PID ? ?

: komatic    : 2015-03-17

, email

:     : 2015-03-18

.
.

:     : 2015-03-22

, .
AVR+DS1820: , . . PID (50). (0, 0.1...99.9, 100 % ==> 0, 1...999, 1000 , = 1). . , ( 1%) , .
, , . ( IAR), + (Altium + pdf) + .

:     : 2015-10-13

!

:

(4000 max):

: