EPICS - lorenzo-campana/bpm GitHub Wiki
To intsall EPICS the first thing to do is download EPICS Base. We will use version 3.14.12.7
because that's the version of the software used in SPEAR3. Extract the archive in your home folder.
To compile EPICS Base
we will use the make
command:
cd ~/base-3.14.12.7
make
Now we need to install a java based graphic interface called VisualDCT. Download the latest version and extract it in your home folder like we did for EPICS Base.
To open the graphic interface and visualize database, just type the following command:
cd ~/VisualDCT-2.8.1
java -cp VisualDCT.jar com.cosylab.vdct.VisualDCT
In order to acces our base
folder more easily we can set up a soft link with the following command:
ln -s /home/user/base-3.14.12.7/ /home/user/epics
In this way we can go in our base-3.14.12.7
folder just by writing cd epics
It's now time to create our application, that we will call my_app
. We will use a Pearl script that automatically create every file that we need. The script can generate varius type of EPICS application, we will use the ioc
type. First we need to create a new folder to put the application file in:
mkdir ~/my_app
cd my_app
After that we can run the script with the following command:
~/base-3.14.12.7/bin/linux-arm/makeBaseApp.pl -t ioc my_app
~/base-3.14.12.7/bin/linux-arm/makeBaseApp.pl -i -t ioc my_app
When executing the second link the prompt will ask you what application the ioc should boot. Juest press Enter
to set the default value and continue.
After this we need to compile the application. As we did for the base
folder, we will use the make
command. Navigate in the my_app
folder and type in make
.
Now in the my_app
folder we should have all the file that we need to set up a database.
The last thing we need to do is add some PATH
in the .bashrc
file. This file contains the commands that are executed when you open a new terminal. WARNING: the .bashrc
file contains critical information for the terminal. If you mess up this file, the terminal won't work anymore. For this reason before editing it, create a backup with this commands:
cd
cp .bashrc bashrc_backup
We will edit the .bashrc
file using the nano
command:
nano .bashrc
Scroll to the bottom of the file and add the following code:
PATH=/home/user/base-3.14.12.7/bin/linux-arm:$PATH
export EPICS_BASE=/home/user/base-3.14.12.7/lib/linux-arm/libca.so
export EPICS+HOST_ARCH=linux-arm
Save and close the file pressing Ctrl + X
then Y
and Enter
We now need to create the database that will store all the record that we need for our application. We can do this in two ways:
- Using the VisualDCT tool
- Writing the
.db
file manually To initialize the database we will write the file ourself. In the future we will use VisualDCT to modify and add record to the database.
The database files will be store in /my_app/my_appApp/Db
. Navigate in this folder and create a database file my_database.db
using the nano
command:
cd ~/my_app/my_appApp/Db
nano my_database.bd
Inside this file we will create a record (for this example we will create a sub
record, a subroutine that can exectue C
code. We will add the code in the next section).
record(sub, my_sub) {
field(SNAM, my_subProcess)
field(INAM, my_subInit)
}
Save and exit with Ctrl = X
then Y
and Enter
.
After creating it we need to add the new database in the Makefile
. In the same directory of the my_database.db
file open the Makefile
with nano
. Search for this line:
#DB += xxx.db
and add the following line of code just below that.
DB += my_database.db
Save and exit with Ctrl = X
then Y
and Enter
. In this way the make
command will know what database it need to use when compiling the application.
A subroutine is a special epics record that can execute C
code. This code will be stored in the /home/user/my_app/my_appApp/src
folder. To create the source code for the subroutine go in the src
folder and create a my_subroutine.c
file using nano
. Inside the file write the following code:
#include <stdio.h>
#include <subRecord.h>
#include <registryFunction.h>
#include <epicsExport.h>
static int my_subInit(subRecord *precord) {
return 0;
}
static int my_subProcess(subRecord *precord) {
return 0;
}
/* Note the function must be registered at the end!*/
epicsRegisterFunction(my_subInit);
epicsRegisterFunction(my_subProcess);
A subroutine record as two special attribute:
- INAM: is the name of the initialization function (
my_subInit
in our case). This function is called only once when the database is loaded. - SNAM: is the name of the process function (
my_subProcess
in our case). This function is called everytime the record gets processed.
Inside this two function we can write any c code we want. If the subroutine record has some input links (we will se later how to create them) we can use them in our code using the pointer precord->a
for the input A (INPA), and so on for the other input (INPB, INPC, etc).
to make the subroutine work we need to register it in EPICS. To do so create a new file called my_database.dbd
in the same folder as the source code my_subroutine.c
. Open it with nano
and write the following code:
function(my_subInit)
function(my_subProcess)
Then exit and save the file.
Now we need to edit the Makefile
inside the src
folder with the new file we just created. Open it with nano
and under the comment
#my_app.dbd will be made up from these files:
my_app_DBD += base.dbd
add the following two line of code :
my_app_DBD += my_database.dbd
my_app_SRCS += my_subroutine.c
Then exit and save the file.
The last thing we need to edit is the st.cmd
file located in /home/pi/my_app/iocBoot/iocmy_app
. Open it with nano
and add the following line of code under ## Load record instances
:
dbLoadRecords("db/my_database.db")
After creating the record remember to compile it using make
in the top folder of your application (/home/user/my_app
).
Right now we only have a subroutine record in our database. In order to add other PV (the equivalent of variables for the database) we will use VisualDCT. Open the Java program (use the lines of code at the end of the EPICS installation chapter) and from the file browser open the .dbd
file my_app.db
located in /home/user/my_app/dbd
. After this you should see a black windows with white dots. Now open the database file with file -> Open... and in the file browser open the my_database.db
file located in /home/user/my_app/my_appApp/Db
.
Inside the database we should have the subroutine records that we created in the previous chapter. In VisualDCT records appear as boxes with the type of record on the top, followed by the name of the record and its attribute in the lower part.
After opening the database you shold have a window like this:
From this window you can create new record just by right clicking anywhere in the black dotted window and then clicking "New record...". On the window that pops up you can select the tipe of record and the name. You can edit the record's attributes by double clicking on it.
We can now link a record to our subroutine. Create an analog output (ao) record called my_record
and then right click on the subroutine record. Under INLINK select INPA and then click on the analog output that we just created. This will link the two record, and the value of my_record
will be avaible to use in the subroutine calling precord->a
.
We want to process the subroutine each time we update the value stored in the my_record
record, so we need a FLNK. To create this type of link just right click on the analog output record, select FLNK and click on the subroutine. In order to setup the right processing scheme, double click on the output record and then change the fiel SCAN to "Passive". Then right click on the INPA of the subroutine and under "Process" set "PP - Process passive".
Now we have EPICS installed with a functioning database we can start the ioc. Go to the folder /home/pi/my_app/iocBoot/iocmy_app
and run the following command to start the ioc:
../../bin/linux-arm/my_app st.cmd
While the ioc is running open another terminal. From there you can access the varius record inside the database we loaded. In order to do so use the following command:
-
caget my_record
to read the value inside the record -
caput my_record value
to write a value inside the record -
camonitor my_record
to start a realtime monitor of the value inside the record that is updated each time the record is processed
To control the GPIO pin of the pi through epics we need to install an external library called WiringPi. To install the library you just need to edit the Makefile
located in /home/pi/my_app/my_appApp/src
and add the following line at the end of the file:
my_app_LIBS += wiringPi
Remember to always make
the application after you commit any change.
With this library we can use the following command while programming our subroutine:
-
#include <wiringPi.h>
to include the library in the code -
wiringPiSetup()
to initialise the library. this function must be called at the start of the program -
pinMode(int pin, int mode)
to set up one of the pin. The available mode areINPUT
or outputOUTPUT
. You must specify the wiringPi pin number and not the one written on the header. Here you can find the right pin number. -
digitalWrite(int pin, int value)
to writeHIGH
(1) orLOW
(0) to an output pin. -
wiringPiISR(int pin, int edgeType, &my_interrupt)
to create an interrupt. You can select the type of signal to trigger the interrupt with the edgeType parameter (option areINT_EDGE_FALLING
,INT_EDGE_RISING
). When an interrupt signal comes in the pin selected, the program will execute themy_interrupt
function. This function must bevoid
without any arguments:
void my_interrupt()
If we want the pi to comunicate with a microcontroller we will need two additional libraries: ASYNC and StreamDevice. With this two piece of software we will be able to setup a serial comunication between the epics ioc on the pi and the microcontroller. This is useful if you need to run a real time program on a more stable system; The pi will handle the IOC and will send to the microcontroller the parameter, while the microcontroller will execute the program.
Let's install the libraries. Enter in the ~/Downloads
folder and the download the files with this two command:
wget http://aps.anl.gov/epics/download/modules/asyn4-28.tar.gz
wget http://epics.web.psi.ch/software/streamdevice/StreamDevice-2.tgz
After that go in your EPICS base (~/base-3.14.12.7
) folder and create a new folder called modules
:
cd ~/base
mkdir modules
The first library that we will install is ASYNC, because it's required for StreamDevice. Extract the library and create a soft link to the folder with this two command:
tar -zxf ~/Downloads/asyn4-28.tar.gz -C ~/base-3.14.12.7/modules/
ln -s /home/pi/base-3.14.12.7/modules/asyn4-28 /home/pi/base-3.14.12.7/modules/asyn
After that enter the async folder with cd ~/base-3.14.12.7/modules/async
and edit the RELEASE
file located in the configure
folder using nano
.
-Comment out the IPAC line
-Comment out the SNCSEQ line
-Comment out the EPICS_BASE line and add the following line EPICS_BASE=/home/pi/base-3.14.12.7
After that in ~/base-3.14.12.7/modules/async
run make
.
When this completes, the system is ready for installation of the Stream Device library. Create a new folder inside modules
and then extract there the library that we downloaded. after that run the makeBaseApp.pl
script, with these commands:
mkdir /home/pi/base-3.14.12.7/modules/stream
cd /home/pi/base-3.14.12.7/modules/stream
tar -zxvf ~/Downloads/StreamDevice-2.tgz -C /home/pi/base-3.14.12.7/modules/stream
makeBaseApp.pl -t support
The last command will ask you the application name; just press Enter
to continue.
In order to let StreamDevice knows where ASYNC is, add the following line of code in the RELEASE
file located in the configure folder:
ASYN=/home/pi/base-3.14.12.7/modules/asyn
To finish the installation run make
in ~/base-3.14.12.7/modules/stream
. Once this completes, cd
into StreamDevice-2-6
, and run make
again.
The first thing to do is to tell our epics application where are the two libraries that we just installed. To do so, edit the RELEASE
file located in ~/my_app/configure/
and add the following lines of code:
ASYN=/home/pi/base-3.14.12.7/modules/asyn
STREAM=/home/pi/base-3.14.12.7/modules/stream
After that we need to create a my_protocol.proto
file that will contain the instruction for epics on what to send to the microcontroller via serial communication. Create this file using nano
in the Db folder of your application (~/my_app/my_appApp/Db/
):
Terminator = LF;
set_parameter {
out "P%d\n";
ExtraInput = Ignore;
}
get_value {
out "R";
in "R %s";
ExtraInput = Ignore;
}
The first line tells EPICS how to terminate strings. The function set_parameter
tells epics to write something (in our case the letter "P" followed by an integer and a new line) in the serial bus, while the get_value
tells epics to expect something (in our case the letter "R" followed by a string) from the serial bus. We will use this information later, in the microcontroller code.
Now we need a new database record that will store the parameter that we want to send to the microcontroller. Open my_database.db
using Visual DCT and create a new analog output (ao) record called my_param
. Double click on it to open the properties and edit the DTYP to "stream" and the OUT to @my_protocol.proto set_parameter() $(PORT)
. Every time this record gets processed, the set_parameter()
function defined in the proto file will be executed, with its output going in the serial port indicated (in this case $(PORT)
, we will set the right port in the next step).
Create a second analog input record called my_value
. Double click on it to open the properties and edit the DTYP to "stream" and the INP to @my_protocol.proto get_value() $(PORT)
Now we need to modify the Makefile. Move to ~/my_app/my_appApp/src
and edit the Makefile you find in there using nano
. After the line that says, myapp_DBD += base.dbd
, add the following lines:
my_app_DBD += asyn.dbd
my_app_DBD += stream.dbd
my_app_DBD += drvAsynIPPort.dbd
my_app_DBD += drvAsynSerialPort.dbd
and near the end of the file, after the line # ADD EXTRA GNUMAKE RULES BELOW HERE
add:
my_app_LIBS += asyn
my_app_LIBS += stream
Now move to ~/my_app/iocBoot/iocmy_app
and edit the st.cmd
file. After > envPaths
(near the top), add the following
epicsEnvSet(STREAM_PROTOCOL_PATH,"../../my_appApp/Db")
After the line, ” my_app_registerRecordDeviceDriver pdbbase”, add the following
drvAsynSerialPortConfigure("SERIALPORT","/dev/ttyACM0",0,0,0)
asynSetOption("SERIALPORT",-1,"baud","115200")
asynSetOption("SERIALPORT",-1,"bits","8")
asynSetOption("SERIALPORT",-1,"parity","none")
asynSetOption("SERIALPORT",-1,"stop","1")
asynSetOption("SERIALPORT",-1,"clocal","Y")
asynSetOption("SERIALPORT",-1,"crtscts","N")
dbLoadRecords("db/my_database.db","PORT='SERIALPORT'")
Those lines configure a serial connection called “SERIALPORT”, linked to /dev/ttyACM0 (the microcontroller should be connected to this port, but check if it's true), and then set all the options so that the serial communications works in the way that the microcontroller expects. Now that this connection has been defined, it can be used in place of the $(PORT) variable referred to in the database definition file.
In this same file (st.cmd
), change any references to $(TOP) to /home/pi/my_app
, and any references to $(IOC) to iocmy_app
.
Finally go to ~/my_app
and make
.
Here you can find the full EPICS app folder for the bpm switch project described in the next sections of the wiki.