Welcome to EPICS!
Accelerator Equipment ↔ Control System ↔ People
The control system is (mostly) a set of software tools and applications that the accelerator operators, physicists, and engineers interact with to understand and control the state of the thousands of pieces of equipment that make up the Linear Accelerator complex.
A lot of accelerator equipment is connected to controllers (e.g. PLCs) that do low-level work like reading in voltages, controlling current, interpreting timing signals, opening and closing valves, and more. A highly specialized software program is needed to translate those signals and states into meaningful and rich data that can be used by operator interfaces and applications. For this we use EPICS (Experimental Physics and Industrial Control Systems). EPICS is a distributed control system toolkit, actively maintained and managed by an diverse group of international collaborators. It started in the 1989 as a joint project between two DOE labs - LANL (Los Alamos) and ANL (Argonne) - as part of the Star Wars program (more history here!). It went open-source in 2004 and is now one of the most widely used control system by particle accelerators and scientific facilities across the world.
What does EPICS look like?
The main EPICS software application is called an IOC (Input Output Controller). An IOC has 3 main functions:
- Stores a database of PVs (Process Variables) or Records (these two terms are often and confusingly used interchangeably). These PVs are uniquely named variables that hold information such as device setpoints and instrument readbacks, along with related data such as units and alarm levels. Controls engineers create and update these databases often when adding new equipment or adding new capabilities. We'll look at these in detail later.
- Provides a device support layer that converts signals from hardware into the formats the PVs understand. A lot of device support is available from the collaboration so developing these is fairly rare, and we generally don't need to think about it.
- Serves up the PV data to the network to be used by software clients using the 'channel access' protocol (or the new 'PV access' protocol). These clients can be various operator interface programs (E.g. EDM, PyDM, CS-Studio), programming languages (E.g. Python, Matlab), command line tools (e.g. caget, caput), alarm handlers, archivers, other IOCs, and more.
A good-sized accelerator facility will have many hundreds of IOCs deployed. Some IOCs run on small computers in hardware racks, and run on real-time operating systems. Others (most actually) are simple software processes that can run on any Linux computer. Here at SLAC, these simple software IOCs (softiocs) run on one of a couple dedicated Linux servers.
![](/download/attachments/476645660/image2022-6-21_9-23-51.png?version=1&modificationDate=1719360554831&api=v2)
How are IOCs developed and run?
At SLAC, we develop our IOCs on the Development network (e.g. lcls-dev3), sometimes against a test stand or a software simulation. How the work is done depends on whether we are changing an existing IOC application, or creating a new one. The folder containing the IOC application files is version controlled with Git. When ready to deploy to the Production network, the Git repo is tagged with a release number and copied over to a production server and booted up using specialized commands. Deploying new software like this is highly controlled and generally only scheduled on accelerator maintenance days. The recipes for updating existing applications and for deploying new ones are beyond the scope of this introduction.
Introduction to common EPICS PV record types and Operator Interfaces
In this section we'll explore some of the most commonly used PV types and their attributes. In the end you will have a small database of unique records you can run and use for learning about the operator interface applications in the next section.
What is are EPICS Records and PVs?
A Record is a software object with a unique name, e.g. MY_RECORD:SETPOINT, controllable fields, and a behavior or action.
A PV has two parts: the record name and a field, e.g. '.VAL', '.DESC', or '.SEVR' which are common to all records. To retrieve the information in the .DESC field we would use the PV name MY_RECORD:SETPOINT.DESC. Note that 'VAL' is the default field and can be left off, so these are equivalent: MY_RECORD:SETPOINT=MY_RECORD:SETPOINT.VAL.
There are different record types that can be used depending on the type of data they are handling. In the example to follow we will be looking at these common record types and their frequently configured fields:
- Analog in (ai) - reads in raw analog signals and can convert the units if needed. Supports alarm levels and severities, smoothing and filtering, graphics and control limits.
- Analog out (ao) - used to send an analog value to a device, converting the units if needed. Supports alarm levels and severities, drive and rate-of-change limits.
- Calculation (calc) -used to perform algebraic or logical calculations on values retrieved from other records. Supports alarm limits and severities.
- Binary in (bi) - used to obtain a digital 0 or 1. Supports mapping to a label and alarm severity.
- Binary out (bo) - used to write a digital 0 or 1. Supports mapping to a label and alarm severity.
- String in (stringin) - holds arbitrary ASCII string of up to 40 characters.
Controls engineers rely on the EPICS Record Reference for information about the different record types and their fields. This reference site also has a good Introduction to EPICS and Process Database Concepts.
Syntax of a Record
Each record starts by declaring a unique name and the type. At SLAC the names are created following an official naming convention in a standardized all-caps format: DEVICE_TYPE:AREA:POSITION:(INSTANCE):SIGNAL_ATTRIBUTES. This makes the names look complicated but they contain a lot of information! For example, QUAD:LI22:401:IACT is a quadrupole magnet in sector LI22 at position 401, and the attribute is IACT (actual current readback).
EPICS Channel Access makes every PV available on the network so any client or person logged on can access them. For this reason it's important not to have duplicate PV names out there because you will randomly connect to either one and this can cause obvious issues. For this introduction we'll stick to simplified record names, E.g. MYNAME:SETPOINT using your own username to ensure they are unique on the network.
Following the name and type are a list of fields. Usually a record type will have many more fields than we care to define so if we don't specify it they fall back to a default (defined in the Record Reference).
There are several fields that are common to all records such as:
- DESC - a 41-character string for human-readable descriptions (default=empty)
- SCAN - determines how often the record should process - range 0.1 second to 10 second, event or interrupt, or passive (default) where the record processing is triggered by one of its links updating (default=passive)
- SEVR - the alarm severity of the record - NO_ALARM by default, MINOR and MAJOR are defined by the engineers in their record databases, INVALID is automatically set if there is a communication error like a bad link (default=NO_ALARM)
Example record types and common field definitions:
record(ai, "MYNAME:READBACK"){ field(DESC, "Description") field(INP, "INPUT:ADDRESS") field(SCAN, "1 second") field(PREC, "2") field(EGU, "Things") field(HIHI, "95") field(HIGH, "90") field(LOLO, "10") field(LOW, "5") field(HHSV, "MAJOR") field(HSV, "MINOR") field(LSV, "MINOR") field(LLSV, "MAJOR") } | record(ao, "MYNAME:SETPOINT"){ field(DESC, "Description") field(OUT, "OUTPUT:ADDRESS PP") field(EGU, "Things") field(PREC, "2") field(DRVH, "100") field(DRVL, "0") } | record(calc, "MYNAME:SCALED"){ field(DESC, "Description") field(INPA, "INPUT:ADDRESS:A CP") field(INPB, "INPUT:ADDRESS:B CP") ... field(INPC, "INPUT:ADDRESS:C CP") field(CALC, "100*(A+B)/C") } |
INP: input (other PV, PLC address) SCAN: how often to process note we don't need to put a 'CP' after this address to trigger processing since it already will process at 1 Hz PREC: precision (# decimal places) HIHI,HIGH,LOW,LOLO: alarm levels HHSV,HSV,LSV,LLSV: alarm severities | OUT: output (other PV, PLC address) note the 'PP' after the address - this makes the receiving record process after it gets the new value EGU: engineering units PREC: precision (# decimal places) DRVH,DRVL: drive high/low limits - commands outside these limits are clamped to these values | INPA-INPL: multiple input addresses note the 'CP' after the address - this makes the record listen to each input and process when any of them change. Here SCAN is passive (default) CALC: logical or algebraic expression 'A', 'B', etc. are the values from the corresponding INPA, INPB, etc. |
record(bi, "MYNAME:STATUS"){ field(DESC, "Description") field(INP, "INPUT:ADDRESS CP") field(ZNAM, "Not Ok") field(ONAM, "Ok") field(ZSV, "MAJOR") field(OSV, "NO_ALARM") } | record(bo, "MYNAME:COMMAND"){ field(DESC, "Description") field(OUT, "OUTPUT:ADDRESS PP") field(ZNAM, "Off") field(ONAM, "On") } | record(stringin, "MYNAME:MESSAGE"){ field(DESC, "Description") field(VAL, "This is a message") } |
INP: input (other PV, PLC address) ZNAM,ONAM: 0,1 value labels ZSV,OSV: 0,1 alarm severities | OUT: output (other PV, PLC address) ZNAM,ONAM: 0,1 value labels | VAL: An initial message - notes that we don't normally initialize VAL since it often comes from some input link or is calculated! |
Now It's Time to Test Your Skills
Project 2:
Additional Helpful Resources
Some reference material useful for the entire problem: