EPICSCAInput

Warning

The EPICSCAInput DataSource is only available in distributions where EPICS Channel Access is installed.

The EPICSCAInput DataSource can be used to receive application data using the EPICS Channel Access protocol. This allows interfacing the application with any EPICS-based monitoring or control application (e.g. EPICS Control System Studio).

This DataSource reads from the PVs asynchronously on a separate thread (which may be allocated to a different CPU core). This means that it is not intended to be used for real-time control, but rather for live parameter configuration.

The names of the PVs need to be defined for every signal in the DataSource configuration.

Given that the PV name needs to be unique, in order to avoid name clashes, the configuration file ../Configurations/MassSpring/RTApp-MassSpring-32.cfg will be automatically updated from a Makefile.cfg. The names of the PVs are based on the username.

The PVs are hosted on a softIOC which needs to be started before running the application. The softIOC configuration file is generated from a template by running the command ../Test/Integrated/GenerateEPICSSoftIOCDb.sh, which will also automatically generate the PV names to match the ones defined in the configuration file ../Configurations/MassSpring/RTApp-MassSpring-32.cfg.

In this example, the ReferencePosition signal is read from the corresponding PV and used as a reference for the control of the mass-spring system.

EPICSCAInput configuration. Note that the PV names are automatically replaced by the Makefile.cfg.
 1        +EPICSCAReader = {
 2            Class = EPICSCA::EPICSCAInput
 3            CPUMask = 0x1 
 4            StackSize = 10000000 
 5            Signals = {
 6                ReferencePosition = {
 7                    Type = float64
 8                    PVName = XSTR(MARTE2-TUTORIAL-USERNAME-REFERENCE-POSITION)
 9                }
10            }
11        }

Running the application

Start the softIOC in a separate terminal:

../Test/Integrated/GenerateEPICSSoftIOCDb.sh
softIoc -d ../Test/Integrated/MassSpring-1.db

Start the application with:

make -C ../Configurations/MassSpring/ -f Makefile.cfg
./MARTeApp.sh -f ../Configurations/MassSpring/RTApp-MassSpring-32_Gen.cfg -l RealTimeLoader -s State1

Once the application is running, inspect the screen output and verify that the application is running without any issues. The log should show entries similar to the following:

$ [Warning - Threads.cpp:181]: Failed to change the thread priority (likely due to insufficient permissions)
$ [Information - RealTimeLoader.cpp:111]: Started application in state State1
$ [Information - MARTeApp.cpp:135]: Application starting
$ [Information - LoggerBroker.cpp:152]: Time [0:0]:0
$ [Information - LoggerBroker.cpp:152]: Time [0:0]:1000000
...

Open another terminal and modify the value of the ReferencePosition PV using the command:

caput MARTE2-TUTORIAL-USERNAME-REFERENCE-POSITION 1.0 #Replace with your username in capital letters

Open another terminal and check that the PVs are being updated with the application data using the command:

camonitor MARTE2-TUTORIAL-USERNAME-REFERENCE-POSITION MARTE2-TUTORIAL-USERNAME-POSITION #Replace with your username in capital letters

The output should be similar to the following:

$ MARTE2-TUTORIAL-USERNAME-POSITION 2026-04-01 13:22:03.381297 1.00076
$ MARTE2-TUTORIAL-USERNAME-POSITION 2026-04-01 13:22:03.391297 1.00071
$ MARTE2-TUTORIAL-USERNAME-POSITION 2026-04-01 13:22:03.401303 1.00065
$ MARTE2-TUTORIAL-USERNAME-POSITION 2026-04-01 13:22:03.411300 1.0006
$ MARTE2-TUTORIAL-USERNAME-POSITION 2026-04-01 13:22:03.421299 1.00055
$ MARTE2-TUTORIAL-USERNAME-POSITION 2026-04-01 13:22:03.431300 1.0005

Exercises

Ex. 1: Switch on/off

The objective of this exercise is to use the EPICSCAInput DataSource to switch the force output of the mass-spring system on and off.

  1. Edit the file ../Configurations/MassSpring/RTApp-MassSpring-33.cfg and add a MuxGAM that selects between a signal named ForceZero and the signal ForceFromController to produce an output signal named Force in DDB1. Name the GAM GAMMuxSwitchOn.

  2. Modify the ControllerGAM to output the signal named ForceFromController instead of Force.

  3. The name of the switch on/off PV is MARTE2-TUTORIAL-USERNAME-SWITCH-ON.

  4. Add the MuxGAM to the execution list.

  5. Execute the application:

make -C ../Configurations/MassSpring/ -f Makefile.cfg
./MARTeApp.sh -f ../Configurations/MassSpring/RTApp-MassSpring-33_Gen.cfg -l RealTimeLoader -s State1
  1. Set a new target ReferencePosition using the caput command.

caput MARTE2-TUTORIAL-USERNAME-REFERENCE-POSITION 1.0 #Replace with your username in capital letters
  1. Observe that the Position is not changing and that the system is not responding to the new target ReferencePosition.

camonitor MARTE2-TUTORIAL-USERNAME-REFERENCE-POSITION MARTE2-TUTORIAL-USERNAME-POSITION #Replace with your username in capital letters
  1. Switch on the system by setting the switch on/off PV to 1 using the command:

caput MARTE2-TUTORIAL-USERNAME-SWITCH-ON 1 #Replace with your username in capital letters
  1. Observe that the Position is now changing and that the system is responding to the new target ReferencePosition.

camonitor MARTE2-TUTORIAL-USERNAME-REFERENCE-POSITION MARTE2-TUTORIAL-USERNAME-POSITION #Replace with your username in capital letters
Solution

The solution is to add a MuxGAM as specified above.

MuxGAM configuration.
 1        +GAMMuxSwitchOn = {
 2            Class = MuxGAM
 3            InputSignals = {
 4                SwitchOn = {
 5                    DataSource = EPICSCAReader
 6                    Type = uint32
 7                    NumberOfDimensions = 1
 8                    NumberOfElements = 1
 9                }
10                ForceZero = {
11                    DataSource = DDB1
12                    Type = float64
13                    NumberOfDimensions = 1
14                    NumberOfElements = 1
15                }
16                ForceFromController = {
17                    DataSource = DDB1
18                    Type = float64
19                    NumberOfDimensions = 1
20                    NumberOfElements = 1
21                }
22            }
23            OutputSignals = {
24                Force = {
25                    DataSource = DDB1
26                    Type = float64
27                    NumberOfDimensions = 1
28                    NumberOfElements = 1
29                }
30            }
31        }

Add the signal to the EPICSCAInput DataSource.

DataSource
 1        +EPICSCAReader = {
 2            Class = EPICSCA::EPICSCAInput
 3            CPUMask = 0x1 
 4            StackSize = 10000000 
 5            Signals = {
 6                ReferencePosition = {
 7                    Type = float64
 8                    PVName = XSTR(MARTE2-TUTORIAL-USERNAME-REFERENCE-POSITION)
 9                }
10                SwitchOn = {
11                    Type = uint32
12                    PVName = XSTR(MARTE2-TUTORIAL-USERNAME-SWITCH-ON)
13                }
14            }
15        }

Add the GAM to the execution list.

GAM execution list.
 1    +States = {
 2        Class = ReferenceContainer
 3        +State1 = {
 4            Class = RealTimeState
 5            +Threads = {
 6                Class = ReferenceContainer
 7                +Thread1 = {
 8                    Class = RealTimeThread
 9                    CPUs = 0x1
10                    Functions = {GAMPerfMonitor GAMTimer GAMReferenceEPICSCA GAMDisturbanceWaveform GAMMathDisturbance GAMFilterDisturbance GAMController GAMConstantZero GAMMuxSwitchOn GAMSpringMass GAMMathModel GAMMathPositionErr GAMStats GAMPatchForceDims GAMForceStats GAMHist GAMMathExpr GAMConversion GAMFilterMovingAvg GAMMathTrigger GAMMathTriggerSecond GAMDisplay GAMWriterStats GAMWriter}
11                }
12            }
13        }        
14    }