Experimental Physics and Industrial Control System
Hi,
I face something similar in my previous jobs, the main difference was we only needed few features : variables values sharing, and timestamps.
As you told CAlab not working with RT modules, and Labview EPICS server is slow(near 0.1s for any transfert) and time consuming because it uses NI shared variables system.
The solution we found was to create our own library in C which use EPICS and then call it in Labview, see below architecture :
Finally, Epics server was on a small raspberry.
For the other Ni-realtime operating system "NIPharlap", I never found a good working solution, so we exchanged variables via sockets between these Target and a gateway which send back value to EPICS server, waiting NI linux RT for every hardware.
Do not hesitate if you wants more info,
Regards,
Hi all!
We have many systems from NI that we would like to integrate with EPICS
for the KATRIN experiment (katrin.kit.edu)
The old control system was written in LabView but we would like to
replace it with EPICS without rewriting the code again. Therefore, we
are looking for a nice LabView-EPICS integration.
We have seen two options for LabView:
- CALAB which does not work with realtime devices
- Official NI EPICS module. It is good but I can list several problems:
huge loss of EPICS features (it is only an implementation of CA plus
alarming, the other metadata and configuration fields are not available)
- not very developer-friendly (adding/removing PVs relies on shared
variables so it is time consuming)
Another two solutions we thought of:
1. Using AsynDriver and communicate with the realtime device using a TCP
protocol
2. Running an EPICS server on the realtime device using NI EPICS module
then shadowing it with a SoftIoc using CA links.
(a softIoc server running with input and output records to read and
write to the original LabView EPICS server)
I have several concerns here:
- Am I missing any other way to integrate LabView with EPICS? I would
like to hear from your experiences.
- Although solution (1) is time consuming, I am in favor of it but let's
check if we can do it more easily with solution (2). Anyway, can the
experts comment on its feasibility?
- Solution (2): What do you think about performance? Alarms? I/O Intr
are not available on a softIoc, so the developer has to use periodic
SCAN. How can I add custom SCAN periods?
Thanks for your help.
Best,
Jalal
--
/* @version: $Id: cb_main.h 183 2009-09-11 13:52:33Z emevel $*/
#ifndef EPCIS_CLIENT_h
#define EPCIS_CLIENT_h
#ifdef __cplusplus
extern "C" {
#endif
/** @brief MgErr is a labview Manager error code type. */
typedef int MgErr;//0 no error ,1 : error
/** @brief InstanceDataPtr is a labview type, it is create by labview see ni relevant documentation for more information */
typedef void* InstanceDataPtr;
typedef InstanceDataPtr* InstanceDataPtrPtr;
/** @brief NAME_SIZE : is the max size for epics name */
#define NAME_SIZE 40
/** @brief SIZE_TABLE : is the maximum number of variable per handle*/
#define SIZE_TABLE 4097
/**
* \struct EPICS_VAR_INIT
* \brief this sturcutre is use to initialize a handle, it contains all var name and the total number of variable
*/
typedef struct str_epics_var_init
{
char epics_val_name_double[SIZE_TABLE][NAME_SIZE+4];
int nbr_element_double;
} EPICS_VAR_INIT;
/**
* \struct EPICS_VAR_INIT
* \brief this sturcutre is return when we call get function
*/
typedef struct str_epics_double_vals
{
double value[SIZE_TABLE];
int nbr_val;
int val_changed[SIZE_TABLE];/*!< it is a table list all value that changed since last get, each cell contain the position of value in value table, or -1 which end the table */
long time_stamp[SIZE_TABLE];/*!< last time when value was update by server, ms since EPICS_client start*/
} EPICS_VAL_GET;
/**\brief BELOW ARE ALL FUNCTION EXPORT
LABV_XXX are function to call specifically for labview
ECL_XXX are function to call for any epics client
To use it refer to example test_client.c, and labiew implementation**/
#ifdef BUILDING_DLL
#define DLL_conv __declspec(dllexport)
#else
#define DLL_conv __declspec(dllimport)
#endif
/**
* \brief Function to create a new EPICS handle
* \return -1 : error, else id of handle
*/
int DLL_conv ecl_create_handle();
/**
* \brief Function for initialize all epics connetions as read
*
* \param EPICS_handle_ID : pass a id to handle (this handler could be used for later read)
* \param Epics_vars_init_read : variable which we will read later
*
* \return 0 okay , 1 : false
*/
int DLL_conv ecl_init_read(int EPICS_handle_ID, EPICS_VAR_INIT Epics_vars_init_read);
/**
* \brief Function to initialize an handle as write
*
* \param EPICS_handle_ID :pass a id to handle (this handler could be used for later read).
* \param Epics_vars_init_write : variable which we will write later
*
* \return 0 okay , 1 : false
*/
int DLL_conv ecl_init_write(int EPICS_handle_ID, EPICS_VAR_INIT Epics_vars_init_write);
/**
* \brief Function to get all varible associated with an hande
*
* \param EPICS_handle_ID :pass a id to handle
* \param EPICS_VAL_GET : structure of value read (must be initialized before beeing send)
*
* \return 0 okay , 1 : false
*/
int DLL_conv ecl_get(int EPICS_handle_ID, EPICS_VAL_GET* Epics_vals);
/**
* \brief Function to get all varible associated with an hande
*
* \param EPICS_handle_ID :pass a id to handle
* \param Epics_vals_to_set : a table containing all value associated with ecl_init_write we previously send
*
* \return 0 okay , 1 : false
*/
int DLL_conv ecl_set(int EPICS_handle_ID, double* Epics_vals_to_set);
/**
* \brief Function for destroy a EPICS handle
*
* \param EPICS_handle_ID :pass a id to handle (this handler could be used for later read).
*
* \return 0 okay , 1 : false
*/
int DLL_conv ecl_clean_handle(int EPICS_handle_ID);
/**
* \brief Function for create an handle in labview
*
* \param Epics_handle_id_ptr_ptr : it is (void**) pointer send by labview
*
* \return 0 okay , 1 : false
*/
MgErr DLL_conv LABV_reserve(InstanceDataPtr* Epics_handle_id_ptr_ptr);
/**
* \brief Function for initialize an handle connetions as read
*
* \param Epics_handle_id_ptr_ptr : (void**) pointer to EPICS_handle_ID that we will use.
* \param epics_val_name_double : variable name table, size of var name is maximum(40char)
* \param nbr_element_double : number of variable in previous table
* \param stderr_message : error console
* \param stdout_message : std console
*
* \return id , -1 : error
*/
int DLL_conv LABV_init_read(InstanceDataPtr* Epics_handle_id_ptr_ptr,const unsigned char* epics_val_name_double, int nbr_element_double, unsigned char* console_message);
/**
* \brief Function for initialize an handle connetions as write
*
* \param Epics_handle_id_ptr_ptr : (void**) pointer to EPICS_handle_ID that we will use.
* \param epics_val_name_double : variable name table, size of var name is maximum(40char)
* \param nbr_element_double : number of variable in previous table
* \param stderr_message : error console
* \param stdout_message : std console
*
* \return id , -1 : error
*/
int DLL_conv LABV_init_write(InstanceDataPtr* Epics_handle_id_ptr_ptr,unsigned char* epics_val_name_double, int nbr_element_double, unsigned char* console_message);
/**
* \brief Function to set value of all variable
*
* \param EPICS_handle_ID :pass a id to handle (this handler could be used for later read).
* \param value : table of double value
* \param nbr_val : nbr of value in table return
* \param val_changed : a table that list all wich value update (only for get), -1 to stop the table example {0,3,5,7,-1} means value 0,3,5, and 7 have changed
* \param stderr_message : error console
* \param stdout_message : std console
*
* \return 0 okay , 1 : false
*/
int DLL_conv LABV_get(int EPICS_handle_ID, double* value,int* nbr_val,int* val_changed,long* time_stamp,unsigned char* console_message);
/**
* \brief Function to set value of all variable
*
* \param EPICS_handle_ID :pass a id to handle (this handler could be used for later read).
* \param Epics_vals_to_set : table of double to set
* \param stderr_message : error console
* \param stdout_message : std console
*
* \return 0 okay , 1 : false
*/
int DLL_conv LABV_set(int EPICS_handle_ID, double* Epics_vals_to_set,unsigned char* console_message);
/**
* \brief Function for destroy a EPICS handle
*
* \param Epics_handle_id_ptr_ptr : (void**) pointer to id that we will use.
*
* \return 0 okay , 1 : false
*/
MgErr DLL_conv LABV_unreserve(InstanceDataPtr* Epics_handle_id_ptr_ptr);
#ifdef __cplusplus
}
#endif
#endif
- References:
- LabView-EPICS Integration using SoftIoc Mostafa, Jalal (IPE) via Tech-talk
- Navigate by Date:
- Prev:
Re: LabView-EPICS Integration using SoftIoc Mostafa, Jalal (IPE) via Tech-talk
- Next:
Re: LabView-EPICS Integration using SoftIoc Mark Rivers via Tech-talk
- Index:
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
<2020>
2021
2022
2023
2024
- Navigate by Thread:
- Prev:
Re: LabView-EPICS Integration using SoftIoc Mark Rivers via Tech-talk
- Next:
RE: LabView-EPICS Integration using SoftIoc Akeroyd, Freddie (STFC, RAL, ISIS) via Tech-talk
- Index:
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
<2020>
2021
2022
2023
2024