Skip to content

Commit

Permalink
heater: Add heater controller support
Browse files Browse the repository at this point in the history
Heater support include the switching between automatic and manual
heating control, besides the parameters for both methods. For the manual
heating setting, the voltage is used to indirectly control the
temperature. On the other hand, automatic control (through PID method)
is allows to specify a set-point temperature to be reached and Kp, Ti,
and Td constants from both boards.

Periodic scan is used in read-back records so that PV has the updated
value when some external access is done to the device to update its
configuration. An arbitrary value of 1 second has been chosen to keep
the value reasonably updated while not overloading the device. Moreover,
when a value is updated, the corresponding read-back value must be
updated so that scripts can directly read back the correct value.
Therefore, it has also been used a forward link to read-back from
set-point records. Note that it is used the `PROC` field in the
forwarding. This is because a non-passive scan is used in the read-back
records.

The PV names have been kept from the previous IOC. This implies that the
issue reported about the misleading PID coefficient names has not been
solved here [1]. This is because we should do that coordinated with the IOC
clients. Therefore, Td should be read as Kd and Ti should be read as Ki.
For this reason, they have been limited to be non-negative as defined in
the PID controller theory. The same goes for Kp. The upper limit (DRVH)
must be specified explicitly, so that the clipping condition `DRVL <
DRVH` holds (as both values defaults to 0). In this case, it is
unlimited (i.e. infinity).

[1]: lnls-dig/bpm-epics-ioc#35
  • Loading branch information
henriquesimoes committed Apr 18, 2023
1 parent 0b3566c commit f3de442
Show file tree
Hide file tree
Showing 2 changed files with 344 additions and 0 deletions.
242 changes: 242 additions & 0 deletions BPMRFFEApp/Db/bpmrffe.db
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,248 @@ record(ai, "$(P)$(R)RFFETempBD-Mon") {
field(EGU, "oC")
}

# Heating controls

record(bo, "$(P)$(R)RFFETempCtl-SP") {
field(DESC, "Set auto temperature control")
field(DTYP, "stream")
field(PINI, "YES")
field(SCAN, "Passive")
field(VAL, "0")
field(ZNAM, "off")
field(ONAM, "on")
field(OUT, "@bpmrffe.proto outTempCtl $(PORT)")
field(FLNK, "$(P)$(R)RFFETempCtl-RB.PROC CA")
}

record(bi, "$(P)$(R)RFFETempCtl-RB") {
field(DESC, "Get auto temperature control")
field(DTYP, "stream")
field(SCAN, "1 second")
field(ZNAM, "off")
field(ONAM, "on")
field(INP, "@bpmrffe.proto inTempCtl $(PORT)")
}

# Manual heater control settings

record(dfanout, "$(P)$(R)RFFEHeater-SP") {
field(DESC, "Set both boards' heater voltage")
field(OMSL, "supervisory")
field(OUTA, "$(P)$(R)RFFEHeaterAC-SP PP")
field(OUTB, "$(P)$(R)RFFEHeaterBD-SP PP")
}

record(ao, "$(P)$(R)RFFEHeaterAC-SP") {
field(DESC, "Set AC board heater's voltage")
field(DTYP, "stream")
field(PINI, "YES")
field(SCAN, "Passive")
field(OUT, "@bpmrffe.proto outHeaterVoltAC $(PORT)")
field(EGU, "V")
field(FLNK, "$(P)$(R)RFFEHeaterAC-RB.PROC CA")
}

record(ai, "$(P)$(R)RFFEHeaterAC-RB") {
field(DESC, "Get AC board heater's voltage")
field(DTYP, "stream")
field(SCAN, "1 second")
field(INP, "@bpmrffe.proto inHeaterVoltAC $(PORT)")
field(EGU, "V")
}

record(ao, "$(P)$(R)RFFEHeaterBD-SP") {
field(DESC, "Set BD board heater's voltage")
field(DTYP, "stream")
field(PINI, "YES")
field(SCAN, "Passive")
field(OUT, "@bpmrffe.proto outHeaterVoltBD $(PORT)")
field(EGU, "V")
field(FLNK, "$(P)$(R)RFFEHeaterBD-RB.PROC CA")
}

record(ai, "$(P)$(R)RFFEHeaterBD-RB") {
field(DESC, "Get BD board heater's voltage")
field(DTYP, "stream")
field(SCAN, "1 second")
field(INP, "@bpmrffe.proto inHeaterVoltBD $(PORT)")
field(EGU, "V")
}

# PID (automatic) controller parameters

record(dfanout, "$(P)$(R)RFFEPidSp-SP") {
field(DESC, "Set both boards' heater temp. setpoint")
field(OMSL, "supervisory")
field(OUTA, "$(P)$(R)RFFEPidSpAC-SP PP")
field(OUTB, "$(P)$(R)RFFEPidSpBD-SP PP")
}

record(ao, "$(P)$(R)RFFEPidSpAC-SP") {
field(DESC, "Set AC board heater temp. setpoint")
field(DTYP, "stream")
field(PINI, "YES")
field(SCAN, "Passive")
field(OUT, "@bpmrffe.proto outPIDTempSpAC $(PORT)")
field(EGU, "oC")
field(FLNK, "$(P)$(R)RFFEPidSpAC-RB.PROC CA")
}

record(ai, "$(P)$(R)RFFEPidSpAC-RB") {
field(DESC, "Get AC board heater temp. setpoint")
field(DTYP, "stream")
field(SCAN, "1 second")
field(INP, "@bpmrffe.proto inPIDTempSpAC $(PORT)")
field(EGU, "oC")
}

record(ao, "$(P)$(R)RFFEPidSpBD-SP") {
field(DESC, "Set BD board heater temp. setpoint")
field(DTYP, "stream")
field(PINI, "YES")
field(SCAN, "Passive")
field(OUT, "@bpmrffe.proto outPIDTempSpBD $(PORT)")
field(EGU, "oC")
field(FLNK, "$(P)$(R)RFFEPidSpBD-RB.PROC CA")
}

record(ai, "$(P)$(R)RFFEPidSpBD-RB") {
field(DESC, "Get BD board heater temp. setpoint")
field(DTYP, "stream")
field(SCAN, "1 second")
field(INP, "@bpmrffe.proto inPIDTempSpBD $(PORT)")
field(EGU, "oC")
}

record(dfanout, "$(P)$(R)RFFEPidKp-SP") {
field(DESC, "Set both boards' PID Kp constant")
field(OMSL, "supervisory")
field(OUTA, "$(P)$(R)RFFEPidACKp-SP PP")
field(OUTB, "$(P)$(R)RFFEPidBDKp-SP PP")
}

record(ao, "$(P)$(R)RFFEPidACKp-SP") {
field(DESC, "Set AC board's PID Kp constant")
field(DTYP, "stream")
field(PINI, "YES")
field(DRVL, "0")
field(DRVH, "inf")
field(SCAN, "Passive")
field(OUT, "@bpmrffe.proto outPIDKpAC $(PORT)")
field(FLNK, "$(P)$(R)RFFEPidACKp-RB.PROC CA")
}

record(ai, "$(P)$(R)RFFEPidACKp-RB") {
field(DESC, "Get AC board's PID Kp constant")
field(DTYP, "stream")
field(SCAN, "1 second")
field(INP, "@bpmrffe.proto inPIDKpAC $(PORT)")
}

record(ao, "$(P)$(R)RFFEPidBDKp-SP") {
field(DESC, "Set BD board's PID Kp constant")
field(DTYP, "stream")
field(PINI, "YES")
field(DRVL, "0")
field(DRVH, "inf")
field(SCAN, "Passive")
field(OUT, "@bpmrffe.proto outPIDKpBD $(PORT)")
field(FLNK, "$(P)$(R)RFFEPidBDKp-RB.PROC CA")
}

record(ai, "$(P)$(R)RFFEPidBDKp-RB") {
field(DESC, "Get BD board's PID Kp constant")
field(DTYP, "stream")
field(SCAN, "1 second")
field(INP, "@bpmrffe.proto inPIDKpBD $(PORT)")
}

record(dfanout, "$(P)$(R)RFFEPidTi-SP") {
field(DESC, "Set both boards' PID Ti constant")
field(OMSL, "supervisory")
field(OUTA, "$(P)$(R)RFFEPidACTi-SP PP")
field(OUTB, "$(P)$(R)RFFEPidBDTi-SP PP")
}

record(ao, "$(P)$(R)RFFEPidACTi-SP") {
field(DESC, "Set AC board's PID Ti constant")
field(DTYP, "stream")
field(PINI, "YES")
field(DRVL, "0")
field(DRVH, "inf")
field(SCAN, "Passive")
field(OUT, "@bpmrffe.proto outPIDTiAC $(PORT)")
field(FLNK, "$(P)$(R)RFFEPidACTi-RB.PROC CA")
}

record(ai, "$(P)$(R)RFFEPidACTi-RB") {
field(DESC, "Get AC board's PID Ti constant")
field(DTYP, "stream")
field(SCAN, "1 second")
field(INP, "@bpmrffe.proto inPIDTiAC $(PORT)")
}

record(ao, "$(P)$(R)RFFEPidBDTi-SP") {
field(DESC, "Set BD board's PID Ti constant")
field(DTYP, "stream")
field(PINI, "YES")
field(DRVL, "0")
field(DRVH, "inf")
field(SCAN, "Passive")
field(OUT, "@bpmrffe.proto outPIDTiBD $(PORT)")
field(FLNK, "$(P)$(R)RFFEPidBDTi-RB.PROC CA")
}

record(ai, "$(P)$(R)RFFEPidBDTi-RB") {
field(DESC, "Get BD board's PID Ti constant")
field(DTYP, "stream")
field(SCAN, "1 second")
field(INP, "@bpmrffe.proto inPIDTiBD $(PORT)")
}

record(dfanout, "$(P)$(R)RFFEPidTd-SP") {
field(DESC, "Set both boards' PID Td constant")
field(OMSL, "supervisory")
field(OUTA, "$(P)$(R)RFFEPidACTd-SP PP")
field(OUTB, "$(P)$(R)RFFEPidBDTd-SP PP")
}

record(ao, "$(P)$(R)RFFEPidACTd-SP") {
field(DESC, "Set AC board's PID Td constant")
field(DTYP, "stream")
field(PINI, "YES")
field(DRVL, "0")
field(DRVH, "inf")
field(SCAN, "Passive")
field(OUT, "@bpmrffe.proto outPIDTdAC $(PORT)")
field(FLNK, "$(P)$(R)RFFEPidACTd-RB.PROC CA")
}

record(ai, "$(P)$(R)RFFEPidACTd-RB") {
field(DESC, "Get AC board's PID Td constant")
field(DTYP, "stream")
field(SCAN, "1 second")
field(INP, "@bpmrffe.proto inPIDTdAC $(PORT)")
}

record(ao, "$(P)$(R)RFFEPidBDTd-SP") {
field(DESC, "Set BD board's PID Td constant")
field(DTYP, "stream")
field(DRVL, "0")
field(DRVH, "inf")
field(PINI, "YES")
field(SCAN, "Passive")
field(OUT, "@bpmrffe.proto outPIDTdBD $(PORT)")
field(FLNK, "$(P)$(R)RFFEPidBDTd-RB.PROC CA")
}

record(ai, "$(P)$(R)RFFEPidBDTd-RB") {
field(DESC, "Get BD board's PID Td constant")
field(DTYP, "stream")
field(SCAN, "1 second")
field(INP, "@bpmrffe.proto inPIDTdBD $(PORT)")
}

# Operations

record(bo, "$(P)$(R)RFFERst-SP") {
Expand Down
102 changes: 102 additions & 0 deletions BPMRFFEApp/Db/bpmrffe.proto
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,108 @@ inMeasTempBD {
in "%f";
}

# Heating control operations
outTempCtl {
out "SET:TEMPControl:AUTOmatic %{0|1}";
}

inTempCtl {
out "GET:TEMPControl:AUTOmatic?";
in "%{0|1}";
}

# Manual heating setting operations
outHeaterVoltAC {
out "SET:DAC:OUTput:AC %f";
}

inHeaterVoltAC {
out "GET:DAC:OUTput:AC?";
in "%f";
}

outHeaterVoltBD {
out "SET:DAC:OUTput:BD %f";
}

inHeaterVoltBD {
out "GET:DAC:OUTput:BD?";
in "%f";
}

# PID parameter setting operations
outPIDTempSpAC {
out "SET:TEMPerature:SETPoint:AC %f";
}

inPIDTempSpAC {
out "GET:TEMPerature:SETPoint:AC?";
in "%f";
}

outPIDTempSpBD {
out "SET:TEMPerature:SETPoint:BD %f";
}

inPIDTempSpBD {
out "GET:TEMPerature:SETPoint:BD?";
in "%f";
}

outPIDKpAC {
out "SET:PID:Kc:AC %f";
}

inPIDKpAC {
out "GET:PID:Kc:AC?";
in "%f";
}

outPIDKpBD {
out "SET:PID:Kc:BD %f";
}

inPIDKpBD {
out "GET:PID:Kc:BD?";
in "%f";
}

outPIDTiAC {
out "SET:PID:Ti:AC %f";
}

inPIDTiAC {
out "GET:PID:Ti:AC?";
in "%f";
}

outPIDTiBD {
out "SET:PID:Ti:BD %f";
}

inPIDTiBD {
out "GET:PID:Ti:BD?";
in "%f";
}

outPIDTdAC {
out "SET:PID:Td:AC %f";
}

inPIDTdAC {
out "GET:PID:Td:AC?";
in "%f";
}

outPIDTdBD {
out "SET:PID:Td:BD %f";
}

inPIDTdBD {
out "GET:PID:Td:BD?";
in "%f";
}

# Operation
Rst {
out "SYSTem:RESet";
Expand Down

0 comments on commit f3de442

Please sign in to comment.