INOS
Control

Overview

The control classes of INOS are responsible for all kinds of control work except axes handling which is documented under Motion. The main focus lies currently on temperature control.

dot_inline_dotgraph_8.png

Overview of all classes which are involved in controller handling of INOS. Clicking on a class directs to the corresponding class documentation.

As shown in the class diagram, a control instance is represented by the class CINOSControl. It has two parts :

General

A control instance is created dynamically via the INCO tree and is usually done with our good old stream file mechanism. Refere to the temperature controller for an example.

Control.Cmd.Create(Name, TrajectoryType, ControllerType, InputName, OutputName)

The values have the following meaning :

  • Name The controller name
  • TrajectoryType The trajectory type. Valid types are INOSJerk, INOSTrapeze or an own customer specific type
  • ControllerType The controller type. Valid types are INOSPid, INOSTemp, INOS2Pt or an own customer specific type
  • InputName The controller input name
  • OutputName The controller output name

Example :

Control.Cmd.Create("Zone0","INOSJerk","INOSTemp","ADP_02.AI_02_00","ADP_02.DO_02_00")

This call creates a control instane named 'Zone0' with a jerk ramp trajectory generator and a controller of type INOSTemp. The name of the input channel (in this case the name of the temperature process image value) is ADP_02.AI_02_00. The name of the command output (in this case a digital output) is ADP_02.DO_02_00.

To be able to use the digital output as a pseudo 'analog' output, one has the possibility tell the system to handle it as a software PWM (pulse wide modulation). This can be done like this :

Example of a pwmoutput.dt2:

// ! table-name
INOS-OUT-PWM
// ! table-data-record-start
Name; text_32; "ADP_02.DO_02_00";
SyncName; text_32; "ADP_02.DI_02_00";
SwitchTime; uint32; 10000;
SwitchTime60Hz; uint32; 8000;
SyncShift; uint32; 2000;
Average; uint32; 100;

The values have the following meaning :

  • Name The name of the digital output
  • SyncName If the PWM has to be synchronized to the 230V/110V power, one can define here the name of the digital input which provides the power sync signal
  • SwitchTime The fastest switching time [us], usually this is 10000us for a 230V/50Hz environment if one is working with a solid state relais
  • SwitchTime60Hz The fastest switching time [us], usually this is 8000us for a 110V/60Hz environment if one is working with a solid state relais
  • SyncShift If a sync input is involved, this is the time [us] between sync and output set, 2000us is usually a good choice
  • Average Smoothen the the power output over this number of cylces (0 if not used)

Setting the INOS system variable

INOS.OutPwm5060Detection = "yes"

enables an automatic power frequency detection. This feature is only useful and available if there is at least one out pwm channel defined with a configured synchronisation input.

If no 60 Hz switching time is configured (SwitchTime60Hz not defined), a default value of 8000us is used. For information purposes, the detected frequency is available in the INCO tree here :

Image.Digital.Output.xxx.Pwm.Power

Temperature control

The temperature controller bases on a standard PID controller with some temperature related optimizations, like

  • heat capacity support to improve as fast as possible jumps to a new commanded temperature
  • support for the Stefan Boltzmann law (see https://en.wikipedia.org/wiki/Stefan-Boltzmann_law)
  • several feed forward possibilities
  • alarm temperature support
  • asymmetric integrator limitation
  • temperature dependent PID parameter sets
  • different PID parameter sets for 'run' and 'halt'
  • ...

Properties

The properties are described in the following section. To get stared, just copy the section below to a new file, name it something like myzone.stream and put the file into the config section of your project.

// Controller creation
//
// Zone0 : Controller name
// INOSJerk : Type of ramp geni
// INOSTemp : Type of controller
// ADP_02.AI_02_00 : Name of temperature channel
// ADP_02.DO_02_00 : Name of digital output
//
Set ZONE0="Control.Entity.Zone0"
Control.Cmd.Create("Zone0","INOSJerk","INOSTemp","ADP_02.AI_02_00","ADP_02.DO_02_00");
//
// ActOutput
//
// Name of a digital output which has to be set if controller is active (empty if not used)
//
#{ZONE0}.Prop.ActOutput=""
//
// ErrorMask
//
// Possibility to mask out errors. The mask can be set either as a 32 bit value or by
// setting a single bit, e.g. #{ZONE0}.ErrorMask.FieldBus=1
//
#{ZONE0}.ErrorMask=0x00000000
//
// ErrorDis
//
// Possibility to define disabling errors, which end up in an inactivation of the
// controller. Can be set either as a 32 bit value or a single bit.
//
#{ZONE0}.ErrorDis=0xffffffff
//
// WarningMask
//
// Possibility to mask out warnings. Can be set either as a 32 bit value or a single bit.
//
#{ZONE0}.WarningMask=0x00000000
//
// CycleTime [ms]
//
// Should correspond to the cycletime of the temperature channel
//
#{ZONE0}.Prop.CycleTime=10.0
//
// EnbOutput
//
// Name of a digital output (or internal flag) which has to be cleared in case of an
// error. This 'output' also allows to group controllers. Controllers with
// the same EnbOutput name, set their 'group' error if EnbOutput is cleared by an
// other controller (empty if not used).
//
#{ZONE0}.Prop.EnbOutput=""
//
// Test values, used for toggle tests
//
#{ZONE0}.Cmd.Test.cmdVal1=100.0
#{ZONE0}.Cmd.Test.cmdVal2=150.0
//
// Ramp configuration. Setting V, A, B = 0 means, that the controller 'jumps' to the
// requested new temperature instead of ramping to it.
//
#{ZONE0}.Ramp.Cmd.cmdV=0.0
#{ZONE0}.Ramp.Cmd.cmdA=0.0
#{ZONE0}.Ramp.Cmd.cmdB=0.0
#{ZONE0}.Ramp.Cmd.cmdJ=0.0
//
// minS [°C]
//
// Minimal allowed commanded temperature.
//
#{ZONE0}.Ramp.Max.minS=40
//
// maxS [°C]
//
// Maximal allowed commanded temperature.
//
#{ZONE0}.Ramp.Max.maxS=300
//
// maxV [°C/sec]
//
// Maximal allowed commanded V. This value is also used to detect max. deltaT
// error. If the controller detects a temperature change with a V > 2*maxV, a
// 'DeltaTemp' error is initiated.
//
#{ZONE0}.Ramp.Max.maxV=40.0
//
// ErrorMask
//
// Possibility to mask out errors. Can be set either as a 32 bit value or a single bit.
//
#{ZONE0}.Control.ErrorMask=0x00000000
//
// ErrorDis
//
// Possibility to define disabling errors, which end up in an inactivation of the
// controller. Can be set either as a 32 bit value or a single bit.
//
#{ZONE0}.Control.ErrorDis=0xFFFFFFFF
//
// WarningMask
//
// Possibility to mask out warnings. Can be set either as a 32 bit value or a single bit.
//
#{ZONE0}.Control.WarningMask=0x00000000
//
// LimInput
//
// Name of a digital input which is set if an external supervision instance reports
// temperature limit reached (empty if not used)
//
#{ZONE0}.Control.Prop.LimInput=""
//
// Vfilter
//
// V filter length. A value between 4 and 10 is normally a good choice.
//
#{ZONE0}.Control.Prop.Vfilter=10
//
// DelayToHalt [ms]
//
// Time in [ms] the controller waits after commanded temperature reached till it
// changes to 'settling' state.
//
#{ZONE0}.Control.Prop.DelayToHalt=1000
//
// SettleTime [ms]
//
// If the actual Serr (Scmd-Sact) is for 'SettleTime' ms smaller than 0.5*maxSerr,
// the Move to the new temperature is marked as done.
//
#{ZONE0}.Control.Prop.SettleTime=4000
//
// SettleTimeout [ms]
//
// Max. allowed settling time. If exeeded the controller initiates a 'settling'
// error.
//
#{ZONE0}.Control.Prop.SettleTimeout=120000
//
// ActivateTimeout [ms]
//
// Max. allowed time an activation can take. If exeeded the controller initiates
// a 'Activate' error. The activation is done if the above described 'settled'
// condition is ok.
//
#{ZONE0}.Control.Prop.ActivateTimeout=120000
//
// haltT [delta °C]
//
// If Scmd-Sact is < haltT, the controller goes into 'settling state'
//
#{ZONE0}.Control.Prop.haltT=2.0
//
// alarmT [°C]
//
// If Sact becomes >= alarmT, the controller initiates an 'AlmTemp' error.
//
#{ZONE0}.Control.Prop.alarmT=310.0
//
// alarmThyst [delta °C]
//
// After an alarm T error, the controller can not be reactivated until Sact
// is < alarmT-alarmThyst
//
#{ZONE0}.Control.Prop.alarmThyst=5.0
//
// breakT [°C]
//
// If Sact becomes >= breakT, the controller initiates an 'SnrBreak' (sensor
// break) error. This is only used if the according hardware doesn't support
// sensor break detection.
//
#{ZONE0}.Control.Prop.breakT=330.0
//
// maxOut [%]
//
// Max. allowed controller output.
//
#{ZONE0}.Control.Prop.maxOut=100
//
// minOut [%]
//
// Max. allowed controller output.
//
#{ZONE0}.Control.Prop.minOut=0
//
// fctOut [*]
//
// Output factor [% * factor = output)
//
#{ZONE0}.Control.Prop.fctOut=1
//
// minTint
//
// Lower PID integrator limit.
//
#{ZONE0}.Control.Prop.minTint=0
//
// maxTint
//
// Upper PID integrator limit.
//
#{ZONE0}.Control.Prop.maxTint=100
//
// maxSerr [°C]
//
// Max. allowed Scmd-Sact in state 'halt'.
//
#{ZONE0}.Control.Prop.maxSerr=2.0
//
// maxSerr [°C]
//
// Max. allowed Scmd-Sact in state 'run'.
//
#{ZONE0}.Control.Prop.maxSerrRun=30.0
//
// EnbBoltzmann [flag] (https://en.wikipedia.org/wiki/Stefan-Boltzmann_law)
//
// If set to 1 -> the controller enables the so called 'boltzmann' feedforward.
// ffBlz = d*A*T^4 (d=5.670*10^-8)
//
#{ZONE0}.Control.Flag.EnbBoltzmann=1.0
//
// Always zero PID integrator in case we're jumping to a new commanded temperature
//
#{ZONE0}.Control.Flag.IntegratorZeroAtJump=1.0
//
// blzP [%]
//
// Power at blzTmax.
//
#{ZONE0}.Control.Prop.blzP=12.0
//
// blzTmin [°C]
//
// Feedforward = 0.0 at this temperature.
//
#{ZONE0}.Control.Prop.blzTmin=20.0
//
// blzTmax [°C]
//
// Feedforward = blzP at this temperature.
//
#{ZONE0}.Control.Prop.blzTmax=300.0
//
// hcpFactor
//
// Used during 'jump' to a new commanded temperature. This factor can be evaluated
// with the tune type 'Hcp'. Tune("Type=Hcp");
//
#{ZONE0}.Control.Prop.hcpFactor=1.757
//
// Tune hcpFactor
//
// Use a 1 sec pulse of 100%
//
#{ZONE0}.Control.Tune.Pulse.Power=100
#{ZONE0}.Control.Tune.Pulse.Time=1000
#{ZONE0}.Control.Tune.Pulse.Timeout=30000
//
// OutDelta [°C], OutTimeout [ms]
//
// They are used to detect an 'output failure' in case of a jump to a new
// commanded temperature. They have the following meaning : After 'OutTimeout'
// ms a minimal temperature change of 'OutDelta' is requested, otherwise the
// controller emits an 'output failure' error.
//
#{ZONE0}.Control.Prop.OutDelta=1.0
#{ZONE0}.Control.Prop.OutTimeout=30000.0
//
// Low range pid parameters. Low range goes from #{ZONE0}.Ramp.Max.minS till
// #{ZONE0}.Control.Pid.Run.Medium
//
#{ZONE0}.Control.Pid.Halt.Low.Kp=3.0
#{ZONE0}.Control.Pid.Halt.Low.Ki=1400.0
#{ZONE0}.Control.Pid.Halt.Low.Kd=350.0
#{ZONE0}.Control.Pid.Halt.Low.ffS=0.0
#{ZONE0}.Control.Pid.Halt.Low.ffSoffset=0.0
#{ZONE0}.Control.Pid.Run.Low.Kp=0.5
#{ZONE0}.Control.Pid.Run.Low.Ki=1400.0
#{ZONE0}.Control.Pid.Run.Low.Kd=350.0
#{ZONE0}.Control.Pid.Run.Low.ffS=0.0
#{ZONE0}.Control.Pid.Run.Low.ffSoffset=0.0
#{ZONE0}.Control.Pid.Run.Low.ffV=0.0
#{ZONE0}.Control.Pid.Run.Low.ffA=0.0
#{ZONE0}.Control.Pid.Run.Low.ffB=0.0
//
// Medium range pid parameters. Medium range goes from #{ZONE0}.Control.Pid.Run.Medium till
// #{ZONE0}.Control.Pid.Run.High
//
#{ZONE0}.Control.Pid.Halt.Medium=100.0
#{ZONE0}.Control.Pid.Halt.Medium.Kp=2.5
#{ZONE0}.Control.Pid.Halt.Medium.Ki=1400.0
#{ZONE0}.Control.Pid.Halt.Medium.Kd=350.0
#{ZONE0}.Control.Pid.Halt.Medium.ffS=0.005
#{ZONE0}.Control.Pid.Halt.Medium.ffSoffset=30.0
#{ZONE0}.Control.Pid.Run.Medium=100.0
#{ZONE0}.Control.Pid.Run.Medium.Kp=2.0
#{ZONE0}.Control.Pid.Run.Medium.Ki=1400.0
#{ZONE0}.Control.Pid.Run.Medium.Kd=350.0
#{ZONE0}.Control.Pid.Run.Medium.ffS=0.0
#{ZONE0}.Control.Pid.Run.Medium.ffSoffset=0.0
#{ZONE0}.Control.Pid.Run.Medium.ffV=0.0
#{ZONE0}.Control.Pid.Run.Medium.ffA=0.0
#{ZONE0}.Control.Pid.Run.Medium.ffB=0.0
//
// High range pid parameters. High range goes from #{ZONE0}.Control.Pid.Run.High till
// #{ZONE0}.Ramp.Max.maxS
//
#{ZONE0}.Control.Pid.Halt.High=200.0
#{ZONE0}.Control.Pid.Halt.High.Kp=3.0
#{ZONE0}.Control.Pid.Halt.High.Ki=1400.0
#{ZONE0}.Control.Pid.Halt.High.Kd=350.0
#{ZONE0}.Control.Pid.Halt.High.ffS=0.001
#{ZONE0}.Control.Pid.Halt.High.ffSoffset=30.0
#{ZONE0}.Control.Pid.Run.High=200.0
#{ZONE0}.Control.Pid.Run.High.Kp=4.0
#{ZONE0}.Control.Pid.Run.High.Ki=1400.0
#{ZONE0}.Control.Pid.Run.High.Kd=350.0
#{ZONE0}.Control.Pid.Run.High.ffS=0.0
#{ZONE0}.Control.Pid.Run.High.ffSoffset=0.0
#{ZONE0}.Control.Pid.Run.High.ffV=0.0
#{ZONE0}.Control.Pid.Run.High.ffA=0.0
#{ZONE0}.Control.Pid.Run.High.ffB=0.0
//
// speed sets
//
#{ZONE0}.Param.Cmd.Create("Slow");
#{ZONE0}.Param.Entity.Slow.Ramp.cmdV=0.5;
#{ZONE0}.Param.Entity.Slow.Ramp.cmdA=10.000;
#{ZONE0}.Param.Entity.Slow.Ramp.cmdB=10.000;
#{ZONE0}.Param.Entity.Slow.Ramp.cmdJ=1000.000;
#{ZONE0}.Param.Cmd.Create("Rapid");
#{ZONE0}.Param.Entity.Rapid.Ramp.cmdV=5.0;
#{ZONE0}.Param.Entity.Rapid.Ramp.cmdA=100.000;
#{ZONE0}.Param.Entity.Rapid.Ramp.cmdB=100.000;
#{ZONE0}.Param.Entity.Rapid.Ramp.cmdJ=1000.000;
// commands starting with '!' will be executed immediately at startup
!Stream.Entity.zone0.Cmd.Run()

Errors

A list of the possible errors on the main control level. Each error can be masked by setting the corresponding bit in ErrorMask. The error ends up in inactivating the controller if the corresponding bit in ErrorDis is set (default for all errors)

EqualPatternDescription
ER_INOS_CTRL_REJECTED 0x00000001 Command was rejected
ER_INOS_CTRL_FAILED 0x00000002 Command failed
ER_INOS_CTRL_REMOTE 0x0000003C Possible remote controller errors. These bits are customer specific and are not set in 'normal' applications
ER_INOS_CTRL_GROUP 0x00000800 Group member is on error. See also 'Prop.EnbOutput'.
ER_INOS_CTRL_BUS 0x00001000 Fieldbus is on error, like 'link down', 'frame error counter', ...
ER_INOS_CTRL_TARGET 0x00002000 Target is on error, like a 'trap', 'overtemperature', ...
ER_INOS_CTRL_CONTROL 0x00004000 Temperature controller is os on error. See Control.Error for a detailed error description
ER_INOS_CTRL_RAMP 0x00008000 Trajectory generator is on error.
ER_INOS_CTRL_SAFETY 0x00010000 Application specific 'safety' error (customer specific)
ER_INOS_CTRL_APPLICAT 0x00020000 General application error (customer specific)

A list of the possible errors on the temperature controller level. Each error can be masked by setting the corresponding bit in Control.ErrorMask. The error ends up in inactivating the controller if the corresponding bit in Control.ErrorDis is set (default for all errors).

EqualPatternDescription
ER_INOS_CONTROLLER_VALCHK 0x00000001 Controller value check error
ER_INOS_CONTROLLER_SETTLE 0x00000002 Settling timeout
ER_INOS_CONTROLLER_OUTCHN 0x00000800 Output channel not found
ER_INOS_CONTROLLER_INPCHN 0x00001000 Input channel not found.
ER_INOS_CONTROLLER_ACTIVATE 0x00002000 Controller activation failed for some reason
ER_INOS_CONTROLLER_EXTERN 0x00004000 External controller on error (customer specific)
ER_INOS_CONTROLLER_OFFLINE 0x00008000 Value channel is offline
ER_INOS_TEMP_CONTROLLER_BREAK 0x00010000 Set if controller's input channel reports a broken sensor (i.e. DF_INOS_IMAGE_VALUE_CFG_ERROR flag set) or if reported value exceeds the configured m_rTbreak temperature
ER_INOS_TEMP_CONTROLLER_SHORT_CIRCUIT 0x00020000 Set if controller's input channel reports a sensor short circuit
ER_INOS_TEMP_CONTROLLER_ALARM 0x00040000 Set if the temperature exceeds the configured 'alarm temperature'
ER_INOS_TEMP_CONTROLLER_OUT_FAILURE 0x00080000 Set if the temperature change does not happen as expected, although the controller puts energy into the system. IOW: The system assumes that the spent energy is not properly translated into the desired temperature change due to an error in the electrical part of the output circuit
ER_INOS_TEMP_CONTROLLER_DELTA 0x00100000 Set if the temperature delta is bigger than the maximum "speed" (i.e. maximum expected/possible temperature change within a given time span) of the temperature controller. This error indicates a problem with the sensors/actors as the temperature should is physically not expected to change that much
ER_INOS_TEMP_CONTROLLER_OUTPWM_SYNC 0x00200000 Set if the outpwm sync input does not toggle
ER_INOS_TEMP_CONTROLLER_LIMIT 0x00400000 Set if an external temperature supervision reports a limit reached error

Warnings

A list of the possible warnings on the main control level. Each warning can masked by setting the corresponding bit in WarningMask

EqualPatternDescription
WR_INOS_CTRL_IGNORED 0x00000001 Command was ignored for some reason
WR_INOS_CTRL_CONTROL 0x00004000 Temperature controller has a pending warning. See Control.Warning for a detailed error description
WR_INOS_CTRL_RAMP 0x00008000 Trajectory generator has a pending warning.

A list of the possible warnings on the temperature controller level. Each warning can be masked by setting the corresponding bit in Control.WarningMask

EqualPatternDescription
WR_INOS_CONTROLLER_INTLIMIT 0x00000001 Integrator limit reached
WR_INOS_CONTROLLER_NOTSUP 0x00000002 General 'not supported' warning
WR_INOS_TEMP_CONTROLLER_LOW_TEMP 0x00010000 Temperature too low for e.g. 'Tune=Blz' or 'Tune=ffS'
WR_INOS_TEMP_CONTROLLER_HIGH_TEMP 0x00010000 Temperature too high for e.g. 'Tune=Hcp'. In this case the temperature has to be smaller than the configured 'Ramp.Max.minS'.

Setup step by step

This section gives a step by step intro how to setup an temperature controller.

Create the configuration

A temperature controller has a analog input which represents the temperature and either an analog or a digital output for the power stage. If the power stage is controlled over a digital output (e.g. a solid state relais), one has to configure a software pwm for this output, which allows the controller to work with values from 0..100%. See General for an example.

The controller itself is set up with a so called stream file. It is an ASCII file which simply has CallProcedure and PutVariable entries and is executed at booting of the system. An example can be found here Properties.

In short :

  • create a *.dt2 file with the pwm configuration (see also General) and put it into the config directory of your project
  • create a *.stream file with this content Properties. To get a good starting point, adjust the following values :
// allowed temperature range
Ramp.Max.minS=40
Ramp.Max.maxS=300
// disable boltzmann
Control.Flag.EnbBoltzmann=0
// disable heat capacity
Control.Prop.hcpFactor=0.0
// zero all PID factors
Control.Pid.Halt.Low.Kp=0.0
Control.Pid.Halt.Low.Ki=0.0
Control.Pid.Halt.Low.Kd=0.0
Control.Pid.Run.Low.Kp=0.0
Control.Pid.Run.Low.Ki=0.0
Control.Pid.Run.Low.Kd=0.0
Control.Pid.Halt.Medium.Kp=0.0
Control.Pid.Halt.Medium.Ki=0.0
Control.Pid.Halt.Medium.Kd=0.0
Control.Pid.Run.Medium.Kp=0.0
Control.Pid.Run.Medium.Ki=0.0
Control.Pid.Run.Medium.Kd=0.0
Control.Pid.Halt.High.Kp=0.0
Control.Pid.Halt.High.Ki=0.0
Control.Pid.Halt.High.Kd=0.0
Control.Pid.Run.High.Kp=0.0
Control.Pid.Run.High.Ki=0.0
Control.Pid.Run.High.Kd=0.0

Verify the configuration

After builing and loading the project to your target, let's verify if everything was setup ok. Open the INCO explorer and check if there is a folder

Control.Entity.Zone0 28.05 °C

where 'Zone0' is the name of your controller. If you don't see this folder :

  • check if the feature 'General options.Temperature control' in your iDev project is selected
  • check with the eventlogger if there are some error traces regarding your controller

Now lets check if the temperature changes if we output power for a short time :

  • open a Varlog and select your input and output channels to be logged (set the trigger to the output channel != 0.0). You find these channels under Image.Analog.Input/Output and/or Image.Digital.Output
  • start logger
  • write e.g. 10% to the output channel, wait some seconds and write 0.0 again

If you see a significant temperature change in your log, everything seems to be fine. If not, try agin with more power or check your config and wiring.

Measure heat capacity

To give the controller a hint regarding the relation between power and temperature delta, you have the possibility to measure the so called hcpFactor (heat capacity factor). This measurement makes only sense if yor heater is some kind of heating plate or similar. It definitely makes no sense for a heater like a hot air gun. Skip this section in this case.

The measurement is done by setting a predefined power for a selected time and measuring the temperature delta.

Measure the hcpFactor :

  • ensure the temperature of your heater lies below Ramp.Max.minS. If this is not the case, cool down the system somehow
  • set the requested pulse values.
Control.Entity.Zone0.Control.Tune.Pulse.Power = 100 // pulse power
Control.Entity.Zone0.Control.Tune.Pulse.Time = 5000 // pulse time [ms]
Control.Entity.Zone0.Control.Tune.Pulse.Timeout = 30000 // pulse timeout [ms]
  • activate the controller. The Control.Entity.Zone0.State should now show 'ready' :
Control.Entity.Zone0.Cmd.Activate()
  • start measurement and (read the next step before you start) :
Control.Entity.Zone0.Cmd.Tune("Type=Hcp")
  • during the measurement the controller state Control.Entity.Zone0.State shows 'tuning'. As soon as the state goes back to 'ready', the mesdurement is done and we suggest to immediately inactivate the controller again, to avoid any overheatings
Control.Entity.Zone0.Cmd.InActivate()
  • the measure result can be found here :
Control.Entity.Zone0.Control.Tune.Result.Hcp.Factor = 1.757
  • move the measure value to the properties section and don't forget to update your controller stream file as well
Control.Entity.Zone0.Control.Prop.hcpFactor = 1.757
  • a good starting point for the PID factors can be found in Result.Pid
Control.Entity.Zone0.Control.Tune.Result.Pid.Kp
Control.Entity.Zone0.Control.Tune.Result.Pid.Kd
Control.Entity.Zone0.Control.Tune.Result.Pid.Ki

PID factors

To setup PID factors, there is currently no reliable mechanism available. You have to do it by hand, but usually this is not really tricky.

  • to avoid any errors during this work, tell the controller to disable value checking and settling supervision :
Control.Entity.Zone0.Control.Flag.ChkVal = 0
Control.Entity.Zone0.Control.Prop.maxSerr = 50
Control.Entity.Zone0.Control.Prop.maxSerrRun = 100
  • we start PID adjustment in the predefined low range (#{ZONE0}.Ramp.Max.minS till #{ZONE0}.Control.Pid.Run.Medium, so clear Ki and Kd in this range (Halt and Run) and set Kp to a starting value e.g. 1
Control.Entity.Zone0.Control.Pid.Halt.Low.Kp = 1.0
Control.Entity.Zone0.Control.Pid.Halt.Low.Ki = 0.0
Control.Entity.Zone0.Control.Pid.Halt.Low.Kd = 0.0
Control.Entity.Zone0.Control.Pid.Run.Low.Kp = 1.0
Control.Entity.Zone0.Control.Pid.Run.Low.Ki = 0.0
Control.Entity.Zone0.Control.Pid.Run.Low.Kd = 0.0
  • activate the controller and move to a reasonable temperature of the low range (e.g. 10°C below #{ZONE0}.Control.Pid.Run.Medium)
Control.Entity.Zone0.Cmd.Activate()
Control.Entity.Zone0.Cmd.Move(80.00:d, "")
  • now 'play' around with Control.Entity.Zone0.Control.Pid.Halt.Low.Kp (typically by increasing Kp) till you get a clean temperature oscillation, use varlog to measure/view the oscillation
  • after successfu oscillation measurement, set the PID values in the following manner
Control.Entity.Zone0.Control.Pid.Halt.Low.Kp = 0.6 * used Kp for oscillation
Control.Entity.Zone0.Control.Pid.Halt.Low.Ki = 0.5 * measured oscillation time [ms]
Control.Entity.Zone0.Control.Pid.Halt.Low.Kd = 0.125 * measured oscillation time [ms]
Control.Entity.Zone0.Control.Pid.Run.Low.Kp = 0.6 * used Kp for oscillation
Control.Entity.Zone0.Control.Pid.Run.Low.Ki = 0.5 * measured oscillation time [ms]
Control.Entity.Zone0.Control.Pid.Run.Low.Kd = 0.125 * measured oscillation time [ms]
  • you should now have a stable controller for the low range, do the same steps for medium and high range or directly use the low parameters for the other ranges, they usually fit not to bad

Optimizations

There are several possibilities to optimize and therefore 'help' the controller to do its work.

  • heat capacity measurement (seen already here Measure heat capacity)
  • temperature dependant power feed forward
  • Boltzmann law feed forward for heating plates

To reduce the dependancy of the integrator limits

Control.Entity.Zone0.Control.Prop.minTint
Control.Entity.Zone0.Control.Prop.maxTint

you have two possibilities to work with a power feed forward.

1. Power feed forward with ffS

The ffS mechanism is configured with the two parameters (per temperature range) :

Control.Entity.Zone0.Control.Pid.Halt.Low.ffS = 0.02
Control.Entity.Zone0.Control.Pid.Halt.Low.ffSoffset = 30.0

The feed forwarded power is calculated like this

actOut = (actS - ffSoffset) * ffS

You can either let the system measure this feed forward with

Control.Entity.Zone0.Cmd.Tune("Type=ffS")

or live change the parameters during active control till the current controller integrator tends to be zero

Control.Entity.Zone0.Control.Err.errSint = 14.56

2. Power feed forward with Boltzmann law

The Stefan–Boltzmann law describes the power radiated from a black body in terms of its temperature (see https://en.wikipedia.org/wiki/Stefan-Boltzmann_law) So if your heater is e.g. similar to a heating plate, this feed forward mechanism is probably the right choice.

How to setup :

  • activate the controller and move to max. / or near the max. allowed temperature
  • check the controller output at this point
Control.Entity.Zone0.Control.Act.actOut = 14.0

In this example, we measured about 14%. Setup the following parameters to get things running

Control.Entity.Zone0.Control.Flag.EnbBoltzmann = 1.0
Control.Entity.Zone0.Control.Prop.blzTmin = 30.0
Control.Entity.Zone0.Control.Prop.blzTmax = 300.0
Control.Entity.Zone0.Control.Prop.blzP = 13.0

The parameters have the following meaning :

  • EnbBoltzmann Enable the boltzmann law
  • blzTmin Minimum temperature where the law should take effect
  • blzTmax Maximum temperature where the law should take effect
  • blzP The requested feed forward power at blzTmax (use about 10% less value than measured)

And now happy heating !