Skip to content

MBP-388: Safety Implementation - #54

Draft
aslanliafichev wants to merge 11 commits into
masterfrom
MBP-388-safety-implementation
Draft

aslanliafichev wants to merge 11 commits into
masterfrom
MBP-388-safety-implementation

Conversation

@aslanliafichev

@aslanliafichev aslanliafichev commented May 19, 2026

Copy link
Copy Markdown
Collaborator

The goal is to develop a PLC Safety interface for ESTIA, this includes:

  1. Mapping of safety functions and safety related diagnostics from the Safety Controller - PNOZmulti 2 via EtherCAT.
  2. Develop/Use the PILS layer to communicate with EPICS/NICOS
  3. Also include Cabinet/PLC specific logic, for this case Cabinet 3, 4 and 5 for ESTIA

For now the code only focuses on task 1, implementation of task 2 and 3 needs to be fully defined:

  • What do we want to showcase to EPICS/NICOS?
  • What does EPICS/NICOS expect regarding Motion Safety?
  • Should the Safety Controller handle all the execution logic? Or are their cases where the PLC needs to execute specific safety logic?

For changes made to tc_generic: https://github.com/EuropeanSpallationSource/tc_generic_structure/pull/23

Comment thread DUTs/Safety/ST_LEDState.TcDUT Outdated
<DUT Name="ST_LEDState" Id="{f261f142-fde3-0208-2395-07dc6293304d}">
<Declaration><![CDATA[TYPE ST_LEDState :
STRUCT
usiLEDState : USINT;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be just nLEDState
Remove space between colon and variable name

Comment thread DUTs/Safety/ST_PNOZEtherCATIn.TcDUT Outdated
stStatus : ST_SafetyStatus; // Placeholder, WIP
stLEDState : ST_LEDState;
aSafetyFunctionIn : ARRAY[1..GVL_SafetyIO.UPPER_BOUND_SF_INPUT] OF ST_SafetyFunctionIn;
aSubSystemIn : ARRAY[1..GVL_SafetyIO.UPPER_BOUND_SS] OF ST_SubSystemIn; // Placeholder, WIP

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove space between colon and variable name
Remove space from the beginning of the comment message

Comment thread DUTs/Safety/ST_PNOZEtherCATOut.TcDUT Outdated
STRUCT
stFeedback : ST_SafetyFeedback;
aSafetyFunctionOut : ARRAY[1..GVL_SafetyIO.UPPER_BOUND_SF_OUTPUT] OF ST_SafetyFunctionOut;
aSubSystemOut : ARRAY[1..GVL_SafetyIO.UPPER_BOUND_SS] OF ST_SubSystemOut;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove whitespace between colon and variable name

Comment thread DUTs/Safety/ST_PNOZEtherCATStatus.TcDUT Outdated
bitWcState AT %I* : BIT;

{attribute 'TcLinkTo' := 'TIID^PNOZ (EtherCAT)^Box (PNOZ m ES EtherCAT)^WcState^InputToggle'}
bitInputToggle AT %I* : BIT;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BIT should be starting with just b

Comment thread DUTs/Safety/ST_PNOZEtherCATStatus.TcDUT Outdated
nState AT %I* : UINT;

{attribute 'TcLinkTo' := 'TIID^PNOZ (EtherCAT)^Box (PNOZ m ES EtherCAT)^InfoData^AdsAddr^netId'}
amsNetId AT %I* : AMSNETID;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AMSNETID is just a type alias for array of 6 bytes, so I think here aAmsNetID would be the right name.

Comment thread DUTs/Safety/ST_PNOZEtherCATStatus.TcDUT Outdated
amsNetId AT %I* : AMSNETID;

{attribute 'TcLinkTo' := 'TIID^PNOZ (EtherCAT)^Box (PNOZ m ES EtherCAT)^InfoData^AdsAddr^port'}
wPort AT %I* : WORD;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WORD is just a number so this should be nPort

Comment thread DUTs/Safety/ST_SafetyFunctionOut.TcDUT Outdated
<DUT Name="ST_SafetyFunctionOut" Id="{d225f0e9-f4be-0268-2036-d232ca0275b9}">
<Declaration><![CDATA[TYPE ST_SafetyFunctionOut :
STRUCT
byRaw : BYTE;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BYTE is just a number so it should start with n

Comment thread POUs/Safety/FB_MotionSafety.TcPOU Outdated
stSafetyStatus.bValidReference := bRefsLinked;

IF NOT stSafetyStatus.bValidReference THEN
RETURN;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is an extra identation here.

Comment thread POUs/Safety/FB_MotionSafety.TcPOU Outdated
bRefsLinked := mLinkRefs(); // Link references, once
END_IF

stSafetyStatus.bValidReference := bRefsLinked;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whats the reason for bRefsLinked? Cant we write directly to stSafetyStatus.bValidReference instead?

@mac-kan

mac-kan commented Aug 20, 2026

Copy link
Copy Markdown
Collaborator

Related to the discussion yesterday about integrating the output of the safety block with cabinet monitoring. I think the best solution will be to let the safety class implement an interface:

// I_SafetyProvider.TcIO
INTERFACE I_SafetyProvider

PROPERTY P_Estop_OK: BOOL // getter
PROPERTY P_STO_OK: BOOL   // getter
FUNCTION_BLOCK fbSafety IMPLEMENTS I_SafetyProvider
VAR_OUTPUT
    bEstop : BOOL;
    bSTO : BOOL;
END_VAR

Property Getters in fbSafety:

P_Estop_OK := bEstop;

P_STO_OK := bSTO;

Then in fbCabMonitoring:
// Pass fbSafety here. If left empty (0), legacy hardware inputs should be used

VAR_INPUT
    iSafetyProvider : I_SafetyProvider;
END_VAR

// Call the safety block and then the cabinet and inject the safety block directly therein

fbSafety();

fbCabMonitoring(
    iSafetyProvider := fbMySafety
);

And of course then the implementation inside fbCabMonitoring is needed to be updated.

Advantage with this solution is if you add 10 new properties to the I_SafetyProvider interface in the future, fbCabMonitoring wont need to be changed in how it is called. Instead, only the inner logic of the class will be updated, since it already has access to the entire safety block via the interface.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants