1.2 Run your first IOC
Create one process variable (PV), run an Input/Output Controller (IOC), and read and write the same value through Channel Access (CA) and pvAccess (PVA).
Open two Bash terminals on the same host with these roles and settings:
| Terminal | Role | Working directory | Environment |
|---|---|---|---|
| Terminal 1 | IOC (softIocPVX) | ~/ioc-training/first/ | source "$TREE/setEpicsEnv.bash" |
| Terminal 2 | CA and PVA client | Any directory | source "$TREE/setEpicsEnv.bash", export EPICS_CA_AUTO_ADDR_LIST=NO EPICS_CA_ADDR_LIST=127.0.0.1, export EPICS_PVA_AUTO_ADDR_LIST=NO EPICS_PVA_ADDR_LIST=127.0.0.1 |
-
In two Bash terminals, activate the matching installation from lesson 1.1. Set
TREEin each terminal to that installation’s absolute path, then direct clients to this host:source "$TREE/setEpicsEnv.bash" export EPICS_CA_AUTO_ADDR_LIST=NO EPICS_CA_ADDR_LIST=127.0.0.1 export EPICS_PVA_AUTO_ADDR_LIST=NO EPICS_PVA_ADDR_LIST=127.0.0.1 -
In terminal 1, create a workspace outside the distribution:
mkdir -p ~/ioc-training/first cd ~/ioc-training/firstSave this database as
water.db:record(ao, "temperature:water") { field(DESC, "Water temperature setpoint") field(EGU, "degC") field(VAL, "0") }This analog output (
ao) record has no hardware connection. A write changes its stored value;EGUidentifies its engineering units. -
Start the installed PVXS executable in terminal 1:
softIocPVX -d water.dbWait for
iocRun: All initialization complete. At the IOC prompt, list the records:dblThe IOC shell prints the loaded record name:
temperature:waterLeave the IOC running in terminal 1.
-
In terminal 2, read the value and description:
caget -t temperature:water caget -t temperature:water.DESC pvxget temperature:waterCA returns the scalar value and description, while PVA displays a typed
NTScalarstructure:0 Water temperature setpoint temperature:water value double = 0 alarm.severity int32_t = 0 alarm.status int32_t = 2 alarm.message string = "UDF" timeStamp.secondsPastEpoch int64_t = 631152000 timeStamp.nanoseconds int32_t = 0 timeStamp.userTag int32_t = 0 display.limitLow double = 0 display.limitHigh double = 0 display.description string = "Water temperature setpoint" display.units string = "degC" display.precision int32_t = 0 display.form.index int32_t = 0 display.form.choices string[] = {7}["Default", "String", "Binary", "Decimal", "Hex", "Exponential", "Engineering"] control.limitLow double = 0 control.limitHigh double = 0 valueAlarm.lowAlarmLimit double = nan valueAlarm.lowWarningLimit double = nan valueAlarm.highWarningLimit double = nan valueAlarm.highAlarmLimit double = nan -
Write through CA, then read through both protocols:
caput temperature:water 24 caget -t temperature:water pvxget temperature:waterBoth reads report
24, and the first write clears the initialUDFalarm status and updatestimeStamp:Old : temperature:water 0 New : temperature:water 24 24 temperature:water value double = 24 alarm.severity int32_t = 0 alarm.status int32_t = 0 alarm.message string = "" timeStamp.secondsPastEpoch int64_t = 1794424745 timeStamp.nanoseconds int32_t = 930919750 timeStamp.userTag int32_t = 0 display.limitLow double = 0 display.limitHigh double = 0 display.description string = "Water temperature setpoint" display.units string = "degC" display.precision int32_t = 0 display.form.index int32_t = 0 display.form.choices string[] = {7}["Default", "String", "Binary", "Decimal", "Hex", "Exponential", "Engineering"] control.limitLow double = 0 control.limitHigh double = 0 valueAlarm.lowAlarmLimit double = nan valueAlarm.lowWarningLimit double = nan valueAlarm.highWarningLimit double = nan valueAlarm.highAlarmLimit double = nan -
Write through PVA and read through CA:
pvxput temperature:water 44 caget -t temperature:waterpvxputexits quietly on success, and CA returns44because both protocols reach the same record:44 -
In terminal 1, stop the IOC:
exit
Exercise: Add an air temperature
Add a second ao record to water.db, named temperature:air, with
DESC set to Air temperature setpoint, EGU to degC, and VAL to
20. Restart the IOC and read both records:
caget temperature:water temperature:air
The restarted records begin at 0 and 20. Client writes in this lesson
are not saved to the database file.
To observe a failed search without changing the host firewall, direct the CA client to an unused local UDP port in terminal 2:
export EPICS_CA_ADDR_LIST=127.0.0.1:59999
caget -w 1 temperature:water
With no IOC search listener on that port, the read times out:
Channel connect timed out: 'temperature:water' not found.
Restore the address and verify that the read succeeds:
export EPICS_CA_ADDR_LIST=127.0.0.1
caget -t temperature:water
An empty address list does not reliably cause failure when automatic broadcast discovery is enabled. Keep it disabled for these local exercises.