Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
osie
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Nikola Balog
osie
Commits
59677959
Commit
59677959
authored
3 years ago
by
Ivan Tyagov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add a new example whoch shows a two couplers being controlled simultanously.
parent
d66706a8
Changes
24
Hide whitespace changes
Inline
Side-by-side
Showing
24 changed files
with
3055 additions
and
0 deletions
+3055
-0
Beremiz/beremiz_tutorial_multiple_couplers_opc_ua/beremiz.xml
...miz/beremiz_tutorial_multiple_couplers_opc_ua/beremiz.xml
+4
-0
Beremiz/beremiz_tutorial_multiple_couplers_opc_ua/build/LOCATED_VARIABLES.h
...torial_multiple_couplers_opc_ua/build/LOCATED_VARIABLES.h
+8
-0
Beremiz/beremiz_tutorial_multiple_couplers_opc_ua/build/POUS.c
...iz/beremiz_tutorial_multiple_couplers_opc_ua/build/POUS.c
+278
-0
Beremiz/beremiz_tutorial_multiple_couplers_opc_ua/build/POUS.h
...iz/beremiz_tutorial_multiple_couplers_opc_ua/build/POUS.h
+147
-0
Beremiz/beremiz_tutorial_multiple_couplers_opc_ua/build/VARIABLES.csv
...miz_tutorial_multiple_couplers_opc_ua/build/VARIABLES.csv
+38
-0
Beremiz/beremiz_tutorial_multiple_couplers_opc_ua/build/beremiz.h
...beremiz_tutorial_multiple_couplers_opc_ua/build/beremiz.h
+35
-0
Beremiz/beremiz_tutorial_multiple_couplers_opc_ua/build/config.c
.../beremiz_tutorial_multiple_couplers_opc_ua/build/config.c
+62
-0
Beremiz/beremiz_tutorial_multiple_couplers_opc_ua/build/config.h
.../beremiz_tutorial_multiple_couplers_opc_ua/build/config.h
+11
-0
Beremiz/beremiz_tutorial_multiple_couplers_opc_ua/build/generated_plc.st
..._tutorial_multiple_couplers_opc_ua/build/generated_plc.st
+70
-0
Beremiz/beremiz_tutorial_multiple_couplers_opc_ua/build/lastbuildPLC.md5
..._tutorial_multiple_couplers_opc_ua/build/lastbuildPLC.md5
+1
-0
Beremiz/beremiz_tutorial_multiple_couplers_opc_ua/build/opcua_client__0.c
...tutorial_multiple_couplers_opc_ua/build/opcua_client__0.c
+115
-0
Beremiz/beremiz_tutorial_multiple_couplers_opc_ua/build/opcua_client__1.c
...tutorial_multiple_couplers_opc_ua/build/opcua_client__1.c
+115
-0
Beremiz/beremiz_tutorial_multiple_couplers_opc_ua/build/plc.st
...iz/beremiz_tutorial_multiple_couplers_opc_ua/build/plc.st
+164
-0
Beremiz/beremiz_tutorial_multiple_couplers_opc_ua/build/plc_debugger.c
...iz_tutorial_multiple_couplers_opc_ua/build/plc_debugger.c
+427
-0
Beremiz/beremiz_tutorial_multiple_couplers_opc_ua/build/plc_main.c
...eremiz_tutorial_multiple_couplers_opc_ua/build/plc_main.c
+959
-0
Beremiz/beremiz_tutorial_multiple_couplers_opc_ua/build/py_ext.c
.../beremiz_tutorial_multiple_couplers_opc_ua/build/py_ext.c
+221
-0
Beremiz/beremiz_tutorial_multiple_couplers_opc_ua/build/resource1.c
...remiz_tutorial_multiple_couplers_opc_ua/build/resource1.c
+37
-0
Beremiz/beremiz_tutorial_multiple_couplers_opc_ua/opcua_0@opcua/baseconfnode.xml
...l_multiple_couplers_opc_ua/opcua_0@opcua/baseconfnode.xml
+2
-0
Beremiz/beremiz_tutorial_multiple_couplers_opc_ua/opcua_0@opcua/confnode.xml
...orial_multiple_couplers_opc_ua/opcua_0@opcua/confnode.xml
+2
-0
Beremiz/beremiz_tutorial_multiple_couplers_opc_ua/opcua_0@opcua/selected.csv
...orial_multiple_couplers_opc_ua/opcua_0@opcua/selected.csv
+16
-0
Beremiz/beremiz_tutorial_multiple_couplers_opc_ua/opcua_1@opcua/baseconfnode.xml
...l_multiple_couplers_opc_ua/opcua_1@opcua/baseconfnode.xml
+2
-0
Beremiz/beremiz_tutorial_multiple_couplers_opc_ua/opcua_1@opcua/confnode.xml
...orial_multiple_couplers_opc_ua/opcua_1@opcua/confnode.xml
+2
-0
Beremiz/beremiz_tutorial_multiple_couplers_opc_ua/opcua_1@opcua/selected.csv
...orial_multiple_couplers_opc_ua/opcua_1@opcua/selected.csv
+16
-0
Beremiz/beremiz_tutorial_multiple_couplers_opc_ua/plc.xml
Beremiz/beremiz_tutorial_multiple_couplers_opc_ua/plc.xml
+323
-0
No files found.
Beremiz/beremiz_tutorial_multiple_couplers_opc_ua/beremiz.xml
0 → 100644
View file @
59677959
<?xml version='1.0' encoding='utf-8'?>
<BeremizRoot
xmlns:xsd=
"http://www.w3.org/2001/XMLSchema"
URI_location=
"LOCAL://"
>
<TargetType/>
</BeremizRoot>
This diff is collapsed.
Click to expand it.
Beremiz/beremiz_tutorial_multiple_couplers_opc_ua/build/LOCATED_VARIABLES.h
0 → 100644
View file @
59677959
__LOCATED_VAR
(
DINT
,
__QD1_0
,
Q
,
D
,
1
,
0
)
__LOCATED_VAR
(
DINT
,
__QD1_1
,
Q
,
D
,
1
,
1
)
__LOCATED_VAR
(
DINT
,
__QD1_2
,
Q
,
D
,
1
,
2
)
__LOCATED_VAR
(
DINT
,
__QD1_3
,
Q
,
D
,
1
,
3
)
__LOCATED_VAR
(
DINT
,
__QD0_0
,
Q
,
D
,
0
,
0
)
__LOCATED_VAR
(
DINT
,
__QD0_1
,
Q
,
D
,
0
,
1
)
__LOCATED_VAR
(
DINT
,
__QD0_2
,
Q
,
D
,
0
,
2
)
__LOCATED_VAR
(
DINT
,
__QD0_3
,
Q
,
D
,
0
,
3
)
This diff is collapsed.
Click to expand it.
Beremiz/beremiz_tutorial_multiple_couplers_opc_ua/build/POUS.c
0 → 100644
View file @
59677959
void
LOGGER_init__
(
LOGGER
*
data__
,
BOOL
retain
)
{
__INIT_VAR
(
data__
->
EN
,
__BOOL_LITERAL
(
TRUE
),
retain
)
__INIT_VAR
(
data__
->
ENO
,
__BOOL_LITERAL
(
TRUE
),
retain
)
__INIT_VAR
(
data__
->
TRIG
,
__BOOL_LITERAL
(
FALSE
),
retain
)
__INIT_VAR
(
data__
->
MSG
,
__STRING_LITERAL
(
0
,
""
),
retain
)
__INIT_VAR
(
data__
->
LEVEL
,
LOGLEVEL__INFO
,
retain
)
__INIT_VAR
(
data__
->
TRIG0
,
__BOOL_LITERAL
(
FALSE
),
retain
)
}
// Code part
void
LOGGER_body__
(
LOGGER
*
data__
)
{
// Control execution
if
(
!
__GET_VAR
(
data__
->
EN
))
{
__SET_VAR
(
data__
->
,
ENO
,,
__BOOL_LITERAL
(
FALSE
));
return
;
}
else
{
__SET_VAR
(
data__
->
,
ENO
,,
__BOOL_LITERAL
(
TRUE
));
}
// Initialise TEMP variables
if
((
__GET_VAR
(
data__
->
TRIG
,)
&&
!
(
__GET_VAR
(
data__
->
TRIG0
,))))
{
#define GetFbVar(var,...) __GET_VAR(data__->var,__VA_ARGS__)
#define SetFbVar(var,val,...) __SET_VAR(data__->,var,__VA_ARGS__,val)
LogMessage
(
GetFbVar
(
LEVEL
),(
char
*
)
GetFbVar
(
MSG
,
.
body
),
GetFbVar
(
MSG
,
.
len
));
#undef GetFbVar
#undef SetFbVar
;
};
__SET_VAR
(
data__
->
,
TRIG0
,,
__GET_VAR
(
data__
->
TRIG
,));
goto
__end
;
__end:
return
;
}
// LOGGER_body__()
void
PYTHON_EVAL_init__
(
PYTHON_EVAL
*
data__
,
BOOL
retain
)
{
__INIT_VAR
(
data__
->
EN
,
__BOOL_LITERAL
(
TRUE
),
retain
)
__INIT_VAR
(
data__
->
ENO
,
__BOOL_LITERAL
(
TRUE
),
retain
)
__INIT_VAR
(
data__
->
TRIG
,
__BOOL_LITERAL
(
FALSE
),
retain
)
__INIT_VAR
(
data__
->
CODE
,
__STRING_LITERAL
(
0
,
""
),
retain
)
__INIT_VAR
(
data__
->
ACK
,
__BOOL_LITERAL
(
FALSE
),
retain
)
__INIT_VAR
(
data__
->
RESULT
,
__STRING_LITERAL
(
0
,
""
),
retain
)
__INIT_VAR
(
data__
->
STATE
,
0
,
retain
)
__INIT_VAR
(
data__
->
BUFFER
,
__STRING_LITERAL
(
0
,
""
),
retain
)
__INIT_VAR
(
data__
->
PREBUFFER
,
__STRING_LITERAL
(
0
,
""
),
retain
)
__INIT_VAR
(
data__
->
TRIGM1
,
__BOOL_LITERAL
(
FALSE
),
retain
)
__INIT_VAR
(
data__
->
TRIGGED
,
__BOOL_LITERAL
(
FALSE
),
retain
)
}
// Code part
void
PYTHON_EVAL_body__
(
PYTHON_EVAL
*
data__
)
{
// Control execution
if
(
!
__GET_VAR
(
data__
->
EN
))
{
__SET_VAR
(
data__
->
,
ENO
,,
__BOOL_LITERAL
(
FALSE
));
return
;
}
else
{
__SET_VAR
(
data__
->
,
ENO
,,
__BOOL_LITERAL
(
TRUE
));
}
// Initialise TEMP variables
__IL_DEFVAR_T
__IL_DEFVAR
;
__IL_DEFVAR_T
__IL_DEFVAR_BACK
;
#define GetFbVar(var,...) __GET_VAR(data__->var,__VA_ARGS__)
#define SetFbVar(var,val,...) __SET_VAR(data__->,var,__VA_ARGS__,val)
extern
void
__PythonEvalFB
(
int
,
PYTHON_EVAL
*
);
__PythonEvalFB
(
0
,
data__
);
#undef GetFbVar
#undef SetFbVar
;
goto
__end
;
__end:
return
;
}
// PYTHON_EVAL_body__()
void
PYTHON_POLL_init__
(
PYTHON_POLL
*
data__
,
BOOL
retain
)
{
__INIT_VAR
(
data__
->
EN
,
__BOOL_LITERAL
(
TRUE
),
retain
)
__INIT_VAR
(
data__
->
ENO
,
__BOOL_LITERAL
(
TRUE
),
retain
)
__INIT_VAR
(
data__
->
TRIG
,
__BOOL_LITERAL
(
FALSE
),
retain
)
__INIT_VAR
(
data__
->
CODE
,
__STRING_LITERAL
(
0
,
""
),
retain
)
__INIT_VAR
(
data__
->
ACK
,
__BOOL_LITERAL
(
FALSE
),
retain
)
__INIT_VAR
(
data__
->
RESULT
,
__STRING_LITERAL
(
0
,
""
),
retain
)
__INIT_VAR
(
data__
->
STATE
,
0
,
retain
)
__INIT_VAR
(
data__
->
BUFFER
,
__STRING_LITERAL
(
0
,
""
),
retain
)
__INIT_VAR
(
data__
->
PREBUFFER
,
__STRING_LITERAL
(
0
,
""
),
retain
)
__INIT_VAR
(
data__
->
TRIGM1
,
__BOOL_LITERAL
(
FALSE
),
retain
)
__INIT_VAR
(
data__
->
TRIGGED
,
__BOOL_LITERAL
(
FALSE
),
retain
)
}
// Code part
void
PYTHON_POLL_body__
(
PYTHON_POLL
*
data__
)
{
// Control execution
if
(
!
__GET_VAR
(
data__
->
EN
))
{
__SET_VAR
(
data__
->
,
ENO
,,
__BOOL_LITERAL
(
FALSE
));
return
;
}
else
{
__SET_VAR
(
data__
->
,
ENO
,,
__BOOL_LITERAL
(
TRUE
));
}
// Initialise TEMP variables
__IL_DEFVAR_T
__IL_DEFVAR
;
__IL_DEFVAR_T
__IL_DEFVAR_BACK
;
#define GetFbVar(var,...) __GET_VAR(data__->var,__VA_ARGS__)
#define SetFbVar(var,val,...) __SET_VAR(data__->,var,__VA_ARGS__,val)
extern
void
__PythonEvalFB
(
int
,
PYTHON_EVAL
*
);
__PythonEvalFB
(
1
,(
PYTHON_EVAL
*
)(
void
*
)
data__
);
#undef GetFbVar
#undef SetFbVar
;
goto
__end
;
__end:
return
;
}
// PYTHON_POLL_body__()
void
PYTHON_GEAR_init__
(
PYTHON_GEAR
*
data__
,
BOOL
retain
)
{
__INIT_VAR
(
data__
->
EN
,
__BOOL_LITERAL
(
TRUE
),
retain
)
__INIT_VAR
(
data__
->
ENO
,
__BOOL_LITERAL
(
TRUE
),
retain
)
__INIT_VAR
(
data__
->
N
,
0
,
retain
)
__INIT_VAR
(
data__
->
TRIG
,
__BOOL_LITERAL
(
FALSE
),
retain
)
__INIT_VAR
(
data__
->
CODE
,
__STRING_LITERAL
(
0
,
""
),
retain
)
__INIT_VAR
(
data__
->
ACK
,
__BOOL_LITERAL
(
FALSE
),
retain
)
__INIT_VAR
(
data__
->
RESULT
,
__STRING_LITERAL
(
0
,
""
),
retain
)
PYTHON_EVAL_init__
(
&
data__
->
PY_EVAL
,
retain
);
__INIT_VAR
(
data__
->
COUNTER
,
0
,
retain
)
__INIT_VAR
(
data__
->
_TMP_ADD10_OUT
,
0
,
retain
)
__INIT_VAR
(
data__
->
_TMP_EQ13_OUT
,
__BOOL_LITERAL
(
FALSE
),
retain
)
__INIT_VAR
(
data__
->
_TMP_SEL15_OUT
,
0
,
retain
)
__INIT_VAR
(
data__
->
_TMP_AND7_OUT
,
__BOOL_LITERAL
(
FALSE
),
retain
)
}
// Code part
void
PYTHON_GEAR_body__
(
PYTHON_GEAR
*
data__
)
{
// Control execution
if
(
!
__GET_VAR
(
data__
->
EN
))
{
__SET_VAR
(
data__
->
,
ENO
,,
__BOOL_LITERAL
(
FALSE
));
return
;
}
else
{
__SET_VAR
(
data__
->
,
ENO
,,
__BOOL_LITERAL
(
TRUE
));
}
// Initialise TEMP variables
__SET_VAR
(
data__
->
,
_TMP_ADD10_OUT
,,
ADD__UINT__UINT
(
(
BOOL
)
__BOOL_LITERAL
(
TRUE
),
NULL
,
(
UINT
)
2
,
(
UINT
)
__GET_VAR
(
data__
->
COUNTER
,),
(
UINT
)
1
));
__SET_VAR
(
data__
->
,
_TMP_EQ13_OUT
,,
EQ__BOOL__UINT
(
(
BOOL
)
__BOOL_LITERAL
(
TRUE
),
NULL
,
(
UINT
)
2
,
(
UINT
)
__GET_VAR
(
data__
->
N
,),
(
UINT
)
__GET_VAR
(
data__
->
_TMP_ADD10_OUT
,)));
__SET_VAR
(
data__
->
,
_TMP_SEL15_OUT
,,
SEL__UINT__BOOL__UINT__UINT
(
(
BOOL
)
__BOOL_LITERAL
(
TRUE
),
NULL
,
(
BOOL
)
__GET_VAR
(
data__
->
_TMP_EQ13_OUT
,),
(
UINT
)
__GET_VAR
(
data__
->
_TMP_ADD10_OUT
,),
(
UINT
)
0
));
__SET_VAR
(
data__
->
,
COUNTER
,,
__GET_VAR
(
data__
->
_TMP_SEL15_OUT
,));
__SET_VAR
(
data__
->
,
_TMP_AND7_OUT
,,
AND__BOOL__BOOL
(
(
BOOL
)
__BOOL_LITERAL
(
TRUE
),
NULL
,
(
UINT
)
2
,
(
BOOL
)
__GET_VAR
(
data__
->
_TMP_EQ13_OUT
,),
(
BOOL
)
__GET_VAR
(
data__
->
TRIG
,)));
__SET_VAR
(
data__
->
PY_EVAL
.,
TRIG
,,
__GET_VAR
(
data__
->
_TMP_AND7_OUT
,));
__SET_VAR
(
data__
->
PY_EVAL
.,
CODE
,,
__GET_VAR
(
data__
->
CODE
,));
PYTHON_EVAL_body__
(
&
data__
->
PY_EVAL
);
__SET_VAR
(
data__
->
,
ACK
,,
__GET_VAR
(
data__
->
PY_EVAL
.
ACK
,));
__SET_VAR
(
data__
->
,
RESULT
,,
__GET_VAR
(
data__
->
PY_EVAL
.
RESULT
,));
goto
__end
;
__end:
return
;
}
// PYTHON_GEAR_body__()
void
COUNTERST_init__
(
COUNTERST
*
data__
,
BOOL
retain
)
{
__INIT_VAR
(
data__
->
EN
,
__BOOL_LITERAL
(
TRUE
),
retain
)
__INIT_VAR
(
data__
->
ENO
,
__BOOL_LITERAL
(
TRUE
),
retain
)
__INIT_VAR
(
data__
->
RESET
,
__BOOL_LITERAL
(
FALSE
),
retain
)
__INIT_VAR
(
data__
->
OUT1
,
0
,
retain
)
__INIT_VAR
(
data__
->
OUT0
,
0
,
retain
)
__INIT_VAR
(
data__
->
CNT1
,
0
,
retain
)
__INIT_VAR
(
data__
->
CNT0
,
0
,
retain
)
__INIT_EXTERNAL
(
INT
,
RESETCOUNTERVALUE
,
data__
->
RESETCOUNTERVALUE
,
retain
)
__INIT_EXTERNAL
(
DINT
,
RELAY0
,
data__
->
RELAY0
,
retain
)
__INIT_EXTERNAL
(
DINT
,
RELAY1
,
data__
->
RELAY1
,
retain
)
__INIT_EXTERNAL
(
DINT
,
RELAY2
,
data__
->
RELAY2
,
retain
)
__INIT_EXTERNAL
(
DINT
,
RELAY3
,
data__
->
RELAY3
,
retain
)
__INIT_EXTERNAL
(
DINT
,
RELAY4
,
data__
->
RELAY4
,
retain
)
__INIT_EXTERNAL
(
DINT
,
RELAY5
,
data__
->
RELAY5
,
retain
)
__INIT_EXTERNAL
(
DINT
,
RELAY6
,
data__
->
RELAY6
,
retain
)
__INIT_EXTERNAL
(
DINT
,
RELAY7
,
data__
->
RELAY7
,
retain
)
}
// Code part
void
COUNTERST_body__
(
COUNTERST
*
data__
)
{
// Control execution
if
(
!
__GET_VAR
(
data__
->
EN
))
{
__SET_VAR
(
data__
->
,
ENO
,,
__BOOL_LITERAL
(
FALSE
));
return
;
}
else
{
__SET_VAR
(
data__
->
,
ENO
,,
__BOOL_LITERAL
(
TRUE
));
}
// Initialise TEMP variables
__SET_VAR
(
data__
->
,
CNT1
,,(
__GET_VAR
(
data__
->
CNT1
,)
+
1
));
if
((
__GET_VAR
(
data__
->
CNT1
,)
==
100
))
{
__SET_EXTERNAL
(
data__
->
,
RELAY0
,,(
__GET_EXTERNAL
(
data__
->
RELAY0
,)
+
1
));
__SET_VAR
(
data__
->
,
CNT1
,,
0
);
__SET_EXTERNAL
(
data__
->
,
RELAY7
,,
__GET_EXTERNAL
(
data__
->
RELAY0
,));
};
__SET_VAR
(
data__
->
,
OUT1
,,
__GET_VAR
(
data__
->
CNT1
,));
__SET_VAR
(
data__
->
,
OUT0
,,
__GET_VAR
(
data__
->
CNT0
,));
goto
__end
;
__end:
return
;
}
// COUNTERST_body__()
void
PLC_PRG_init__
(
PLC_PRG
*
data__
,
BOOL
retain
)
{
__INIT_VAR
(
data__
->
RESET
,
__BOOL_LITERAL
(
FALSE
),
retain
)
__INIT_VAR
(
data__
->
CNT0
,
0
,
retain
)
__INIT_VAR
(
data__
->
CNT1
,
0
,
retain
)
COUNTERST_init__
(
&
data__
->
COUNTERST0
,
retain
);
}
// Code part
void
PLC_PRG_body__
(
PLC_PRG
*
data__
)
{
// Initialise TEMP variables
__SET_VAR
(
data__
->
COUNTERST0
.,
RESET
,,
__GET_VAR
(
data__
->
RESET
,));
COUNTERST_body__
(
&
data__
->
COUNTERST0
);
__SET_VAR
(
data__
->
,
CNT1
,,
__GET_VAR
(
data__
->
COUNTERST0
.
OUT1
,));
__SET_VAR
(
data__
->
,
CNT0
,,
__GET_VAR
(
data__
->
COUNTERST0
.
OUT0
,));
goto
__end
;
__end:
return
;
}
// PLC_PRG_body__()
This diff is collapsed.
Click to expand it.
Beremiz/beremiz_tutorial_multiple_couplers_opc_ua/build/POUS.h
0 → 100644
View file @
59677959
#include "beremiz.h"
#ifndef __POUS_H
#define __POUS_H
#include "accessor.h"
#include "iec_std_lib.h"
__DECLARE_ENUMERATED_TYPE
(
LOGLEVEL
,
LOGLEVEL__CRITICAL
,
LOGLEVEL__WARNING
,
LOGLEVEL__INFO
,
LOGLEVEL__DEBUG
)
// FUNCTION_BLOCK LOGGER
// Data part
typedef
struct
{
// FB Interface - IN, OUT, IN_OUT variables
__DECLARE_VAR
(
BOOL
,
EN
)
__DECLARE_VAR
(
BOOL
,
ENO
)
__DECLARE_VAR
(
BOOL
,
TRIG
)
__DECLARE_VAR
(
STRING
,
MSG
)
__DECLARE_VAR
(
LOGLEVEL
,
LEVEL
)
// FB private variables - TEMP, private and located variables
__DECLARE_VAR
(
BOOL
,
TRIG0
)
}
LOGGER
;
void
LOGGER_init__
(
LOGGER
*
data__
,
BOOL
retain
);
// Code part
void
LOGGER_body__
(
LOGGER
*
data__
);
// FUNCTION_BLOCK PYTHON_EVAL
// Data part
typedef
struct
{
// FB Interface - IN, OUT, IN_OUT variables
__DECLARE_VAR
(
BOOL
,
EN
)
__DECLARE_VAR
(
BOOL
,
ENO
)
__DECLARE_VAR
(
BOOL
,
TRIG
)
__DECLARE_VAR
(
STRING
,
CODE
)
__DECLARE_VAR
(
BOOL
,
ACK
)
__DECLARE_VAR
(
STRING
,
RESULT
)
// FB private variables - TEMP, private and located variables
__DECLARE_VAR
(
DWORD
,
STATE
)
__DECLARE_VAR
(
STRING
,
BUFFER
)
__DECLARE_VAR
(
STRING
,
PREBUFFER
)
__DECLARE_VAR
(
BOOL
,
TRIGM1
)
__DECLARE_VAR
(
BOOL
,
TRIGGED
)
}
PYTHON_EVAL
;
void
PYTHON_EVAL_init__
(
PYTHON_EVAL
*
data__
,
BOOL
retain
);
// Code part
void
PYTHON_EVAL_body__
(
PYTHON_EVAL
*
data__
);
// FUNCTION_BLOCK PYTHON_POLL
// Data part
typedef
struct
{
// FB Interface - IN, OUT, IN_OUT variables
__DECLARE_VAR
(
BOOL
,
EN
)
__DECLARE_VAR
(
BOOL
,
ENO
)
__DECLARE_VAR
(
BOOL
,
TRIG
)
__DECLARE_VAR
(
STRING
,
CODE
)
__DECLARE_VAR
(
BOOL
,
ACK
)
__DECLARE_VAR
(
STRING
,
RESULT
)
// FB private variables - TEMP, private and located variables
__DECLARE_VAR
(
DWORD
,
STATE
)
__DECLARE_VAR
(
STRING
,
BUFFER
)
__DECLARE_VAR
(
STRING
,
PREBUFFER
)
__DECLARE_VAR
(
BOOL
,
TRIGM1
)
__DECLARE_VAR
(
BOOL
,
TRIGGED
)
}
PYTHON_POLL
;
void
PYTHON_POLL_init__
(
PYTHON_POLL
*
data__
,
BOOL
retain
);
// Code part
void
PYTHON_POLL_body__
(
PYTHON_POLL
*
data__
);
// FUNCTION_BLOCK PYTHON_GEAR
// Data part
typedef
struct
{
// FB Interface - IN, OUT, IN_OUT variables
__DECLARE_VAR
(
BOOL
,
EN
)
__DECLARE_VAR
(
BOOL
,
ENO
)
__DECLARE_VAR
(
UINT
,
N
)
__DECLARE_VAR
(
BOOL
,
TRIG
)
__DECLARE_VAR
(
STRING
,
CODE
)
__DECLARE_VAR
(
BOOL
,
ACK
)
__DECLARE_VAR
(
STRING
,
RESULT
)
// FB private variables - TEMP, private and located variables
PYTHON_EVAL
PY_EVAL
;
__DECLARE_VAR
(
UINT
,
COUNTER
)
__DECLARE_VAR
(
UINT
,
_TMP_ADD10_OUT
)
__DECLARE_VAR
(
BOOL
,
_TMP_EQ13_OUT
)
__DECLARE_VAR
(
UINT
,
_TMP_SEL15_OUT
)
__DECLARE_VAR
(
BOOL
,
_TMP_AND7_OUT
)
}
PYTHON_GEAR
;
void
PYTHON_GEAR_init__
(
PYTHON_GEAR
*
data__
,
BOOL
retain
);
// Code part
void
PYTHON_GEAR_body__
(
PYTHON_GEAR
*
data__
);
// FUNCTION_BLOCK COUNTERST
// Data part
typedef
struct
{
// FB Interface - IN, OUT, IN_OUT variables
__DECLARE_VAR
(
BOOL
,
EN
)
__DECLARE_VAR
(
BOOL
,
ENO
)
__DECLARE_VAR
(
BOOL
,
RESET
)
__DECLARE_VAR
(
INT
,
OUT1
)
__DECLARE_VAR
(
INT
,
OUT0
)
// FB private variables - TEMP, private and located variables
__DECLARE_VAR
(
INT
,
CNT1
)
__DECLARE_VAR
(
INT
,
CNT0
)
__DECLARE_EXTERNAL
(
INT
,
RESETCOUNTERVALUE
)
__DECLARE_EXTERNAL
(
DINT
,
RELAY0
)
__DECLARE_EXTERNAL
(
DINT
,
RELAY1
)
__DECLARE_EXTERNAL
(
DINT
,
RELAY2
)
__DECLARE_EXTERNAL
(
DINT
,
RELAY3
)
__DECLARE_EXTERNAL
(
DINT
,
RELAY4
)
__DECLARE_EXTERNAL
(
DINT
,
RELAY5
)
__DECLARE_EXTERNAL
(
DINT
,
RELAY6
)
__DECLARE_EXTERNAL
(
DINT
,
RELAY7
)
}
COUNTERST
;
void
COUNTERST_init__
(
COUNTERST
*
data__
,
BOOL
retain
);
// Code part
void
COUNTERST_body__
(
COUNTERST
*
data__
);
// PROGRAM PLC_PRG
// Data part
typedef
struct
{
// PROGRAM Interface - IN, OUT, IN_OUT variables
__DECLARE_VAR
(
BOOL
,
RESET
)
__DECLARE_VAR
(
INT
,
CNT0
)
__DECLARE_VAR
(
INT
,
CNT1
)
// PROGRAM private variables - TEMP, private and located variables
COUNTERST
COUNTERST0
;
}
PLC_PRG
;
void
PLC_PRG_init__
(
PLC_PRG
*
data__
,
BOOL
retain
);
// Code part
void
PLC_PRG_body__
(
PLC_PRG
*
data__
);
#endif //__POUS_H
This diff is collapsed.
Click to expand it.
Beremiz/beremiz_tutorial_multiple_couplers_opc_ua/build/VARIABLES.csv
0 → 100644
View file @
59677959
// Programs
0;CONFIG.RESOURCE1.INSTANCE0;PLC_PRG;
// Variables
0;VAR;CONFIG.RESETCOUNTERVALUE;CONFIG.RESETCOUNTERVALUE;INT;INT;
1;OUT;CONFIG.RELAY0;CONFIG.RELAY0;DINT;DINT;
2;OUT;CONFIG.RELAY1;CONFIG.RELAY1;DINT;DINT;
3;OUT;CONFIG.RELAY2;CONFIG.RELAY2;DINT;DINT;
4;OUT;CONFIG.RELAY3;CONFIG.RELAY3;DINT;DINT;
5;OUT;CONFIG.RELAY4;CONFIG.RELAY4;DINT;DINT;
6;OUT;CONFIG.RELAY5;CONFIG.RELAY5;DINT;DINT;
7;OUT;CONFIG.RELAY6;CONFIG.RELAY6;DINT;DINT;
8;OUT;CONFIG.RELAY7;CONFIG.RELAY7;DINT;DINT;
9;FB;CONFIG.RESOURCE1.INSTANCE0;CONFIG.RESOURCE1.INSTANCE0;PLC_PRG;;
10;VAR;CONFIG.RESOURCE1.INSTANCE0.RESET;CONFIG.RESOURCE1.INSTANCE0.RESET;BOOL;BOOL;
11;VAR;CONFIG.RESOURCE1.INSTANCE0.CNT0;CONFIG.RESOURCE1.INSTANCE0.CNT0;INT;INT;
12;VAR;CONFIG.RESOURCE1.INSTANCE0.CNT1;CONFIG.RESOURCE1.INSTANCE0.CNT1;INT;INT;
13;FB;CONFIG.RESOURCE1.INSTANCE0.COUNTERST0;CONFIG.RESOURCE1.INSTANCE0.COUNTERST0;COUNTERST;;
14;VAR;CONFIG.RESOURCE1.INSTANCE0.COUNTERST0.EN;CONFIG.RESOURCE1.INSTANCE0.COUNTERST0.EN;BOOL;BOOL;
15;VAR;CONFIG.RESOURCE1.INSTANCE0.COUNTERST0.ENO;CONFIG.RESOURCE1.INSTANCE0.COUNTERST0.ENO;BOOL;BOOL;
16;VAR;CONFIG.RESOURCE1.INSTANCE0.COUNTERST0.RESET;CONFIG.RESOURCE1.INSTANCE0.COUNTERST0.RESET;BOOL;BOOL;
17;VAR;CONFIG.RESOURCE1.INSTANCE0.COUNTERST0.OUT1;CONFIG.RESOURCE1.INSTANCE0.COUNTERST0.OUT1;INT;INT;
18;VAR;CONFIG.RESOURCE1.INSTANCE0.COUNTERST0.OUT0;CONFIG.RESOURCE1.INSTANCE0.COUNTERST0.OUT0;INT;INT;
19;VAR;CONFIG.RESOURCE1.INSTANCE0.COUNTERST0.CNT1;CONFIG.RESOURCE1.INSTANCE0.COUNTERST0.CNT1;INT;INT;
20;VAR;CONFIG.RESOURCE1.INSTANCE0.COUNTERST0.CNT0;CONFIG.RESOURCE1.INSTANCE0.COUNTERST0.CNT0;INT;INT;
21;EXT;CONFIG.RESOURCE1.INSTANCE0.COUNTERST0.RESETCOUNTERVALUE;CONFIG.RESOURCE1.INSTANCE0.COUNTERST0.RESETCOUNTERVALUE;INT;INT;
22;EXT;CONFIG.RESOURCE1.INSTANCE0.COUNTERST0.RELAY0;CONFIG.RESOURCE1.INSTANCE0.COUNTERST0.RELAY0;DINT;DINT;
23;EXT;CONFIG.RESOURCE1.INSTANCE0.COUNTERST0.RELAY1;CONFIG.RESOURCE1.INSTANCE0.COUNTERST0.RELAY1;DINT;DINT;
24;EXT;CONFIG.RESOURCE1.INSTANCE0.COUNTERST0.RELAY2;CONFIG.RESOURCE1.INSTANCE0.COUNTERST0.RELAY2;DINT;DINT;
25;EXT;CONFIG.RESOURCE1.INSTANCE0.COUNTERST0.RELAY3;CONFIG.RESOURCE1.INSTANCE0.COUNTERST0.RELAY3;DINT;DINT;
26;EXT;CONFIG.RESOURCE1.INSTANCE0.COUNTERST0.RELAY4;CONFIG.RESOURCE1.INSTANCE0.COUNTERST0.RELAY4;DINT;DINT;
27;EXT;CONFIG.RESOURCE1.INSTANCE0.COUNTERST0.RELAY5;CONFIG.RESOURCE1.INSTANCE0.COUNTERST0.RELAY5;DINT;DINT;
28;EXT;CONFIG.RESOURCE1.INSTANCE0.COUNTERST0.RELAY6;CONFIG.RESOURCE1.INSTANCE0.COUNTERST0.RELAY6;DINT;DINT;
29;EXT;CONFIG.RESOURCE1.INSTANCE0.COUNTERST0.RELAY7;CONFIG.RESOURCE1.INSTANCE0.COUNTERST0.RELAY7;DINT;DINT;
// Ticktime
20000000
This diff is collapsed.
Click to expand it.
Beremiz/beremiz_tutorial_multiple_couplers_opc_ua/build/beremiz.h
0 → 100644
View file @
59677959
#ifndef _BEREMIZ_H_
#define _BEREMIZ_H_
/* Beremiz' header file for use by extensions */
#include "iec_types.h"
#define LOG_LEVELS 4
#define LOG_CRITICAL 0
#define LOG_WARNING 1
#define LOG_INFO 2
#define LOG_DEBUG 3
extern
unsigned
long
long
common_ticktime__
;
#ifdef TARGET_LOGGING_DISABLE
static
inline
int
LogMessage
(
uint8_t
level
,
char
*
buf
,
uint32_t
size
)
{
(
void
)
level
;
(
void
)
buf
;
(
void
)
size
;
return
0
;
}
#else
int
LogMessage
(
uint8_t
level
,
char
*
buf
,
uint32_t
size
);
#endif
long
AtomicCompareExchange
(
long
*
atomicvar
,
long
compared
,
long
exchange
);
void
*
create_RT_to_nRT_signal
(
char
*
name
);
void
delete_RT_to_nRT_signal
(
void
*
handle
);
int
wait_RT_to_nRT_signal
(
void
*
handle
);
int
unblock_RT_to_nRT_signal
(
void
*
handle
);
void
nRT_reschedule
(
void
);
#endif
This diff is collapsed.
Click to expand it.
Beremiz/beremiz_tutorial_multiple_couplers_opc_ua/build/config.c
0 → 100644
View file @
59677959
/*******************************************/
/* FILE GENERATED BY iec2c */
/* Editing this file is not recommended... */
/*******************************************/
#include "iec_std_lib.h"
#include "accessor.h"
#include "POUS.h"
// CONFIGURATION CONFIG
__DECLARE_GLOBAL
(
INT
,
CONFIG
,
RESETCOUNTERVALUE
)
__DECLARE_GLOBAL_LOCATION
(
DINT
,
__QD1_0
)
__DECLARE_GLOBAL_LOCATED
(
DINT
,
CONFIG
,
RELAY0
)
__DECLARE_GLOBAL_LOCATION
(
DINT
,
__QD1_1
)
__DECLARE_GLOBAL_LOCATED
(
DINT
,
CONFIG
,
RELAY1
)
__DECLARE_GLOBAL_LOCATION
(
DINT
,
__QD1_2
)
__DECLARE_GLOBAL_LOCATED
(
DINT
,
CONFIG
,
RELAY2
)
__DECLARE_GLOBAL_LOCATION
(
DINT
,
__QD1_3
)
__DECLARE_GLOBAL_LOCATED
(
DINT
,
CONFIG
,
RELAY3
)
__DECLARE_GLOBAL_LOCATION
(
DINT
,
__QD0_0
)
__DECLARE_GLOBAL_LOCATED
(
DINT
,
CONFIG
,
RELAY4
)
__DECLARE_GLOBAL_LOCATION
(
DINT
,
__QD0_1
)
__DECLARE_GLOBAL_LOCATED
(
DINT
,
CONFIG
,
RELAY5
)
__DECLARE_GLOBAL_LOCATION
(
DINT
,
__QD0_2
)
__DECLARE_GLOBAL_LOCATED
(
DINT
,
CONFIG
,
RELAY6
)
__DECLARE_GLOBAL_LOCATION
(
DINT
,
__QD0_3
)
__DECLARE_GLOBAL_LOCATED
(
DINT
,
CONFIG
,
RELAY7
)
void
RESOURCE1_init__
(
void
);
void
config_init__
(
void
)
{
BOOL
retain
;
retain
=
0
;
__INIT_GLOBAL
(
INT
,
RESETCOUNTERVALUE
,
__INITIAL_VALUE
(
0
),
retain
)
__INIT_GLOBAL_LOCATED
(
CONFIG
,
RELAY0
,
__QD1_0
,
retain
)
__INIT_GLOBAL
(
DINT
,
RELAY0
,
__INITIAL_VALUE
(
0
),
retain
)
__INIT_GLOBAL_LOCATED
(
CONFIG
,
RELAY1
,
__QD1_1
,
retain
)
__INIT_GLOBAL
(
DINT
,
RELAY1
,
__INITIAL_VALUE
(
0
),
retain
)
__INIT_GLOBAL_LOCATED
(
CONFIG
,
RELAY2
,
__QD1_2
,
retain
)
__INIT_GLOBAL
(
DINT
,
RELAY2
,
__INITIAL_VALUE
(
0
),
retain
)
__INIT_GLOBAL_LOCATED
(
CONFIG
,
RELAY3
,
__QD1_3
,
retain
)
__INIT_GLOBAL
(
DINT
,
RELAY3
,
__INITIAL_VALUE
(
0
),
retain
)
__INIT_GLOBAL_LOCATED
(
CONFIG
,
RELAY4
,
__QD0_0
,
retain
)
__INIT_GLOBAL
(
DINT
,
RELAY4
,
__INITIAL_VALUE
(
0
),
retain
)
__INIT_GLOBAL_LOCATED
(
CONFIG
,
RELAY5
,
__QD0_1
,
retain
)
__INIT_GLOBAL
(
DINT
,
RELAY5
,
__INITIAL_VALUE
(
0
),
retain
)
__INIT_GLOBAL_LOCATED
(
CONFIG
,
RELAY6
,
__QD0_2
,
retain
)
__INIT_GLOBAL
(
DINT
,
RELAY6
,
__INITIAL_VALUE
(
0
),
retain
)
__INIT_GLOBAL_LOCATED
(
CONFIG
,
RELAY7
,
__QD0_3
,
retain
)
__INIT_GLOBAL
(
DINT
,
RELAY7
,
__INITIAL_VALUE
(
0
),
retain
)
RESOURCE1_init__
();
}
void
RESOURCE1_run__
(
unsigned
long
tick
);
void
config_run__
(
unsigned
long
tick
)
{
RESOURCE1_run__
(
tick
);
}
unsigned
long
long
common_ticktime__
=
20000000ULL
*
1ULL
;
/*ns*/
unsigned
long
greatest_tick_count__
=
(
unsigned
long
)
0UL
;
/*tick*/
This diff is collapsed.
Click to expand it.
Beremiz/beremiz_tutorial_multiple_couplers_opc_ua/build/config.h
0 → 100644
View file @
59677959
#include "beremiz.h"
__DECLARE_GLOBAL_PROTOTYPE
(
INT
,
RESETCOUNTERVALUE
)
__DECLARE_GLOBAL_PROTOTYPE
(
DINT
,
RELAY0
)
__DECLARE_GLOBAL_PROTOTYPE
(
DINT
,
RELAY1
)
__DECLARE_GLOBAL_PROTOTYPE
(
DINT
,
RELAY2
)
__DECLARE_GLOBAL_PROTOTYPE
(
DINT
,
RELAY3
)
__DECLARE_GLOBAL_PROTOTYPE
(
DINT
,
RELAY4
)
__DECLARE_GLOBAL_PROTOTYPE
(
DINT
,
RELAY5
)
__DECLARE_GLOBAL_PROTOTYPE
(
DINT
,
RELAY6
)
__DECLARE_GLOBAL_PROTOTYPE
(
DINT
,
RELAY7
)
This diff is collapsed.
Click to expand it.
Beremiz/beremiz_tutorial_multiple_couplers_opc_ua/build/generated_plc.st
0 → 100644
View file @
59677959
FUNCTION_BLOCK
CounterST
VAR_INPUT
Reset
:
BOOL
;
END_VAR
VAR_OUTPUT
Out1
:
INT
;
Out0
:
INT
;
END_VAR
VAR
Cnt1
:
INT
;
Cnt0
:
INT
;
END_VAR
VAR_EXTERNAL
ResetCounterValue
:
INT
;
Relay0
:
DINT
;
Relay1
:
DINT
;
Relay2
:
DINT
;
Relay3
:
DINT
;
Relay4
:
DINT
;
Relay5
:
DINT
;
Relay6
:
DINT
;
Relay7
:
DINT
;
END_VAR
Cnt1
:=
Cnt1
+
1
;
IF
Cnt1
=
100
THEN
Relay0
:=
Relay0
+
1
;
Cnt1
:=
0
;
Relay7
:=
Relay0
;
END_IF
;
Out1
:=
Cnt1
;
Out0
:=
Cnt0
;
END_FUNCTION_BLOCK
PROGRAM
plc_prg
VAR_INPUT
Reset
:
BOOL
;
END_VAR
VAR_OUTPUT
Cnt0
:
INT
;
Cnt1
:
INT
;
END_VAR
VAR
CounterST0
:
CounterST
;
END_VAR
CounterST0
(
Reset
:=
Reset
);
Cnt1
:=
CounterST0
.
Out1
;
Cnt0
:=
CounterST0
.
Out0
;
END_PROGRAM
CONFIGURATION
config
VAR_GLOBAL
ResetCounterValue
:
INT
:=
0
;
Relay0
AT
%
QD1
.
0
:
DINT
:=
0
;
Relay1
AT
%
QD1
.
1
:
DINT
:=
0
;
Relay2
AT
%
QD1
.
2
:
DINT
:=
0
;
Relay3
AT
%
QD1
.
3
:
DINT
:=
0
;
Relay4
AT
%
QD0
.
0
:
DINT
:=
0
;
Relay5
AT
%
QD0
.
1
:
DINT
:=
0
;
Relay6
AT
%
QD0
.
2
:
DINT
:=
0
;
Relay7
AT
%
QD0
.
3
:
DINT
:=
0
;
END_VAR
RESOURCE
resource1
ON
PLC
TASK
task0
(
INTERVAL
:=
T
#20ms
,
PRIORITY
:=
0
);
PROGRAM
instance0
WITH
task0
:
plc_prg
;
END_RESOURCE
END_CONFIGURATION
This diff is collapsed.
Click to expand it.
Beremiz/beremiz_tutorial_multiple_couplers_opc_ua/build/lastbuildPLC.md5
0 → 100644
View file @
59677959
32859094401bf4365af30f2ffc3c1279
\ No newline at end of file
This diff is collapsed.
Click to expand it.
Beremiz/beremiz_tutorial_multiple_couplers_opc_ua/build/opcua_client__0.c
0 → 100644
View file @
59677959
/* code generated by beremiz OPC-UA extension */
#include <open62541/client_config_default.h>
#include <open62541/client_highlevel.h>
#include <open62541/plugin/log_stdout.h>
UA_Client
*
client
;
#define DECL_VAR(ua_type, C_type, c_loc_name) \
UA_Variant c_loc_name##_variant; \
C_type c_loc_name##_buf = 0; \
C_type *c_loc_name = &c_loc_name##_buf;
DECL_VAR
(
UA_Int32
,
uint32_t
,
__ID0_0
)
DECL_VAR
(
UA_Int32
,
uint32_t
,
__ID0_1
)
DECL_VAR
(
UA_Int32
,
uint32_t
,
__ID0_2
)
DECL_VAR
(
UA_Int32
,
uint32_t
,
__ID0_3
)
DECL_VAR
(
UA_Int32
,
uint32_t
,
__ID0_4
)
DECL_VAR
(
UA_Int32
,
uint32_t
,
__ID0_5
)
DECL_VAR
(
UA_Int32
,
uint32_t
,
__ID0_6
)
DECL_VAR
(
UA_Int32
,
uint32_t
,
__ID0_7
)
DECL_VAR
(
UA_Int32
,
uint32_t
,
__QD0_0
)
DECL_VAR
(
UA_Int32
,
uint32_t
,
__QD0_1
)
DECL_VAR
(
UA_Int32
,
uint32_t
,
__QD0_2
)
DECL_VAR
(
UA_Int32
,
uint32_t
,
__QD0_3
)
DECL_VAR
(
UA_Int32
,
uint32_t
,
__QD0_4
)
DECL_VAR
(
UA_Int32
,
uint32_t
,
__QD0_5
)
DECL_VAR
(
UA_Int32
,
uint32_t
,
__QD0_6
)
DECL_VAR
(
UA_Int32
,
uint32_t
,
__QD0_7
)
void
__cleanup_0
(
void
)
{
UA_Client_disconnect
(
client
);
UA_Client_delete
(
client
);
}
#define INIT_READ_VARIANT(ua_type, c_loc_name) \
UA_Variant_init(&c_loc_name##_variant);
#define INIT_WRITE_VARIANT(ua_type, ua_type_enum, c_loc_name) \
UA_Variant_setScalar(&c_loc_name##_variant, (ua_type*)c_loc_name, &UA_TYPES[ua_type_enum]);
int
__init_0
(
int
argc
,
char
**
argv
)
{
UA_StatusCode
retval
;
client
=
UA_Client_new
();
UA_ClientConfig_setDefault
(
UA_Client_getConfig
(
client
));
INIT_READ_VARIANT
(
UA_Int32
,
__ID0_0
)
INIT_READ_VARIANT
(
UA_Int32
,
__ID0_1
)
INIT_READ_VARIANT
(
UA_Int32
,
__ID0_2
)
INIT_READ_VARIANT
(
UA_Int32
,
__ID0_3
)
INIT_READ_VARIANT
(
UA_Int32
,
__ID0_4
)
INIT_READ_VARIANT
(
UA_Int32
,
__ID0_5
)
INIT_READ_VARIANT
(
UA_Int32
,
__ID0_6
)
INIT_READ_VARIANT
(
UA_Int32
,
__ID0_7
)
INIT_WRITE_VARIANT
(
UA_Int32
,
UA_TYPES_INT32
,
__QD0_0
)
INIT_WRITE_VARIANT
(
UA_Int32
,
UA_TYPES_INT32
,
__QD0_1
)
INIT_WRITE_VARIANT
(
UA_Int32
,
UA_TYPES_INT32
,
__QD0_2
)
INIT_WRITE_VARIANT
(
UA_Int32
,
UA_TYPES_INT32
,
__QD0_3
)
INIT_WRITE_VARIANT
(
UA_Int32
,
UA_TYPES_INT32
,
__QD0_4
)
INIT_WRITE_VARIANT
(
UA_Int32
,
UA_TYPES_INT32
,
__QD0_5
)
INIT_WRITE_VARIANT
(
UA_Int32
,
UA_TYPES_INT32
,
__QD0_6
)
INIT_WRITE_VARIANT
(
UA_Int32
,
UA_TYPES_INT32
,
__QD0_7
)
/* Connect to server */
retval
=
UA_Client_connect
(
client
,
"opc.tcp://192.168.0.73:4840"
);
if
(
retval
!=
UA_STATUSCODE_GOOD
)
{
UA_Client_delete
(
client
);
return
EXIT_FAILURE
;
}
}
#define READ_VALUE(ua_type, ua_type_enum, c_loc_name, ua_nodeid_type, ua_nsidx, ua_node_id) \
retval = UA_Client_readValueAttribute( \
client, ua_nodeid_type(ua_nsidx, ua_node_id), &c_loc_name##_variant); \
if(retval == UA_STATUSCODE_GOOD && UA_Variant_isScalar(&c_loc_name##_variant) && \
c_loc_name##_variant.type == &UA_TYPES[ua_type_enum]) { \
c_loc_name##_buf = *(ua_type*)c_loc_name##_variant.data; \
UA_Variant_clear(&c_loc_name##_variant);
/* Unalloc requiered on each read ! */
\
}
void
__retrieve_0
(
void
)
{
UA_StatusCode
retval
;
READ_VALUE
(
UA_Int32
,
UA_TYPES_INT32
,
__ID0_0
,
UA_NODEID_STRING
,
1
,
"i2c0.relay0"
)
READ_VALUE
(
UA_Int32
,
UA_TYPES_INT32
,
__ID0_1
,
UA_NODEID_STRING
,
1
,
"i2c0.relay1"
)
READ_VALUE
(
UA_Int32
,
UA_TYPES_INT32
,
__ID0_2
,
UA_NODEID_STRING
,
1
,
"i2c0.relay2"
)
READ_VALUE
(
UA_Int32
,
UA_TYPES_INT32
,
__ID0_3
,
UA_NODEID_STRING
,
1
,
"i2c0.relay3"
)
READ_VALUE
(
UA_Int32
,
UA_TYPES_INT32
,
__ID0_4
,
UA_NODEID_STRING
,
1
,
"i2c1.relay0"
)
READ_VALUE
(
UA_Int32
,
UA_TYPES_INT32
,
__ID0_5
,
UA_NODEID_STRING
,
1
,
"i2c1.relay1"
)
READ_VALUE
(
UA_Int32
,
UA_TYPES_INT32
,
__ID0_6
,
UA_NODEID_STRING
,
1
,
"i2c1.relay2"
)
READ_VALUE
(
UA_Int32
,
UA_TYPES_INT32
,
__ID0_7
,
UA_NODEID_STRING
,
1
,
"i2c1.relay3"
)
}
#define WRITE_VALUE(ua_type, c_loc_name, ua_nodeid_type, ua_nsidx, ua_node_id) \
UA_Client_writeValueAttribute( \
client, ua_nodeid_type(ua_nsidx, ua_node_id), &c_loc_name##_variant);
void
__publish_0
(
void
)
{
WRITE_VALUE
(
UA_Int32
,
__QD0_0
,
UA_NODEID_STRING
,
1
,
"i2c0.relay0"
)
WRITE_VALUE
(
UA_Int32
,
__QD0_1
,
UA_NODEID_STRING
,
1
,
"i2c0.relay1"
)
WRITE_VALUE
(
UA_Int32
,
__QD0_2
,
UA_NODEID_STRING
,
1
,
"i2c0.relay2"
)
WRITE_VALUE
(
UA_Int32
,
__QD0_3
,
UA_NODEID_STRING
,
1
,
"i2c0.relay3"
)
WRITE_VALUE
(
UA_Int32
,
__QD0_4
,
UA_NODEID_STRING
,
1
,
"i2c1.relay0"
)
WRITE_VALUE
(
UA_Int32
,
__QD0_5
,
UA_NODEID_STRING
,
1
,
"i2c1.relay1"
)
WRITE_VALUE
(
UA_Int32
,
__QD0_6
,
UA_NODEID_STRING
,
1
,
"i2c1.relay2"
)
WRITE_VALUE
(
UA_Int32
,
__QD0_7
,
UA_NODEID_STRING
,
1
,
"i2c1.relay3"
)
}
This diff is collapsed.
Click to expand it.
Beremiz/beremiz_tutorial_multiple_couplers_opc_ua/build/opcua_client__1.c
0 → 100644
View file @
59677959
/* code generated by beremiz OPC-UA extension */
#include <open62541/client_config_default.h>
#include <open62541/client_highlevel.h>
#include <open62541/plugin/log_stdout.h>
UA_Client
*
client
;
#define DECL_VAR(ua_type, C_type, c_loc_name) \
UA_Variant c_loc_name##_variant; \
C_type c_loc_name##_buf = 0; \
C_type *c_loc_name = &c_loc_name##_buf;
DECL_VAR
(
UA_Int32
,
uint32_t
,
__ID1_0
)
DECL_VAR
(
UA_Int32
,
uint32_t
,
__ID1_1
)
DECL_VAR
(
UA_Int32
,
uint32_t
,
__ID1_2
)
DECL_VAR
(
UA_Int32
,
uint32_t
,
__ID1_3
)
DECL_VAR
(
UA_Int32
,
uint32_t
,
__ID1_4
)
DECL_VAR
(
UA_Int32
,
uint32_t
,
__ID1_5
)
DECL_VAR
(
UA_Int32
,
uint32_t
,
__ID1_6
)
DECL_VAR
(
UA_Int32
,
uint32_t
,
__ID1_7
)
DECL_VAR
(
UA_Int32
,
uint32_t
,
__QD1_0
)
DECL_VAR
(
UA_Int32
,
uint32_t
,
__QD1_1
)
DECL_VAR
(
UA_Int32
,
uint32_t
,
__QD1_2
)
DECL_VAR
(
UA_Int32
,
uint32_t
,
__QD1_3
)
DECL_VAR
(
UA_Int32
,
uint32_t
,
__QD1_4
)
DECL_VAR
(
UA_Int32
,
uint32_t
,
__QD1_5
)
DECL_VAR
(
UA_Int32
,
uint32_t
,
__QD1_6
)
DECL_VAR
(
UA_Int32
,
uint32_t
,
__QD1_7
)
void
__cleanup_1
(
void
)
{
UA_Client_disconnect
(
client
);
UA_Client_delete
(
client
);
}
#define INIT_READ_VARIANT(ua_type, c_loc_name) \
UA_Variant_init(&c_loc_name##_variant);
#define INIT_WRITE_VARIANT(ua_type, ua_type_enum, c_loc_name) \
UA_Variant_setScalar(&c_loc_name##_variant, (ua_type*)c_loc_name, &UA_TYPES[ua_type_enum]);
int
__init_1
(
int
argc
,
char
**
argv
)
{
UA_StatusCode
retval
;
client
=
UA_Client_new
();
UA_ClientConfig_setDefault
(
UA_Client_getConfig
(
client
));
INIT_READ_VARIANT
(
UA_Int32
,
__ID1_0
)
INIT_READ_VARIANT
(
UA_Int32
,
__ID1_1
)
INIT_READ_VARIANT
(
UA_Int32
,
__ID1_2
)
INIT_READ_VARIANT
(
UA_Int32
,
__ID1_3
)
INIT_READ_VARIANT
(
UA_Int32
,
__ID1_4
)
INIT_READ_VARIANT
(
UA_Int32
,
__ID1_5
)
INIT_READ_VARIANT
(
UA_Int32
,
__ID1_6
)
INIT_READ_VARIANT
(
UA_Int32
,
__ID1_7
)
INIT_WRITE_VARIANT
(
UA_Int32
,
UA_TYPES_INT32
,
__QD1_0
)
INIT_WRITE_VARIANT
(
UA_Int32
,
UA_TYPES_INT32
,
__QD1_1
)
INIT_WRITE_VARIANT
(
UA_Int32
,
UA_TYPES_INT32
,
__QD1_2
)
INIT_WRITE_VARIANT
(
UA_Int32
,
UA_TYPES_INT32
,
__QD1_3
)
INIT_WRITE_VARIANT
(
UA_Int32
,
UA_TYPES_INT32
,
__QD1_4
)
INIT_WRITE_VARIANT
(
UA_Int32
,
UA_TYPES_INT32
,
__QD1_5
)
INIT_WRITE_VARIANT
(
UA_Int32
,
UA_TYPES_INT32
,
__QD1_6
)
INIT_WRITE_VARIANT
(
UA_Int32
,
UA_TYPES_INT32
,
__QD1_7
)
/* Connect to server */
retval
=
UA_Client_connect
(
client
,
"opc.tcp://192.168.0.70:4840"
);
if
(
retval
!=
UA_STATUSCODE_GOOD
)
{
UA_Client_delete
(
client
);
return
EXIT_FAILURE
;
}
}
#define READ_VALUE(ua_type, ua_type_enum, c_loc_name, ua_nodeid_type, ua_nsidx, ua_node_id) \
retval = UA_Client_readValueAttribute( \
client, ua_nodeid_type(ua_nsidx, ua_node_id), &c_loc_name##_variant); \
if(retval == UA_STATUSCODE_GOOD && UA_Variant_isScalar(&c_loc_name##_variant) && \
c_loc_name##_variant.type == &UA_TYPES[ua_type_enum]) { \
c_loc_name##_buf = *(ua_type*)c_loc_name##_variant.data; \
UA_Variant_clear(&c_loc_name##_variant);
/* Unalloc requiered on each read ! */
\
}
void
__retrieve_1
(
void
)
{
UA_StatusCode
retval
;
READ_VALUE
(
UA_Int32
,
UA_TYPES_INT32
,
__ID1_0
,
UA_NODEID_STRING
,
1
,
"i2c0.relay0"
)
READ_VALUE
(
UA_Int32
,
UA_TYPES_INT32
,
__ID1_1
,
UA_NODEID_STRING
,
1
,
"i2c0.relay1"
)
READ_VALUE
(
UA_Int32
,
UA_TYPES_INT32
,
__ID1_2
,
UA_NODEID_STRING
,
1
,
"i2c0.relay2"
)
READ_VALUE
(
UA_Int32
,
UA_TYPES_INT32
,
__ID1_3
,
UA_NODEID_STRING
,
1
,
"i2c0.relay3"
)
READ_VALUE
(
UA_Int32
,
UA_TYPES_INT32
,
__ID1_4
,
UA_NODEID_STRING
,
1
,
"i2c1.relay0"
)
READ_VALUE
(
UA_Int32
,
UA_TYPES_INT32
,
__ID1_5
,
UA_NODEID_STRING
,
1
,
"i2c1.relay1"
)
READ_VALUE
(
UA_Int32
,
UA_TYPES_INT32
,
__ID1_6
,
UA_NODEID_STRING
,
1
,
"i2c1.relay2"
)
READ_VALUE
(
UA_Int32
,
UA_TYPES_INT32
,
__ID1_7
,
UA_NODEID_STRING
,
1
,
"i2c1.relay3"
)
}
#define WRITE_VALUE(ua_type, c_loc_name, ua_nodeid_type, ua_nsidx, ua_node_id) \
UA_Client_writeValueAttribute( \
client, ua_nodeid_type(ua_nsidx, ua_node_id), &c_loc_name##_variant);
void
__publish_1
(
void
)
{
WRITE_VALUE
(
UA_Int32
,
__QD1_0
,
UA_NODEID_STRING
,
1
,
"i2c0.relay0"
)
WRITE_VALUE
(
UA_Int32
,
__QD1_1
,
UA_NODEID_STRING
,
1
,
"i2c0.relay1"
)
WRITE_VALUE
(
UA_Int32
,
__QD1_2
,
UA_NODEID_STRING
,
1
,
"i2c0.relay2"
)
WRITE_VALUE
(
UA_Int32
,
__QD1_3
,
UA_NODEID_STRING
,
1
,
"i2c0.relay3"
)
WRITE_VALUE
(
UA_Int32
,
__QD1_4
,
UA_NODEID_STRING
,
1
,
"i2c1.relay0"
)
WRITE_VALUE
(
UA_Int32
,
__QD1_5
,
UA_NODEID_STRING
,
1
,
"i2c1.relay1"
)
WRITE_VALUE
(
UA_Int32
,
__QD1_6
,
UA_NODEID_STRING
,
1
,
"i2c1.relay2"
)
WRITE_VALUE
(
UA_Int32
,
__QD1_7
,
UA_NODEID_STRING
,
1
,
"i2c1.relay3"
)
}
This diff is collapsed.
Click to expand it.
Beremiz/beremiz_tutorial_multiple_couplers_opc_ua/build/plc.st
0 → 100644
View file @
59677959
TYPE
LOGLEVEL
:
(
CRITICAL
,
WARNING
,
INFO
,
DEBUG
)
:=
INFO
;
END_TYPE
FUNCTION_BLOCK
LOGGER
VAR_INPUT
TRIG
:
BOOL
;
MSG
:
STRING
;
LEVEL
:
LOGLEVEL
:=
INFO
;
END_VAR
VAR
TRIG0
:
BOOL
;
END_VAR
IF
TRIG
AND
NOT
TRIG0
THEN
{{
LogMessage
(
GetFbVar
(
LEVEL
)
,
(
char
*
)
GetFbVar
(
MSG
,
.
body
)
,
GetFbVar
(
MSG
,
.
len
));
}}
END_IF
;
TRIG0:
=
TRIG
;
END_FUNCTION_BLOCK
FUNCTION_BLOCK
python_eval
VAR_INPUT
TRIG
:
BOOL
;
CODE
:
STRING
;
END_VAR
VAR_OUTPUT
ACK
:
BOOL
;
RESULT
:
STRING
;
END_VAR
VAR
STATE
:
DWORD
;
BUFFER
:
STRING
;
PREBUFFER
:
STRING
;
TRIGM1
:
BOOL
;
TRIGGED
:
BOOL
;
END_VAR
{
extern
void
__
PythonEvalFB
(
int
,
PYTHON_EVAL
*
);
__
PythonEvalFB
(
0
,
data__
);}
END_FUNCTION_BLOCK
FUNCTION_BLOCK
python_poll
VAR_INPUT
TRIG
:
BOOL
;
CODE
:
STRING
;
END_VAR
VAR_OUTPUT
ACK
:
BOOL
;
RESULT
:
STRING
;
END_VAR
VAR
STATE
:
DWORD
;
BUFFER
:
STRING
;
PREBUFFER
:
STRING
;
TRIGM1
:
BOOL
;
TRIGGED
:
BOOL
;
END_VAR
{
extern
void
__
PythonEvalFB
(
int
,
PYTHON_EVAL
*
);
__
PythonEvalFB
(
1
,
(
PYTHON_EVAL
*
)(
void
*
)
data__
);}
END_FUNCTION_BLOCK
FUNCTION_BLOCK
python_gear
VAR_INPUT
N
:
UINT
;
TRIG
:
BOOL
;
CODE
:
STRING
;
END_VAR
VAR_OUTPUT
ACK
:
BOOL
;
RESULT
:
STRING
;
END_VAR
VAR
py_eval
:
python_eval
;
COUNTER
:
UINT
;
_
TMP_ADD10_OUT
:
UINT
;
_
TMP_EQ13_OUT
:
BOOL
;
_
TMP_SEL15_OUT
:
UINT
;
_
TMP_AND7_OUT
:
BOOL
;
END_VAR
_
TMP_ADD10_OUT
:=
ADD
(
COUNTER
,
1
);
_
TMP_EQ13_OUT
:=
EQ
(
N
,
_
TMP_ADD10_OUT
);
_
TMP_SEL15_OUT
:=
SEL
(
_
TMP_EQ13_OUT
,
_
TMP_ADD10_OUT
,
0
);
COUNTER
:=
_
TMP_SEL15_OUT
;
_
TMP_AND7_OUT
:=
AND
(
_
TMP_EQ13_OUT
,
TRIG
);
py_eval
(
TRIG
:=
_
TMP_AND7_OUT
,
CODE
:=
CODE
);
ACK
:=
py_eval
.
ACK
;
RESULT
:=
py_eval
.
RESULT
;
END_FUNCTION_BLOCK
FUNCTION_BLOCK
CounterST
VAR_INPUT
Reset
:
BOOL
;
END_VAR
VAR_OUTPUT
Out1
:
INT
;
Out0
:
INT
;
END_VAR
VAR
Cnt1
:
INT
;
Cnt0
:
INT
;
END_VAR
VAR_EXTERNAL
ResetCounterValue
:
INT
;
Relay0
:
DINT
;
Relay1
:
DINT
;
Relay2
:
DINT
;
Relay3
:
DINT
;
Relay4
:
DINT
;
Relay5
:
DINT
;
Relay6
:
DINT
;
Relay7
:
DINT
;
END_VAR
Cnt1
:=
Cnt1
+
1
;
IF
Cnt1
=
100
THEN
Relay0
:=
Relay0
+
1
;
Cnt1
:=
0
;
Relay7
:=
Relay0
;
END_IF
;
Out1
:=
Cnt1
;
Out0
:=
Cnt0
;
END_FUNCTION_BLOCK
PROGRAM
plc_prg
VAR_INPUT
Reset
:
BOOL
;
END_VAR
VAR_OUTPUT
Cnt0
:
INT
;
Cnt1
:
INT
;
END_VAR
VAR
CounterST0
:
CounterST
;
END_VAR
CounterST0
(
Reset
:=
Reset
);
Cnt1
:=
CounterST0
.
Out1
;
Cnt0
:=
CounterST0
.
Out0
;
END_PROGRAM
CONFIGURATION
config
VAR_GLOBAL
ResetCounterValue
:
INT
:=
0
;
Relay0
AT
%
QD1
.
0
:
DINT
:=
0
;
Relay1
AT
%
QD1
.
1
:
DINT
:=
0
;
Relay2
AT
%
QD1
.
2
:
DINT
:=
0
;
Relay3
AT
%
QD1
.
3
:
DINT
:=
0
;
Relay4
AT
%
QD0
.
0
:
DINT
:=
0
;
Relay5
AT
%
QD0
.
1
:
DINT
:=
0
;
Relay6
AT
%
QD0
.
2
:
DINT
:=
0
;
Relay7
AT
%
QD0
.
3
:
DINT
:=
0
;
END_VAR
RESOURCE
resource1
ON
PLC
TASK
task0
(
INTERVAL
:=
T
#20ms
,
PRIORITY
:=
0
);
PROGRAM
instance0
WITH
task0
:
plc_prg
;
END_RESOURCE
END_CONFIGURATION
This diff is collapsed.
Click to expand it.
Beremiz/beremiz_tutorial_multiple_couplers_opc_ua/build/plc_debugger.c
0 → 100644
View file @
59677959
/*
* DEBUGGER code
*
* On "publish", when buffer is free, debugger stores arbitrary variables
* content into, and mark this buffer as filled
*
*
* Buffer content is read asynchronously, (from non real time part),
* and then buffer marked free again.
*
*
* */
#ifdef TARGET_DEBUG_AND_RETAIN_DISABLE
void
__init_debug
(
void
){}
void
__cleanup_debug
(
void
){}
void
__retrieve_debug
(
void
){}
void
__publish_debug
(
void
){}
#else
#include "iec_types_all.h"
#include "POUS.h"
/*for memcpy*/
#include <string.h>
#include <stdio.h>
#ifndef TARGET_ONLINE_DEBUG_DISABLE
#define BUFFER_SIZE 84
/* Atomically accessed variable for buffer state */
#define BUFFER_FREE 0
#define BUFFER_BUSY 1
static
long
buffer_state
=
BUFFER_FREE
;
/* The buffer itself */
char
debug_buffer
[
BUFFER_SIZE
];
/* Buffer's cursor*/
static
char
*
buffer_cursor
=
debug_buffer
;
#endif
static
unsigned
int
retain_offset
=
0
;
/***
* Declare programs
**/
extern
PLC_PRG
RESOURCE1__INSTANCE0
;
/***
* Declare global variables from resources and conf
**/
extern
__IEC_INT_t
CONFIG__RESETCOUNTERVALUE
;
extern
__IEC_DINT_p
CONFIG__RELAY0
;
extern
__IEC_DINT_p
CONFIG__RELAY1
;
extern
__IEC_DINT_p
CONFIG__RELAY2
;
extern
__IEC_DINT_p
CONFIG__RELAY3
;
extern
__IEC_DINT_p
CONFIG__RELAY4
;
extern
__IEC_DINT_p
CONFIG__RELAY5
;
extern
__IEC_DINT_p
CONFIG__RELAY6
;
extern
__IEC_DINT_p
CONFIG__RELAY7
;
extern
PLC_PRG
RESOURCE1__INSTANCE0
;
typedef
const
struct
{
void
*
ptr
;
__IEC_types_enum
type
;
}
dbgvardsc_t
;
static
dbgvardsc_t
dbgvardsc
[]
=
{
{
&
(
CONFIG__RESETCOUNTERVALUE
),
INT_ENUM
},
{
&
(
CONFIG__RELAY0
),
DINT_O_ENUM
},
{
&
(
CONFIG__RELAY1
),
DINT_O_ENUM
},
{
&
(
CONFIG__RELAY2
),
DINT_O_ENUM
},
{
&
(
CONFIG__RELAY3
),
DINT_O_ENUM
},
{
&
(
CONFIG__RELAY4
),
DINT_O_ENUM
},
{
&
(
CONFIG__RELAY5
),
DINT_O_ENUM
},
{
&
(
CONFIG__RELAY6
),
DINT_O_ENUM
},
{
&
(
CONFIG__RELAY7
),
DINT_O_ENUM
},
{
&
(
RESOURCE1__INSTANCE0
.
RESET
),
BOOL_ENUM
},
{
&
(
RESOURCE1__INSTANCE0
.
CNT0
),
INT_ENUM
},
{
&
(
RESOURCE1__INSTANCE0
.
CNT1
),
INT_ENUM
},
{
&
(
RESOURCE1__INSTANCE0
.
COUNTERST0
.
EN
),
BOOL_ENUM
},
{
&
(
RESOURCE1__INSTANCE0
.
COUNTERST0
.
ENO
),
BOOL_ENUM
},
{
&
(
RESOURCE1__INSTANCE0
.
COUNTERST0
.
RESET
),
BOOL_ENUM
},
{
&
(
RESOURCE1__INSTANCE0
.
COUNTERST0
.
OUT1
),
INT_ENUM
},
{
&
(
RESOURCE1__INSTANCE0
.
COUNTERST0
.
OUT0
),
INT_ENUM
},
{
&
(
RESOURCE1__INSTANCE0
.
COUNTERST0
.
CNT1
),
INT_ENUM
},
{
&
(
RESOURCE1__INSTANCE0
.
COUNTERST0
.
CNT0
),
INT_ENUM
},
{
&
(
RESOURCE1__INSTANCE0
.
COUNTERST0
.
RESETCOUNTERVALUE
),
INT_P_ENUM
},
{
&
(
RESOURCE1__INSTANCE0
.
COUNTERST0
.
RELAY0
),
DINT_P_ENUM
},
{
&
(
RESOURCE1__INSTANCE0
.
COUNTERST0
.
RELAY1
),
DINT_P_ENUM
},
{
&
(
RESOURCE1__INSTANCE0
.
COUNTERST0
.
RELAY2
),
DINT_P_ENUM
},
{
&
(
RESOURCE1__INSTANCE0
.
COUNTERST0
.
RELAY3
),
DINT_P_ENUM
},
{
&
(
RESOURCE1__INSTANCE0
.
COUNTERST0
.
RELAY4
),
DINT_P_ENUM
},
{
&
(
RESOURCE1__INSTANCE0
.
COUNTERST0
.
RELAY5
),
DINT_P_ENUM
},
{
&
(
RESOURCE1__INSTANCE0
.
COUNTERST0
.
RELAY6
),
DINT_P_ENUM
},
{
&
(
RESOURCE1__INSTANCE0
.
COUNTERST0
.
RELAY7
),
DINT_P_ENUM
}
};
typedef
void
(
*
__for_each_variable_do_fp
)(
dbgvardsc_t
*
);
void
__for_each_variable_do
(
__for_each_variable_do_fp
fp
)
{
unsigned
int
i
;
for
(
i
=
0
;
i
<
sizeof
(
dbgvardsc
)
/
sizeof
(
dbgvardsc_t
);
i
++
){
dbgvardsc_t
*
dsc
=
&
dbgvardsc
[
i
];
if
(
dsc
->
type
!=
UNKNOWN_ENUM
)
(
*
fp
)(
dsc
);
}
}
#define __Unpack_desc_type dbgvardsc_t
#define __Unpack_case_t(TYPENAME) \
case TYPENAME##_ENUM :\
*flags = ((__IEC_##TYPENAME##_t *)varp)->flags;\
forced_value_p = *real_value_p = &((__IEC_##TYPENAME##_t *)varp)->value;\
break;
#define __Unpack_case_p(TYPENAME)\
case TYPENAME##_O_ENUM :\
*flags = __IEC_OUTPUT_FLAG;\
case TYPENAME##_P_ENUM :\
*flags |= ((__IEC_##TYPENAME##_p *)varp)->flags;\
*real_value_p = ((__IEC_##TYPENAME##_p *)varp)->value;\
forced_value_p = &((__IEC_##TYPENAME##_p *)varp)->fvalue;\
break;
#define __Is_a_string(dsc) (dsc->type == STRING_ENUM) ||\
(dsc->type == STRING_P_ENUM) ||\
(dsc->type == STRING_O_ENUM)
static
void
*
UnpackVar
(
__Unpack_desc_type
*
dsc
,
void
**
real_value_p
,
char
*
flags
)
{
void
*
varp
=
dsc
->
ptr
;
void
*
forced_value_p
=
NULL
;
*
flags
=
0
;
/* find data to copy*/
switch
(
dsc
->
type
){
__ANY
(
__Unpack_case_t
)
__ANY
(
__Unpack_case_p
)
default:
break
;
}
if
(
*
flags
&
__IEC_FORCE_FLAG
)
return
forced_value_p
;
return
*
real_value_p
;
}
void
Remind
(
unsigned
int
offset
,
unsigned
int
count
,
void
*
p
);
void
RemindIterator
(
dbgvardsc_t
*
dsc
)
{
void
*
real_value_p
=
NULL
;
char
flags
=
0
;
UnpackVar
(
dsc
,
&
real_value_p
,
&
flags
);
if
(
flags
&
__IEC_RETAIN_FLAG
){
USINT
size
=
__get_type_enum_size
(
dsc
->
type
);
/* compute next cursor positon*/
unsigned
int
next_retain_offset
=
retain_offset
+
size
;
/* if buffer not full */
Remind
(
retain_offset
,
size
,
real_value_p
);
/* increment cursor according size*/
retain_offset
=
next_retain_offset
;
}
}
extern
int
CheckRetainBuffer
(
void
);
extern
void
InitRetain
(
void
);
void
__init_debug
(
void
)
{
/* init local static vars */
#ifndef TARGET_ONLINE_DEBUG_DISABLE
buffer_cursor
=
debug_buffer
;
buffer_state
=
BUFFER_FREE
;
#endif
retain_offset
=
0
;
InitRetain
();
/* Iterate over all variables to fill debug buffer */
if
(
CheckRetainBuffer
()){
__for_each_variable_do
(
RemindIterator
);
}
else
{
char
mstr
[]
=
"RETAIN memory invalid - defaults used"
;
LogMessage
(
LOG_WARNING
,
mstr
,
sizeof
(
mstr
));
}
retain_offset
=
0
;
}
extern
void
InitiateDebugTransfer
(
void
);
extern
void
CleanupRetain
(
void
);
extern
unsigned
long
__tick
;
void
__cleanup_debug
(
void
)
{
#ifndef TARGET_ONLINE_DEBUG_DISABLE
buffer_cursor
=
debug_buffer
;
InitiateDebugTransfer
();
#endif
CleanupRetain
();
}
void
__retrieve_debug
(
void
)
{
}
void
Retain
(
unsigned
int
offset
,
unsigned
int
count
,
void
*
p
);
static
inline
void
BufferIterator
(
dbgvardsc_t
*
dsc
,
int
do_debug
)
{
void
*
real_value_p
=
NULL
;
void
*
visible_value_p
=
NULL
;
char
flags
=
0
;
visible_value_p
=
UnpackVar
(
dsc
,
&
real_value_p
,
&
flags
);
if
(
flags
&
(
__IEC_DEBUG_FLAG
|
__IEC_RETAIN_FLAG
)){
USINT
size
=
__get_type_enum_size
(
dsc
->
type
);
#ifndef TARGET_ONLINE_DEBUG_DISABLE
if
(
flags
&
__IEC_DEBUG_FLAG
){
/* copy visible variable to buffer */
;
if
(
do_debug
){
/* compute next cursor positon.
No need to check overflow, as BUFFER_SIZE
is computed large enough */
if
(
__Is_a_string
(
dsc
)){
/* optimization for strings */
size
=
((
STRING
*
)
visible_value_p
)
->
len
+
1
;
}
char
*
next_cursor
=
buffer_cursor
+
size
;
/* copy data to the buffer */
memcpy
(
buffer_cursor
,
visible_value_p
,
size
);
/* increment cursor according size*/
buffer_cursor
=
next_cursor
;
}
/* re-force real value of outputs (M and Q)*/
if
((
flags
&
__IEC_FORCE_FLAG
)
&&
(
flags
&
__IEC_OUTPUT_FLAG
)){
memcpy
(
real_value_p
,
visible_value_p
,
size
);
}
}
#endif
if
(
flags
&
__IEC_RETAIN_FLAG
){
/* compute next cursor positon*/
unsigned
int
next_retain_offset
=
retain_offset
+
size
;
/* if buffer not full */
Retain
(
retain_offset
,
size
,
real_value_p
);
/* increment cursor according size*/
retain_offset
=
next_retain_offset
;
}
}
}
void
DebugIterator
(
dbgvardsc_t
*
dsc
){
BufferIterator
(
dsc
,
1
);
}
void
RetainIterator
(
dbgvardsc_t
*
dsc
){
BufferIterator
(
dsc
,
0
);
}
unsigned
int
retain_size
=
0
;
/* GetRetainSizeIterator */
void
GetRetainSizeIterator
(
dbgvardsc_t
*
dsc
)
{
void
*
real_value_p
=
NULL
;
char
flags
=
0
;
UnpackVar
(
dsc
,
&
real_value_p
,
&
flags
);
if
(
flags
&
__IEC_RETAIN_FLAG
){
USINT
size
=
__get_type_enum_size
(
dsc
->
type
);
/* Calc retain buffer size */
retain_size
+=
size
;
}
}
/* Return size of all retain variables */
unsigned
int
GetRetainSize
(
void
)
{
__for_each_variable_do
(
GetRetainSizeIterator
);
return
retain_size
;
}
extern
void
PLC_GetTime
(
IEC_TIME
*
);
extern
int
TryEnterDebugSection
(
void
);
extern
long
AtomicCompareExchange
(
long
*
,
long
,
long
);
extern
long
long
AtomicCompareExchange64
(
long
long
*
,
long
long
,
long
long
);
extern
void
LeaveDebugSection
(
void
);
extern
void
ValidateRetainBuffer
(
void
);
extern
void
InValidateRetainBuffer
(
void
);
void
__publish_debug
(
void
)
{
retain_offset
=
0
;
InValidateRetainBuffer
();
#ifndef TARGET_ONLINE_DEBUG_DISABLE
/* Check there is no running debugger re-configuration */
if
(
TryEnterDebugSection
()){
/* Lock buffer */
long
latest_state
=
AtomicCompareExchange
(
&
buffer_state
,
BUFFER_FREE
,
BUFFER_BUSY
);
/* If buffer was free */
if
(
latest_state
==
BUFFER_FREE
)
{
/* Reset buffer cursor */
buffer_cursor
=
debug_buffer
;
/* Iterate over all variables to fill debug buffer */
__for_each_variable_do
(
DebugIterator
);
/* Leave debug section,
* Trigger asynchronous transmission
* (returns immediately) */
InitiateDebugTransfer
();
/* size */
}
else
{
/* when not debugging, do only retain */
__for_each_variable_do
(
RetainIterator
);
}
LeaveDebugSection
();
}
else
#endif
{
/* when not debugging, do only retain */
__for_each_variable_do
(
RetainIterator
);
}
ValidateRetainBuffer
();
}
#ifndef TARGET_ONLINE_DEBUG_DISABLE
#define __RegisterDebugVariable_case_t(TYPENAME) \
case TYPENAME##_ENUM :\
((__IEC_##TYPENAME##_t *)varp)->flags |= flags;\
if(force)\
((__IEC_##TYPENAME##_t *)varp)->value = *((TYPENAME *)force);\
break;
#define __RegisterDebugVariable_case_p(TYPENAME)\
case TYPENAME##_P_ENUM :\
((__IEC_##TYPENAME##_p *)varp)->flags |= flags;\
if(force)\
((__IEC_##TYPENAME##_p *)varp)->fvalue = *((TYPENAME *)force);\
break;\
case TYPENAME##_O_ENUM :\
((__IEC_##TYPENAME##_p *)varp)->flags |= flags;\
if(force){\
((__IEC_##TYPENAME##_p *)varp)->fvalue = *((TYPENAME *)force);\
*(((__IEC_##TYPENAME##_p *)varp)->value) = *((TYPENAME *)force);\
}\
break;
void
RegisterDebugVariable
(
unsigned
int
idx
,
void
*
force
)
{
if
(
idx
<
sizeof
(
dbgvardsc
)
/
sizeof
(
dbgvardsc_t
)){
unsigned
char
flags
=
force
?
__IEC_DEBUG_FLAG
|
__IEC_FORCE_FLAG
:
__IEC_DEBUG_FLAG
;
dbgvardsc_t
*
dsc
=
&
dbgvardsc
[
idx
];
void
*
varp
=
dsc
->
ptr
;
switch
(
dsc
->
type
){
__ANY
(
__RegisterDebugVariable_case_t
)
__ANY
(
__RegisterDebugVariable_case_p
)
default:
break
;
}
}
}
#define __ResetDebugVariablesIterator_case_t(TYPENAME) \
case TYPENAME##_ENUM :\
((__IEC_##TYPENAME##_t *)varp)->flags &= ~(__IEC_DEBUG_FLAG|__IEC_FORCE_FLAG);\
break;
#define __ResetDebugVariablesIterator_case_p(TYPENAME)\
case TYPENAME##_P_ENUM :\
case TYPENAME##_O_ENUM :\
((__IEC_##TYPENAME##_p *)varp)->flags &= ~(__IEC_DEBUG_FLAG|__IEC_FORCE_FLAG);\
break;
void
ResetDebugVariablesIterator
(
dbgvardsc_t
*
dsc
)
{
/* force debug flag to 0*/
void
*
varp
=
dsc
->
ptr
;
switch
(
dsc
->
type
){
__ANY
(
__ResetDebugVariablesIterator_case_t
)
__ANY
(
__ResetDebugVariablesIterator_case_p
)
default:
break
;
}
}
void
ResetDebugVariables
(
void
)
{
__for_each_variable_do
(
ResetDebugVariablesIterator
);
}
void
FreeDebugData
(
void
)
{
/* atomically mark buffer as free */
AtomicCompareExchange
(
&
buffer_state
,
BUFFER_BUSY
,
BUFFER_FREE
);
}
int
WaitDebugData
(
unsigned
long
*
tick
);
/* Wait until debug data ready and return pointer to it */
int
GetDebugData
(
unsigned
long
*
tick
,
unsigned
long
*
size
,
void
**
buffer
){
int
wait_error
=
WaitDebugData
(
tick
);
if
(
!
wait_error
){
*
size
=
buffer_cursor
-
debug_buffer
;
*
buffer
=
debug_buffer
;
}
return
wait_error
;
}
#endif
#endif
This diff is collapsed.
Click to expand it.
Beremiz/beremiz_tutorial_multiple_couplers_opc_ua/build/plc_main.c
0 → 100644
View file @
59677959
/**
* Head of code common to all C targets
**/
#include "beremiz.h"
#include <string.h>
/*
* Prototypes of functions provided by generated C softPLC
**/
void
config_run__
(
unsigned
long
tick
);
void
config_init__
(
void
);
/*
* Prototypes of functions provided by generated target C code
* */
long
long
AtomicCompareExchange64
(
long
long
*
,
long
long
,
long
long
);
void
__init_debug
(
void
);
void
__cleanup_debug
(
void
);
/*void __retrieve_debug(void);*/
void
__publish_debug
(
void
);
/*
* Variables used by generated C softPLC and plugins
**/
IEC_TIME
__CURRENT_TIME
;
IEC_BOOL
__DEBUG
=
0
;
unsigned
long
__tick
=
0
;
char
*
PLC_ID
=
NULL
;
/*
* Variable generated by C softPLC and plugins
**/
extern
unsigned
long
greatest_tick_count__
;
/* Help to quit cleanly when init fail at a certain level */
static
int
init_level
=
0
;
/*
* Prototypes of functions exported by plugins
**/
int
__init_py_ext
(
int
argc
,
char
**
argv
);
void
__cleanup_py_ext
(
void
);
void
__retrieve_py_ext
(
void
);
void
__publish_py_ext
(
void
);
int
__init_0
(
int
argc
,
char
**
argv
);
void
__cleanup_0
(
void
);
void
__retrieve_0
(
void
);
void
__publish_0
(
void
);
int
__init_1
(
int
argc
,
char
**
argv
);
void
__cleanup_1
(
void
);
void
__retrieve_1
(
void
);
void
__publish_1
(
void
);
/*
* Retrieve input variables, run PLC and publish output variables
**/
void
__run
(
void
)
{
__tick
++
;
if
(
greatest_tick_count__
)
__tick
%=
greatest_tick_count__
;
__retrieve_py_ext
();
__retrieve_0
();
__retrieve_1
();
/*__retrieve_debug();*/
config_run__
(
__tick
);
__publish_debug
();
__publish_1
();
__publish_0
();
__publish_py_ext
();
}
/*
* Initialize variables according to PLC's default values,
* and then init plugins with that values
**/
int
__init
(
int
argc
,
char
**
argv
)
{
int
res
=
0
;
init_level
=
0
;
/* Effective tick time with 1ms default value */
if
(
!
common_ticktime__
)
common_ticktime__
=
1000000
;
config_init__
();
__init_debug
();
init_level
=
1
;
if
((
res
=
__init_py_ext
(
argc
,
argv
))){
return
res
;}
init_level
=
2
;
if
((
res
=
__init_0
(
argc
,
argv
))){
return
res
;}
init_level
=
3
;
if
((
res
=
__init_1
(
argc
,
argv
))){
return
res
;}
return
res
;
}
/*
* Calls plugin cleanup proc.
**/
void
__cleanup
(
void
)
{
if
(
init_level
>=
3
)
__cleanup_1
();
if
(
init_level
>=
2
)
__cleanup_0
();
if
(
init_level
>=
1
)
__cleanup_py_ext
();
__cleanup_debug
();
}
void
PLC_GetTime
(
IEC_TIME
*
CURRENT_TIME
);
void
PLC_SetTimer
(
unsigned
long
long
next
,
unsigned
long
long
period
);
/**
* Linux specific code
**/
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <signal.h>
#include <stdlib.h>
#include <pthread.h>
#include <locale.h>
#include <semaphore.h>
static
sem_t
Run_PLC
;
long
AtomicCompareExchange
(
long
*
atomicvar
,
long
compared
,
long
exchange
)
{
return
__sync_val_compare_and_swap
(
atomicvar
,
compared
,
exchange
);
}
long
long
AtomicCompareExchange64
(
long
long
*
atomicvar
,
long
long
compared
,
long
long
exchange
)
{
return
__sync_val_compare_and_swap
(
atomicvar
,
compared
,
exchange
);
}
void
PLC_GetTime
(
IEC_TIME
*
CURRENT_TIME
)
{
struct
timespec
tmp
;
clock_gettime
(
CLOCK_REALTIME
,
&
tmp
);
CURRENT_TIME
->
tv_sec
=
tmp
.
tv_sec
;
CURRENT_TIME
->
tv_nsec
=
tmp
.
tv_nsec
;
}
void
PLC_timer_notify
(
sigval_t
val
)
{
PLC_GetTime
(
&
__CURRENT_TIME
);
sem_post
(
&
Run_PLC
);
}
timer_t
PLC_timer
;
void
PLC_SetTimer
(
unsigned
long
long
next
,
unsigned
long
long
period
)
{
struct
itimerspec
timerValues
;
/*
printf("SetTimer(%lld,%lld)\n",next, period);
*/
memset
(
&
timerValues
,
0
,
sizeof
(
struct
itimerspec
));
{
#ifdef __lldiv_t_defined
lldiv_t
nxt_div
=
lldiv
(
next
,
1000000000
);
lldiv_t
period_div
=
lldiv
(
period
,
1000000000
);
timerValues
.
it_value
.
tv_sec
=
nxt_div
.
quot
;
timerValues
.
it_value
.
tv_nsec
=
nxt_div
.
rem
;
timerValues
.
it_interval
.
tv_sec
=
period_div
.
quot
;
timerValues
.
it_interval
.
tv_nsec
=
period_div
.
rem
;
#else
timerValues
.
it_value
.
tv_sec
=
next
/
1000000000
;
timerValues
.
it_value
.
tv_nsec
=
next
%
1000000000
;
timerValues
.
it_interval
.
tv_sec
=
period
/
1000000000
;
timerValues
.
it_interval
.
tv_nsec
=
period
%
1000000000
;
#endif
}
timer_settime
(
PLC_timer
,
0
,
&
timerValues
,
NULL
);
}
//
void
catch_signal
(
int
sig
)
{
// signal(SIGTERM, catch_signal);
signal
(
SIGINT
,
catch_signal
);
printf
(
"Got Signal %d
\n
"
,
sig
);
exit
(
0
);
}
static
unsigned
long
__debug_tick
;
pthread_t
PLC_thread
;
static
pthread_mutex_t
python_wait_mutex
=
PTHREAD_MUTEX_INITIALIZER
;
static
pthread_mutex_t
python_mutex
=
PTHREAD_MUTEX_INITIALIZER
;
static
pthread_mutex_t
debug_wait_mutex
=
PTHREAD_MUTEX_INITIALIZER
;
static
pthread_mutex_t
debug_mutex
=
PTHREAD_MUTEX_INITIALIZER
;
int
PLC_shutdown
=
0
;
int
ForceSaveRetainReq
(
void
)
{
return
PLC_shutdown
;
}
void
PLC_thread_proc
(
void
*
arg
)
{
while
(
!
PLC_shutdown
)
{
sem_wait
(
&
Run_PLC
);
__run
();
}
pthread_exit
(
0
);
}
#define maxval(a,b) ((a>b)?a:b)
int
startPLC
(
int
argc
,
char
**
argv
)
{
struct
sigevent
sigev
;
setlocale
(
LC_NUMERIC
,
"C"
);
PLC_shutdown
=
0
;
sem_init
(
&
Run_PLC
,
0
,
0
);
pthread_create
(
&
PLC_thread
,
NULL
,
(
void
*
)
&
PLC_thread_proc
,
NULL
);
memset
(
&
sigev
,
0
,
sizeof
(
struct
sigevent
));
sigev
.
sigev_value
.
sival_int
=
0
;
sigev
.
sigev_notify
=
SIGEV_THREAD
;
sigev
.
sigev_notify_attributes
=
NULL
;
sigev
.
sigev_notify_function
=
PLC_timer_notify
;
pthread_mutex_init
(
&
debug_wait_mutex
,
NULL
);
pthread_mutex_init
(
&
debug_mutex
,
NULL
);
pthread_mutex_init
(
&
python_wait_mutex
,
NULL
);
pthread_mutex_init
(
&
python_mutex
,
NULL
);
pthread_mutex_lock
(
&
debug_wait_mutex
);
pthread_mutex_lock
(
&
python_wait_mutex
);
timer_create
(
CLOCK_MONOTONIC
,
&
sigev
,
&
PLC_timer
);
if
(
__init
(
argc
,
argv
)
==
0
){
PLC_SetTimer
(
common_ticktime__
,
common_ticktime__
);
/* install signal handler for manual break */
signal
(
SIGINT
,
catch_signal
);
}
else
{
return
1
;
}
return
0
;
}
int
TryEnterDebugSection
(
void
)
{
if
(
pthread_mutex_trylock
(
&
debug_mutex
)
==
0
){
/* Only enter if debug active */
if
(
__DEBUG
){
return
1
;
}
pthread_mutex_unlock
(
&
debug_mutex
);
}
return
0
;
}
void
LeaveDebugSection
(
void
)
{
pthread_mutex_unlock
(
&
debug_mutex
);
}
int
stopPLC
()
{
/* Stop the PLC */
PLC_shutdown
=
1
;
sem_post
(
&
Run_PLC
);
PLC_SetTimer
(
0
,
0
);
pthread_join
(
PLC_thread
,
NULL
);
sem_destroy
(
&
Run_PLC
);
timer_delete
(
PLC_timer
);
__cleanup
();
pthread_mutex_destroy
(
&
debug_wait_mutex
);
pthread_mutex_destroy
(
&
debug_mutex
);
pthread_mutex_destroy
(
&
python_wait_mutex
);
pthread_mutex_destroy
(
&
python_mutex
);
return
0
;
}
extern
unsigned
long
__tick
;
int
WaitDebugData
(
unsigned
long
*
tick
)
{
int
res
;
if
(
PLC_shutdown
)
return
1
;
/* Wait signal from PLC thread */
res
=
pthread_mutex_lock
(
&
debug_wait_mutex
);
*
tick
=
__debug_tick
;
return
res
;
}
/* Called by PLC thread when debug_publish finished
* This is supposed to unlock debugger thread in WaitDebugData*/
void
InitiateDebugTransfer
()
{
/* remember tick */
__debug_tick
=
__tick
;
/* signal debugger thread it can read data */
pthread_mutex_unlock
(
&
debug_wait_mutex
);
}
int
suspendDebug
(
int
disable
)
{
/* Prevent PLC to enter debug code */
pthread_mutex_lock
(
&
debug_mutex
);
/*__DEBUG is protected by this mutex */
__DEBUG
=
!
disable
;
if
(
disable
)
pthread_mutex_unlock
(
&
debug_mutex
);
return
0
;
}
void
resumeDebug
(
void
)
{
__DEBUG
=
1
;
/* Let PLC enter debug code */
pthread_mutex_unlock
(
&
debug_mutex
);
}
/* from plc_python.c */
int
WaitPythonCommands
(
void
)
{
/* Wait signal from PLC thread */
return
pthread_mutex_lock
(
&
python_wait_mutex
);
}
/* Called by PLC thread on each new python command*/
void
UnBlockPythonCommands
(
void
)
{
/* signal python thread it can read data */
pthread_mutex_unlock
(
&
python_wait_mutex
);
}
int
TryLockPython
(
void
)
{
return
pthread_mutex_trylock
(
&
python_mutex
)
==
0
;
}
void
UnLockPython
(
void
)
{
pthread_mutex_unlock
(
&
python_mutex
);
}
void
LockPython
(
void
)
{
pthread_mutex_lock
(
&
python_mutex
);
}
struct
RT_to_nRT_signal_s
{
pthread_cond_t
WakeCond
;
pthread_mutex_t
WakeCondLock
;
};
typedef
struct
RT_to_nRT_signal_s
RT_to_nRT_signal_t
;
#define _LogAndReturnNull(text) \
{\
char mstr[256] = text " for ";\
strncat(mstr, name, 255);\
LogMessage(LOG_CRITICAL, mstr, strlen(mstr));\
return NULL;\
}
void
*
create_RT_to_nRT_signal
(
char
*
name
){
RT_to_nRT_signal_t
*
sig
=
(
RT_to_nRT_signal_t
*
)
malloc
(
sizeof
(
RT_to_nRT_signal_t
));
if
(
!
sig
)
_LogAndReturnNull
(
"Failed allocating memory for RT_to_nRT signal"
);
pthread_cond_init
(
&
sig
->
WakeCond
,
NULL
);
pthread_mutex_init
(
&
sig
->
WakeCondLock
,
NULL
);
return
(
void
*
)
sig
;
}
void
delete_RT_to_nRT_signal
(
void
*
handle
){
RT_to_nRT_signal_t
*
sig
=
(
RT_to_nRT_signal_t
*
)
handle
;
pthread_cond_destroy
(
&
sig
->
WakeCond
);
pthread_mutex_destroy
(
&
sig
->
WakeCondLock
);
free
(
sig
);
}
int
wait_RT_to_nRT_signal
(
void
*
handle
){
int
ret
;
RT_to_nRT_signal_t
*
sig
=
(
RT_to_nRT_signal_t
*
)
handle
;
pthread_mutex_lock
(
&
sig
->
WakeCondLock
);
ret
=
pthread_cond_wait
(
&
sig
->
WakeCond
,
&
sig
->
WakeCondLock
);
pthread_mutex_unlock
(
&
sig
->
WakeCondLock
);
return
ret
;
}
int
unblock_RT_to_nRT_signal
(
void
*
handle
){
RT_to_nRT_signal_t
*
sig
=
(
RT_to_nRT_signal_t
*
)
handle
;
return
pthread_cond_signal
(
&
sig
->
WakeCond
);
}
void
nRT_reschedule
(
void
){
sched_yield
();
}
/*
This file is part of Beremiz, a Integrated Development Environment for
programming IEC 61131-3 automates supporting plcopen standard and CanFestival.
See COPYING.runtime
Copyright (C) 2018: Sergey Surkov <surkov.sv@summatechnology.ru>
Copyright (C) 2018: Andrey Skvortsov <andrej.skvortzov@gmail.com>
*/
#ifndef HAVE_RETAIN
#include <stdio.h>
#include <stdint.h>
#include <unistd.h>
#include "iec_types.h"
int
GetRetainSize
(
void
);
/* Retain buffer. */
FILE
*
retain_buffer
;
const
char
rb_file
[]
=
"retain_buffer_file"
;
const
char
rb_file_bckp
[]
=
"retain_buffer_file.bak"
;
/* Retain header struct. */
struct
retain_info_t
{
uint32_t
retain_size
;
uint32_t
hash_size
;
uint8_t
*
hash
;
uint32_t
header_offset
;
uint32_t
header_crc
;
};
/* Init retain info structure. */
struct
retain_info_t
retain_info
;
/* CRC lookup table and initial state. */
static
const
uint32_t
crc32_table
[
256
]
=
{
0x00000000
,
0x77073096
,
0xEE0E612C
,
0x990951BA
,
0x076DC419
,
0x706AF48F
,
0xE963A535
,
0x9E6495A3
,
0x0EDB8832
,
0x79DCB8A4
,
0xE0D5E91E
,
0x97D2D988
,
0x09B64C2B
,
0x7EB17CBD
,
0xE7B82D07
,
0x90BF1D91
,
0x1DB71064
,
0x6AB020F2
,
0xF3B97148
,
0x84BE41DE
,
0x1ADAD47D
,
0x6DDDE4EB
,
0xF4D4B551
,
0x83D385C7
,
0x136C9856
,
0x646BA8C0
,
0xFD62F97A
,
0x8A65C9EC
,
0x14015C4F
,
0x63066CD9
,
0xFA0F3D63
,
0x8D080DF5
,
0x3B6E20C8
,
0x4C69105E
,
0xD56041E4
,
0xA2677172
,
0x3C03E4D1
,
0x4B04D447
,
0xD20D85FD
,
0xA50AB56B
,
0x35B5A8FA
,
0x42B2986C
,
0xDBBBC9D6
,
0xACBCF940
,
0x32D86CE3
,
0x45DF5C75
,
0xDCD60DCF
,
0xABD13D59
,
0x26D930AC
,
0x51DE003A
,
0xC8D75180
,
0xBFD06116
,
0x21B4F4B5
,
0x56B3C423
,
0xCFBA9599
,
0xB8BDA50F
,
0x2802B89E
,
0x5F058808
,
0xC60CD9B2
,
0xB10BE924
,
0x2F6F7C87
,
0x58684C11
,
0xC1611DAB
,
0xB6662D3D
,
0x76DC4190
,
0x01DB7106
,
0x98D220BC
,
0xEFD5102A
,
0x71B18589
,
0x06B6B51F
,
0x9FBFE4A5
,
0xE8B8D433
,
0x7807C9A2
,
0x0F00F934
,
0x9609A88E
,
0xE10E9818
,
0x7F6A0DBB
,
0x086D3D2D
,
0x91646C97
,
0xE6635C01
,
0x6B6B51F4
,
0x1C6C6162
,
0x856530D8
,
0xF262004E
,
0x6C0695ED
,
0x1B01A57B
,
0x8208F4C1
,
0xF50FC457
,
0x65B0D9C6
,
0x12B7E950
,
0x8BBEB8EA
,
0xFCB9887C
,
0x62DD1DDF
,
0x15DA2D49
,
0x8CD37CF3
,
0xFBD44C65
,
0x4DB26158
,
0x3AB551CE
,
0xA3BC0074
,
0xD4BB30E2
,
0x4ADFA541
,
0x3DD895D7
,
0xA4D1C46D
,
0xD3D6F4FB
,
0x4369E96A
,
0x346ED9FC
,
0xAD678846
,
0xDA60B8D0
,
0x44042D73
,
0x33031DE5
,
0xAA0A4C5F
,
0xDD0D7CC9
,
0x5005713C
,
0x270241AA
,
0xBE0B1010
,
0xC90C2086
,
0x5768B525
,
0x206F85B3
,
0xB966D409
,
0xCE61E49F
,
0x5EDEF90E
,
0x29D9C998
,
0xB0D09822
,
0xC7D7A8B4
,
0x59B33D17
,
0x2EB40D81
,
0xB7BD5C3B
,
0xC0BA6CAD
,
0xEDB88320
,
0x9ABFB3B6
,
0x03B6E20C
,
0x74B1D29A
,
0xEAD54739
,
0x9DD277AF
,
0x04DB2615
,
0x73DC1683
,
0xE3630B12
,
0x94643B84
,
0x0D6D6A3E
,
0x7A6A5AA8
,
0xE40ECF0B
,
0x9309FF9D
,
0x0A00AE27
,
0x7D079EB1
,
0xF00F9344
,
0x8708A3D2
,
0x1E01F268
,
0x6906C2FE
,
0xF762575D
,
0x806567CB
,
0x196C3671
,
0x6E6B06E7
,
0xFED41B76
,
0x89D32BE0
,
0x10DA7A5A
,
0x67DD4ACC
,
0xF9B9DF6F
,
0x8EBEEFF9
,
0x17B7BE43
,
0x60B08ED5
,
0xD6D6A3E8
,
0xA1D1937E
,
0x38D8C2C4
,
0x4FDFF252
,
0xD1BB67F1
,
0xA6BC5767
,
0x3FB506DD
,
0x48B2364B
,
0xD80D2BDA
,
0xAF0A1B4C
,
0x36034AF6
,
0x41047A60
,
0xDF60EFC3
,
0xA867DF55
,
0x316E8EEF
,
0x4669BE79
,
0xCB61B38C
,
0xBC66831A
,
0x256FD2A0
,
0x5268E236
,
0xCC0C7795
,
0xBB0B4703
,
0x220216B9
,
0x5505262F
,
0xC5BA3BBE
,
0xB2BD0B28
,
0x2BB45A92
,
0x5CB36A04
,
0xC2D7FFA7
,
0xB5D0CF31
,
0x2CD99E8B
,
0x5BDEAE1D
,
0x9B64C2B0
,
0xEC63F226
,
0x756AA39C
,
0x026D930A
,
0x9C0906A9
,
0xEB0E363F
,
0x72076785
,
0x05005713
,
0x95BF4A82
,
0xE2B87A14
,
0x7BB12BAE
,
0x0CB61B38
,
0x92D28E9B
,
0xE5D5BE0D
,
0x7CDCEFB7
,
0x0BDBDF21
,
0x86D3D2D4
,
0xF1D4E242
,
0x68DDB3F8
,
0x1FDA836E
,
0x81BE16CD
,
0xF6B9265B
,
0x6FB077E1
,
0x18B74777
,
0x88085AE6
,
0xFF0F6A70
,
0x66063BCA
,
0x11010B5C
,
0x8F659EFF
,
0xF862AE69
,
0x616BFFD3
,
0x166CCF45
,
0xA00AE278
,
0xD70DD2EE
,
0x4E048354
,
0x3903B3C2
,
0xA7672661
,
0xD06016F7
,
0x4969474D
,
0x3E6E77DB
,
0xAED16A4A
,
0xD9D65ADC
,
0x40DF0B66
,
0x37D83BF0
,
0xA9BCAE53
,
0xDEBB9EC5
,
0x47B2CF7F
,
0x30B5FFE9
,
0xBDBDF21C
,
0xCABAC28A
,
0x53B39330
,
0x24B4A3A6
,
0xBAD03605
,
0xCDD70693
,
0x54DE5729
,
0x23D967BF
,
0xB3667A2E
,
0xC4614AB8
,
0x5D681B02
,
0x2A6F2B94
,
0xB40BBE37
,
0xC30C8EA1
,
0x5A05DF1B
,
0x2D02EF8D
,
};
uint32_t
retain_crc
;
/* Calculate CRC32 for len bytes from pointer buf with init starting value. */
uint32_t
GenerateCRC32Sum
(
const
void
*
buf
,
unsigned
int
len
,
uint32_t
init
)
{
uint32_t
crc
=
~
init
;
unsigned
char
*
current
=
(
unsigned
char
*
)
buf
;
while
(
len
--
)
crc
=
crc32_table
[(
crc
^
*
current
++
)
&
0xFF
]
^
(
crc
>>
8
);
return
~
crc
;
}
/* Calc CRC32 for retain file byte by byte. */
int
CheckFileCRC
(
FILE
*
file_buffer
)
{
/* Set the magic constant for one-pass CRC calc according to ZIP CRC32. */
const
uint32_t
magic_number
=
0x2144df1c
;
/* CRC initial state. */
uint32_t
calc_crc32
=
0
;
char
data_block
=
0
;
while
(
!
feof
(
file_buffer
)){
if
(
fread
(
&
data_block
,
sizeof
(
data_block
),
1
,
file_buffer
))
calc_crc32
=
GenerateCRC32Sum
(
&
data_block
,
sizeof
(
char
),
calc_crc32
);
}
/* Compare crc result with a magic number. */
return
(
calc_crc32
==
magic_number
)
?
1
:
0
;
}
/* Compare current hash with hash from file byte by byte. */
int
CheckFilehash
(
void
)
{
int
k
,
ret
;
int
offset
=
sizeof
(
retain_info
.
retain_size
);
rewind
(
retain_buffer
);
fseek
(
retain_buffer
,
offset
,
SEEK_SET
);
uint32_t
size
;
ret
=
fread
(
&
size
,
sizeof
(
size
),
1
,
retain_buffer
);
if
(
size
!=
retain_info
.
hash_size
)
return
0
;
for
(
k
=
0
;
k
<
retain_info
.
hash_size
;
k
++
){
uint8_t
file_digit
;
ret
=
fread
(
&
file_digit
,
sizeof
(
char
),
1
,
retain_buffer
);
if
(
file_digit
!=
*
(
retain_info
.
hash
+
k
))
return
0
;
}
return
1
;
}
void
InitRetain
(
void
)
{
int
i
;
/* Get retain size in bytes */
retain_info
.
retain_size
=
GetRetainSize
();
/* Hash stored in retain file as array of char in hex digits
(that's why we divide strlen in two). */
retain_info
.
hash_size
=
PLC_ID
?
strlen
(
PLC_ID
)
/
2
:
0
;
//retain_info.hash_size = 0;
retain_info
.
hash
=
malloc
(
retain_info
.
hash_size
);
/* Transform hash string into byte sequence. */
for
(
i
=
0
;
i
<
retain_info
.
hash_size
;
i
++
)
{
int
byte
=
0
;
sscanf
((
PLC_ID
+
i
*
2
),
"%02X"
,
&
byte
);
retain_info
.
hash
[
i
]
=
byte
;
}
/* Calc header offset. */
retain_info
.
header_offset
=
sizeof
(
retain_info
.
retain_size
)
+
\
sizeof
(
retain_info
.
hash_size
)
+
\
retain_info
.
hash_size
;
/* Set header CRC initial state. */
retain_info
.
header_crc
=
0
;
/* Calc crc for header. */
retain_info
.
header_crc
=
GenerateCRC32Sum
(
&
retain_info
.
retain_size
,
sizeof
(
retain_info
.
retain_size
),
retain_info
.
header_crc
);
retain_info
.
header_crc
=
GenerateCRC32Sum
(
&
retain_info
.
hash_size
,
sizeof
(
retain_info
.
hash_size
),
retain_info
.
header_crc
);
retain_info
.
header_crc
=
GenerateCRC32Sum
(
retain_info
.
hash
,
retain_info
.
hash_size
,
retain_info
.
header_crc
);
}
void
CleanupRetain
(
void
)
{
/* Free hash memory. */
free
(
retain_info
.
hash
);
}
int
CheckRetainFile
(
const
char
*
file
)
{
retain_buffer
=
fopen
(
file
,
"rb"
);
if
(
retain_buffer
)
{
/* Check CRC32 and hash. */
if
(
CheckFileCRC
(
retain_buffer
))
if
(
CheckFilehash
())
return
1
;
fclose
(
retain_buffer
);
retain_buffer
=
NULL
;
}
return
0
;
}
int
CheckRetainBuffer
(
void
)
{
retain_buffer
=
NULL
;
if
(
!
retain_info
.
retain_size
)
return
1
;
/* Check latest retain file. */
if
(
CheckRetainFile
(
rb_file
))
return
1
;
/* Check if we have backup. */
if
(
CheckRetainFile
(
rb_file_bckp
))
return
1
;
/* We don't have any valid retain buffer - nothing to remind. */
return
0
;
}
#ifndef FILE_RETAIN_SAVE_PERIOD_S
#define FILE_RETAIN_SAVE_PERIOD_S 1.0
#endif
static
double
CalcDiffSeconds
(
IEC_TIME
*
t1
,
IEC_TIME
*
t2
)
{
IEC_TIME
dt
=
{
t1
->
tv_sec
-
t2
->
tv_sec
,
t1
->
tv_nsec
-
t2
->
tv_nsec
};
if
((
dt
.
tv_nsec
<
-
1000000000
)
||
((
dt
.
tv_sec
>
0
)
&&
(
dt
.
tv_nsec
<
0
))){
dt
.
tv_sec
--
;
dt
.
tv_nsec
+=
1000000000
;
}
if
((
dt
.
tv_nsec
>
+
1000000000
)
||
((
dt
.
tv_sec
<
0
)
&&
(
dt
.
tv_nsec
>
0
))){
dt
.
tv_sec
++
;
dt
.
tv_nsec
-=
1000000000
;
}
return
dt
.
tv_sec
+
1e-9
*
dt
.
tv_nsec
;
}
int
RetainSaveNeeded
(
void
)
{
int
ret
=
0
;
static
IEC_TIME
last_save
;
IEC_TIME
now
;
double
diff_s
;
/* no retain */
if
(
!
retain_info
.
retain_size
)
return
0
;
/* periodic retain flush to avoid high I/O load */
PLC_GetTime
(
&
now
);
diff_s
=
CalcDiffSeconds
(
&
now
,
&
last_save
);
if
((
diff_s
>
FILE_RETAIN_SAVE_PERIOD_S
)
||
ForceSaveRetainReq
())
{
ret
=
1
;
last_save
=
now
;
}
return
ret
;
}
void
ValidateRetainBuffer
(
void
)
{
if
(
!
retain_buffer
)
return
;
/* Add retain data CRC to the end of buffer file. */
fseek
(
retain_buffer
,
0
,
SEEK_END
);
fwrite
(
&
retain_crc
,
sizeof
(
uint32_t
),
1
,
retain_buffer
);
/* Sync file buffer and close file. */
#ifdef __WIN32
fflush
(
retain_buffer
);
#else
fsync
(
fileno
(
retain_buffer
));
#endif
fclose
(
retain_buffer
);
retain_buffer
=
NULL
;
}
void
InValidateRetainBuffer
(
void
)
{
if
(
!
RetainSaveNeeded
())
return
;
/* Rename old retain file into *.bak if it exists. */
rename
(
rb_file
,
rb_file_bckp
);
/* Set file CRC initial value. */
retain_crc
=
retain_info
.
header_crc
;
/* Create new retain file. */
retain_buffer
=
fopen
(
rb_file
,
"wb+"
);
if
(
!
retain_buffer
)
{
fprintf
(
stderr
,
"Failed to create retain file : %s
\n
"
,
rb_file
);
return
;
}
/* Write header to the new file. */
fwrite
(
&
retain_info
.
retain_size
,
sizeof
(
retain_info
.
retain_size
),
1
,
retain_buffer
);
fwrite
(
&
retain_info
.
hash_size
,
sizeof
(
retain_info
.
hash_size
),
1
,
retain_buffer
);
fwrite
(
retain_info
.
hash
,
sizeof
(
char
),
retain_info
.
hash_size
,
retain_buffer
);
}
void
Retain
(
unsigned
int
offset
,
unsigned
int
count
,
void
*
p
)
{
if
(
!
retain_buffer
)
return
;
/* Generate CRC 32 for each data block. */
retain_crc
=
GenerateCRC32Sum
(
p
,
count
,
retain_crc
);
/* Save current var in file. */
fseek
(
retain_buffer
,
retain_info
.
header_offset
+
offset
,
SEEK_SET
);
fwrite
(
p
,
count
,
1
,
retain_buffer
);
}
void
Remind
(
unsigned
int
offset
,
unsigned
int
count
,
void
*
p
)
{
int
ret
;
/* Remind variable from file. */
fseek
(
retain_buffer
,
retain_info
.
header_offset
+
offset
,
SEEK_SET
);
ret
=
fread
((
void
*
)
p
,
count
,
1
,
retain_buffer
);
}
#endif // !HAVE_RETAIN
/**
* Tail of code common to all C targets
**/
/**
* LOGGING
**/
#ifndef TARGET_LOGGING_DISABLE
#ifndef LOG_BUFFER_SIZE
#define LOG_BUFFER_SIZE (1<<14)
/*16Ko*/
#endif
#ifndef LOG_BUFFER_ATTRS
#define LOG_BUFFER_ATTRS
#endif
#define LOG_BUFFER_MASK (LOG_BUFFER_SIZE-1)
static
char
LogBuff
[
LOG_LEVELS
][
LOG_BUFFER_SIZE
]
LOG_BUFFER_ATTRS
;
static
void
inline
copy_to_log
(
uint8_t
level
,
uint32_t
buffpos
,
void
*
buf
,
uint32_t
size
){
if
(
buffpos
+
size
<
LOG_BUFFER_SIZE
){
memcpy
(
&
LogBuff
[
level
][
buffpos
],
buf
,
size
);
}
else
{
uint32_t
remaining
=
LOG_BUFFER_SIZE
-
buffpos
;
memcpy
(
&
LogBuff
[
level
][
buffpos
],
buf
,
remaining
);
memcpy
(
LogBuff
[
level
],
(
char
*
)
buf
+
remaining
,
size
-
remaining
);
}
}
static
void
inline
copy_from_log
(
uint8_t
level
,
uint32_t
buffpos
,
void
*
buf
,
uint32_t
size
){
if
(
buffpos
+
size
<
LOG_BUFFER_SIZE
){
memcpy
(
buf
,
&
LogBuff
[
level
][
buffpos
],
size
);
}
else
{
uint32_t
remaining
=
LOG_BUFFER_SIZE
-
buffpos
;
memcpy
(
buf
,
&
LogBuff
[
level
][
buffpos
],
remaining
);
memcpy
((
char
*
)
buf
+
remaining
,
LogBuff
[
level
],
size
-
remaining
);
}
}
/* Log buffer structure
|<-Tail1.msgsize->|<-sizeof(mTail)->|<--Tail2.msgsize-->|<-sizeof(mTail)->|...
| Message1 Body | Tail1 | Message2 Body | Tail2 |
*/
typedef
struct
{
uint32_t
msgidx
;
uint32_t
msgsize
;
unsigned
long
tick
;
IEC_TIME
time
;
}
mTail
;
/* Log cursor : 64b
|63 ... 32|31 ... 0|
| Message | Buffer |
| counter | Index | */
static
uint64_t
LogCursor
[
LOG_LEVELS
]
LOG_BUFFER_ATTRS
=
{
0x0
,
0x0
,
0x0
,
0x0
};
void
ResetLogCount
(
void
)
{
uint8_t
level
;
for
(
level
=
0
;
level
<
LOG_LEVELS
;
level
++
){
LogCursor
[
level
]
=
0
;
}
}
/* Store one log message of give size */
int
LogMessage
(
uint8_t
level
,
char
*
buf
,
uint32_t
size
){
if
(
size
<
LOG_BUFFER_SIZE
-
sizeof
(
mTail
)){
uint32_t
buffpos
;
uint64_t
new_cursor
,
old_cursor
;
mTail
tail
;
tail
.
msgsize
=
size
;
tail
.
tick
=
__tick
;
PLC_GetTime
(
&
tail
.
time
);
/* We cannot increment both msg index and string pointer
in a single atomic operation but we can detect having been interrupted.
So we can try with atomic compare and swap in a loop until operation
succeeds non interrupted */
do
{
old_cursor
=
LogCursor
[
level
];
buffpos
=
(
uint32_t
)
old_cursor
;
tail
.
msgidx
=
(
old_cursor
>>
32
);
new_cursor
=
((
uint64_t
)(
tail
.
msgidx
+
1
)
<<
32
)
|
(
uint64_t
)((
buffpos
+
size
+
sizeof
(
mTail
))
&
LOG_BUFFER_MASK
);
}
while
(
AtomicCompareExchange64
(
(
long
long
*
)
&
LogCursor
[
level
],
(
long
long
)
old_cursor
,
(
long
long
)
new_cursor
)
!=
(
long
long
)
old_cursor
);
copy_to_log
(
level
,
buffpos
,
buf
,
size
);
copy_to_log
(
level
,
(
buffpos
+
size
)
&
LOG_BUFFER_MASK
,
&
tail
,
sizeof
(
mTail
));
return
1
;
/* Success */
}
else
{
char
mstr
[]
=
"Logging error : message too big"
;
LogMessage
(
LOG_CRITICAL
,
mstr
,
sizeof
(
mstr
));
}
return
0
;
}
uint32_t
GetLogCount
(
uint8_t
level
){
return
(
uint64_t
)
LogCursor
[
level
]
>>
32
;
}
/* Return message size and content */
uint32_t
GetLogMessage
(
uint8_t
level
,
uint32_t
msgidx
,
char
*
buf
,
uint32_t
max_size
,
uint32_t
*
tick
,
uint32_t
*
tv_sec
,
uint32_t
*
tv_nsec
){
uint64_t
cursor
=
LogCursor
[
level
];
if
(
cursor
){
/* seach cursor */
uint32_t
stailpos
=
(
uint32_t
)
cursor
;
uint32_t
smsgidx
;
mTail
tail
;
tail
.
msgidx
=
cursor
>>
32
;
tail
.
msgsize
=
0
;
/* Message search loop */
do
{
smsgidx
=
tail
.
msgidx
;
stailpos
=
(
stailpos
-
sizeof
(
mTail
)
-
tail
.
msgsize
)
&
LOG_BUFFER_MASK
;
copy_from_log
(
level
,
stailpos
,
&
tail
,
sizeof
(
mTail
));
}
while
((
tail
.
msgidx
==
smsgidx
-
1
)
&&
(
tail
.
msgidx
>
msgidx
));
if
(
tail
.
msgidx
==
msgidx
){
uint32_t
sbuffpos
=
(
stailpos
-
tail
.
msgsize
)
&
LOG_BUFFER_MASK
;
uint32_t
totalsize
=
tail
.
msgsize
;
*
tick
=
tail
.
tick
;
*
tv_sec
=
tail
.
time
.
tv_sec
;
*
tv_nsec
=
tail
.
time
.
tv_nsec
;
copy_from_log
(
level
,
sbuffpos
,
buf
,
totalsize
>
max_size
?
max_size
:
totalsize
);
return
totalsize
;
}
}
return
0
;
}
#endif
#ifndef TARGET_EXT_SYNC_DISABLE
#define CALIBRATED -2
#define NOT_CALIBRATED -1
static
int
calibration_count
=
NOT_CALIBRATED
;
static
IEC_TIME
cal_begin
;
static
long
long
Tsync
=
0
;
static
long
long
FreqCorr
=
0
;
static
int
Nticks
=
0
;
static
unsigned
long
last_tick
=
0
;
/*
* Called on each external periodic sync event
* make PLC tick synchronous with external sync
* ratio defines when PLC tick occurs between two external sync
* @param sync_align_ratio
* 0->100 : align ratio
* < 0 : no align, calibrate period
**/
void
align_tick
(
int
sync_align_ratio
)
{
/*
printf("align_tick(%d)\n", calibrate);
*/
if
(
sync_align_ratio
<
0
){
/* Calibration */
if
(
calibration_count
==
CALIBRATED
)
/* Re-calibration*/
calibration_count
=
NOT_CALIBRATED
;
if
(
calibration_count
==
NOT_CALIBRATED
)
/* Calibration start, get time*/
PLC_GetTime
(
&
cal_begin
);
calibration_count
++
;
}
else
{
/* do alignment (if possible) */
if
(
calibration_count
>=
0
){
/* End of calibration */
/* Get final time */
IEC_TIME
cal_end
;
PLC_GetTime
(
&
cal_end
);
/*adjust calibration_count*/
calibration_count
++
;
/* compute mean of Tsync, over calibration period */
Tsync
=
((
long
long
)(
cal_end
.
tv_sec
-
cal_begin
.
tv_sec
)
*
(
long
long
)
1000000000
+
(
cal_end
.
tv_nsec
-
cal_begin
.
tv_nsec
))
/
calibration_count
;
if
(
(
Nticks
=
(
Tsync
/
common_ticktime__
))
>
0
){
FreqCorr
=
(
Tsync
%
common_ticktime__
);
/* to be divided by Nticks */
}
else
{
FreqCorr
=
Tsync
-
(
common_ticktime__
%
Tsync
);
}
/*
printf("Tsync = %ld\n", Tsync);
printf("calibration_count = %d\n", calibration_count);
printf("Nticks = %d\n", Nticks);
*/
calibration_count
=
CALIBRATED
;
}
if
(
calibration_count
==
CALIBRATED
){
/* Get Elapsed time since last PLC tick (__CURRENT_TIME) */
IEC_TIME
now
;
long
long
elapsed
;
long
long
Tcorr
;
long
long
PhaseCorr
;
long
long
PeriodicTcorr
;
PLC_GetTime
(
&
now
);
elapsed
=
(
now
.
tv_sec
-
__CURRENT_TIME
.
tv_sec
)
*
1000000000
+
now
.
tv_nsec
-
__CURRENT_TIME
.
tv_nsec
;
if
(
Nticks
>
0
){
PhaseCorr
=
elapsed
-
(
common_ticktime__
+
FreqCorr
/
Nticks
)
*
sync_align_ratio
/
100
;
/* to be divided by Nticks */
Tcorr
=
common_ticktime__
+
(
PhaseCorr
+
FreqCorr
)
/
Nticks
;
if
(
Nticks
<
2
){
/* When Sync source period is near Tick time */
/* PhaseCorr may not be applied to Periodic time given to timer */
PeriodicTcorr
=
common_ticktime__
+
FreqCorr
/
Nticks
;
}
else
{
PeriodicTcorr
=
Tcorr
;
}
}
else
if
(
__tick
>
last_tick
){
last_tick
=
__tick
;
PhaseCorr
=
elapsed
-
(
Tsync
*
sync_align_ratio
/
100
);
PeriodicTcorr
=
Tcorr
=
common_ticktime__
+
PhaseCorr
+
FreqCorr
;
}
else
{
/*PLC did not run meanwhile. Nothing to do*/
return
;
}
/* DO ALIGNEMENT */
PLC_SetTimer
(
Tcorr
-
elapsed
,
PeriodicTcorr
);
}
}
}
#endif
This diff is collapsed.
Click to expand it.
Beremiz/beremiz_tutorial_multiple_couplers_opc_ua/build/py_ext.c
0 → 100644
View file @
59677959
/*
* Python Asynchronous execution code
*
* PLC put python commands in a fifo, respecting execution order
* with the help of C pragmas inserted in python_eval FB code
*
* Buffer content is read asynchronously, (from non real time part),
* commands are executed and result stored for later use by PLC.
*
* In this implementation, fifo is a list of pointer to python_eval
* function blocks structures. Some local variables have been added in
* python_eval interface. We use those local variables as buffer and state
* flags.
*
* */
#include "iec_types_all.h"
#include "POUS.h"
#include <string.h>
/* The fifo (fixed size, as number of FB is fixed) */
static
PYTHON_EVAL
*
EvalFBs
[
1
];
/* Producer and consumer cursors */
static
int
Current_PLC_EvalFB
;
static
int
Current_Python_EvalFB
;
/* A global IEC-Python gateway state, for use inside python_eval FBs*/
static
int
PythonState
;
#define PYTHON_LOCKED_BY_PYTHON 0
#define PYTHON_LOCKED_BY_PLC 1
#define PYTHON_MUSTWAKEUP 2
#define PYTHON_FINISHED 4
/* Each python_eval FunctionBlock have it own state */
#define PYTHON_FB_FREE 0
#define PYTHON_FB_REQUESTED 1
#define PYTHON_FB_PROCESSING 2
#define PYTHON_FB_ANSWERED 3
int
WaitPythonCommands
(
void
);
void
UnBlockPythonCommands
(
void
);
int
TryLockPython
(
void
);
void
UnLockPython
(
void
);
void
LockPython
(
void
);
int
__init_py_ext
()
{
int
i
;
/* Initialize cursors */
Current_Python_EvalFB
=
0
;
Current_PLC_EvalFB
=
0
;
PythonState
=
PYTHON_LOCKED_BY_PYTHON
;
for
(
i
=
0
;
i
<
1
;
i
++
)
EvalFBs
[
i
]
=
NULL
;
return
0
;
}
void
__cleanup_py_ext
()
{
PythonState
=
PYTHON_FINISHED
;
UnBlockPythonCommands
();
}
void
__retrieve_py_ext
()
{
/* Check Python thread is not being
* modifying internal python_eval data */
PythonState
=
TryLockPython
()
?
PYTHON_LOCKED_BY_PLC
:
PYTHON_LOCKED_BY_PYTHON
;
/* If python thread _is_ in, then PythonState remains PYTHON_LOCKED_BY_PYTHON
* and python_eval will no do anything */
}
void
__publish_py_ext
()
{
if
(
PythonState
&
PYTHON_LOCKED_BY_PLC
){
/* If runnig PLC did push something in the fifo*/
if
(
PythonState
&
PYTHON_MUSTWAKEUP
){
/* WakeUp python thread */
UnBlockPythonCommands
();
}
UnLockPython
();
}
}
/**
* Called by the PLC, each time a python_eval
* FB instance is executed
*/
void
__PythonEvalFB
(
int
poll
,
PYTHON_EVAL
*
data__
)
{
if
(
!
__GET_VAR
(
data__
->
TRIG
)){
/* ACK is False when TRIG is false, except a pulse when receiving result */
__SET_VAR
(
data__
->
,
ACK
,,
0
);
}
/* detect rising edge on TRIG to trigger evaluation */
if
(((
__GET_VAR
(
data__
->
TRIG
)
&&
!
__GET_VAR
(
data__
->
TRIGM1
))
||
/* polling is equivalent to trig on value rather than on rising edge*/
(
poll
&&
__GET_VAR
(
data__
->
TRIG
)
))
&&
/* trig only if not already trigged */
__GET_VAR
(
data__
->
TRIGGED
)
==
0
){
/* mark as trigged */
__SET_VAR
(
data__
->
,
TRIGGED
,,
1
);
/* make a safe copy of the code */
__SET_VAR
(
data__
->
,
PREBUFFER
,,
__GET_VAR
(
data__
->
CODE
));
}
/* retain value for next rising edge detection */
__SET_VAR
(
data__
->
,
TRIGM1
,,
__GET_VAR
(
data__
->
TRIG
));
/* python thread is not in ? */
if
(
PythonState
&
PYTHON_LOCKED_BY_PLC
){
/* if some answer are waiting, publish*/
if
(
__GET_VAR
(
data__
->
STATE
)
==
PYTHON_FB_ANSWERED
){
/* Copy buffer content into result*/
__SET_VAR
(
data__
->
,
RESULT
,,
__GET_VAR
(
data__
->
BUFFER
));
/* signal result presence to PLC*/
__SET_VAR
(
data__
->
,
ACK
,,
1
);
/* Mark as free */
__SET_VAR
(
data__
->
,
STATE
,,
PYTHON_FB_FREE
);
/* mark as not trigged */
if
(
!
poll
)
__SET_VAR
(
data__
->
,
TRIGGED
,,
0
);
/*printf("__PythonEvalFB pop %d - %*s\n",Current_PLC_EvalFB, data__->BUFFER.len, data__->BUFFER.body);*/
}
else
if
(
poll
){
/* when in polling, no answer == ack down */
__SET_VAR
(
data__
->
,
ACK
,,
0
);
}
/* got the order to act ?*/
if
(
__GET_VAR
(
data__
->
TRIGGED
)
==
1
&&
/* and not already being processed */
__GET_VAR
(
data__
->
STATE
)
==
PYTHON_FB_FREE
)
{
/* Enter the block in the fifo
* Don't have to check if fifo cell is free
* as fifo size == FB count, and a FB cannot
* be requested twice */
EvalFBs
[
Current_PLC_EvalFB
]
=
data__
;
/* copy into BUFFER local*/
__SET_VAR
(
data__
->
,
BUFFER
,,
__GET_VAR
(
data__
->
PREBUFFER
));
/* Set ACK pin to low so that we can set a rising edge on result */
if
(
!
poll
){
/* when not polling, a new answer imply reseting ack*/
__SET_VAR
(
data__
->
,
ACK
,,
0
);
}
else
{
/* when in polling, acting reset trigger */
__SET_VAR
(
data__
->
,
TRIGGED
,,
0
);
}
/* Mark FB busy */
__SET_VAR
(
data__
->
,
STATE
,,
PYTHON_FB_REQUESTED
);
/* Have to wakeup python thread in case he was asleep */
PythonState
|=
PYTHON_MUSTWAKEUP
;
/*printf("__PythonEvalFB push %d - %*s\n",Current_PLC_EvalFB, data__->BUFFER.len, data__->BUFFER.body);*/
/* Get a new line */
Current_PLC_EvalFB
=
(
Current_PLC_EvalFB
+
1
)
%
1
;
}
}
}
char
*
PythonIterator
(
char
*
result
,
void
**
id
)
{
char
*
next_command
;
PYTHON_EVAL
*
data__
;
//printf("PythonIterator result %s\n", result);
/*emergency exit*/
if
(
PythonState
&
PYTHON_FINISHED
)
return
NULL
;
/* take python mutex to prevent changing PLC data while PLC running */
LockPython
();
/* Get current FB */
data__
=
EvalFBs
[
Current_Python_EvalFB
];
if
(
data__
&&
/* may be null at first run */
__GET_VAR
(
data__
->
STATE
)
==
PYTHON_FB_PROCESSING
){
/* some answer awaited*/
/* If result not None */
if
(
result
){
/* Get results len */
__SET_VAR
(
data__
->
,
BUFFER
,
.
len
,
strlen
(
result
));
/* prevent results overrun */
if
(
__GET_VAR
(
data__
->
BUFFER
,
.
len
)
>
STR_MAX_LEN
)
{
__SET_VAR
(
data__
->
,
BUFFER
,
.
len
,
STR_MAX_LEN
);
/* TODO : signal error */
}
/* Copy results to buffer */
strncpy
((
char
*
)
__GET_VAR
(
data__
->
BUFFER
,
.
body
),
result
,
__GET_VAR
(
data__
->
BUFFER
,.
len
));
}
else
{
__SET_VAR
(
data__
->
,
BUFFER
,
.
len
,
0
);
}
/* remove block from fifo*/
EvalFBs
[
Current_Python_EvalFB
]
=
NULL
;
/* Mark block as answered */
__SET_VAR
(
data__
->
,
STATE
,,
PYTHON_FB_ANSWERED
);
/* Get a new line */
Current_Python_EvalFB
=
(
Current_Python_EvalFB
+
1
)
%
1
;
//printf("PythonIterator ++ Current_Python_EvalFB %d\n", Current_Python_EvalFB);
}
/* while next slot is empty */
while
(((
data__
=
EvalFBs
[
Current_Python_EvalFB
])
==
NULL
)
||
/* or doesn't contain command */
__GET_VAR
(
data__
->
STATE
)
!=
PYTHON_FB_REQUESTED
)
{
UnLockPython
();
/* wait next FB to eval */
//printf("PythonIterator wait\n");
if
(
WaitPythonCommands
())
return
NULL
;
/*emergency exit*/
if
(
PythonState
&
PYTHON_FINISHED
)
return
NULL
;
LockPython
();
}
/* Mark block as processing */
__SET_VAR
(
data__
->
,
STATE
,,
PYTHON_FB_PROCESSING
);
//printf("PythonIterator\n");
/* make BUFFER a null terminated string */
__SET_VAR
(
data__
->
,
BUFFER
,
.
body
[
__GET_VAR
(
data__
->
BUFFER
,
.
len
)],
0
);
/* next command is BUFFER */
next_command
=
(
char
*
)
__GET_VAR
(
data__
->
BUFFER
,
.
body
);
*
id
=
data__
;
/* free python mutex */
UnLockPython
();
/* return the next command to eval */
return
next_command
;
}
This diff is collapsed.
Click to expand it.
Beremiz/beremiz_tutorial_multiple_couplers_opc_ua/build/resource1.c
0 → 100644
View file @
59677959
/*******************************************/
/* FILE GENERATED BY iec2c */
/* Editing this file is not recommended... */
/*******************************************/
#include "iec_std_lib.h"
// RESOURCE RESOURCE1
extern
unsigned
long
long
common_ticktime__
;
#include "accessor.h"
#include "POUS.h"
#include "config.h"
#include "POUS.c"
BOOL
TASK0
;
PLC_PRG
RESOURCE1__INSTANCE0
;
#define INSTANCE0 RESOURCE1__INSTANCE0
void
RESOURCE1_init__
(
void
)
{
BOOL
retain
;
retain
=
0
;
TASK0
=
__BOOL_LITERAL
(
FALSE
);
PLC_PRG_init__
(
&
INSTANCE0
,
retain
);
}
void
RESOURCE1_run__
(
unsigned
long
tick
)
{
TASK0
=
!
(
tick
%
1
);
if
(
TASK0
)
{
PLC_PRG_body__
(
&
INSTANCE0
);
}
}
This diff is collapsed.
Click to expand it.
Beremiz/beremiz_tutorial_multiple_couplers_opc_ua/opcua_0@opcua/baseconfnode.xml
0 → 100644
View file @
59677959
<?xml version='1.0' encoding='utf-8'?>
<BaseParams
xmlns:xsd=
"http://www.w3.org/2001/XMLSchema"
IEC_Channel=
"1"
Name=
"opcua_0"
/>
This diff is collapsed.
Click to expand it.
Beremiz/beremiz_tutorial_multiple_couplers_opc_ua/opcua_0@opcua/confnode.xml
0 → 100644
View file @
59677959
<?xml version='1.0' encoding='utf-8'?>
<OPCUAClient
xmlns:xsd=
"http://www.w3.org/2001/XMLSchema"
Server_URI=
"opc.tcp://192.168.0.70:4840"
/>
This diff is collapsed.
Click to expand it.
Beremiz/beremiz_tutorial_multiple_couplers_opc_ua/opcua_0@opcua/selected.csv
0 → 100644
View file @
59677959
input,I2C0 / Relay 0,1,str,i2c0.relay0,Int32,0
input,I2C0 / Relay 1,1,str,i2c0.relay1,Int32,1
input,I2C0 / Relay 2,1,str,i2c0.relay2,Int32,2
input,I2C0 / Relay 3,1,str,i2c0.relay3,Int32,3
input,I2C1 / Relay 0,1,str,i2c1.relay0,Int32,4
input,I2C1 / Relay 1,1,str,i2c1.relay1,Int32,5
input,I2C1 / Relay 2,1,str,i2c1.relay2,Int32,6
input,I2C1 / Relay 3,1,str,i2c1.relay3,Int32,7
output,I2C0 / Relay 0,1,str,i2c0.relay0,Int32,0
output,I2C0 / Relay 1,1,str,i2c0.relay1,Int32,1
output,I2C0 / Relay 2,1,str,i2c0.relay2,Int32,2
output,I2C0 / Relay 3,1,str,i2c0.relay3,Int32,3
output,I2C1 / Relay 0,1,str,i2c1.relay0,Int32,4
output,I2C1 / Relay 1,1,str,i2c1.relay1,Int32,5
output,I2C1 / Relay 2,1,str,i2c1.relay2,Int32,6
output,I2C1 / Relay 3,1,str,i2c1.relay3,Int32,7
This diff is collapsed.
Click to expand it.
Beremiz/beremiz_tutorial_multiple_couplers_opc_ua/opcua_1@opcua/baseconfnode.xml
0 → 100644
View file @
59677959
<?xml version='1.0' encoding='utf-8'?>
<BaseParams
xmlns:xsd=
"http://www.w3.org/2001/XMLSchema"
IEC_Channel=
"0"
Name=
"opcua_1"
/>
This diff is collapsed.
Click to expand it.
Beremiz/beremiz_tutorial_multiple_couplers_opc_ua/opcua_1@opcua/confnode.xml
0 → 100644
View file @
59677959
<?xml version='1.0' encoding='utf-8'?>
<OPCUAClient
xmlns:xsd=
"http://www.w3.org/2001/XMLSchema"
Server_URI=
"opc.tcp://192.168.0.73:4840"
/>
This diff is collapsed.
Click to expand it.
Beremiz/beremiz_tutorial_multiple_couplers_opc_ua/opcua_1@opcua/selected.csv
0 → 100644
View file @
59677959
input,I2C0 / Relay 0,1,str,i2c0.relay0,Int32,0
input,I2C0 / Relay 1,1,str,i2c0.relay1,Int32,1
input,I2C0 / Relay 2,1,str,i2c0.relay2,Int32,2
input,I2C0 / Relay 3,1,str,i2c0.relay3,Int32,3
input,I2C1 / Relay 0,1,str,i2c1.relay0,Int32,4
input,I2C1 / Relay 1,1,str,i2c1.relay1,Int32,5
input,I2C1 / Relay 2,1,str,i2c1.relay2,Int32,6
input,I2C1 / Relay 3,1,str,i2c1.relay3,Int32,7
output,I2C0 / Relay 0,1,str,i2c0.relay0,Int32,0
output,I2C0 / Relay 1,1,str,i2c0.relay1,Int32,1
output,I2C0 / Relay 2,1,str,i2c0.relay2,Int32,2
output,I2C0 / Relay 3,1,str,i2c0.relay3,Int32,3
output,I2C1 / Relay 0,1,str,i2c1.relay0,Int32,4
output,I2C1 / Relay 1,1,str,i2c1.relay1,Int32,5
output,I2C1 / Relay 2,1,str,i2c1.relay2,Int32,6
output,I2C1 / Relay 3,1,str,i2c1.relay3,Int32,7
This diff is collapsed.
Click to expand it.
Beremiz/beremiz_tutorial_multiple_couplers_opc_ua/plc.xml
0 → 100644
View file @
59677959
<?xml version='1.0' encoding='utf-8'?>
<project
xmlns:ns1=
"http://www.plcopen.org/xml/tc6_0201"
xmlns:xhtml=
"http://www.w3.org/1999/xhtml"
xmlns:xsd=
"http://www.w3.org/2001/XMLSchema"
xmlns=
"http://www.plcopen.org/xml/tc6_0201"
>
<fileHeader
companyName=
"Unknown"
productName=
"Unnamed"
productVersion=
"1"
creationDateTime=
"2021-05-14T14:33:11"
/>
<contentHeader
name=
"Counter (OSIE)"
modificationDateTime=
"2022-01-11T13:42:39"
>
<coordinateInfo>
<fbd>
<scaling
x=
"0"
y=
"0"
/>
</fbd>
<ld>
<scaling
x=
"0"
y=
"0"
/>
</ld>
<sfc>
<scaling
x=
"0"
y=
"0"
/>
</sfc>
</coordinateInfo>
</contentHeader>
<types>
<dataTypes/>
<pous>
<pou
name=
"plc_prg"
pouType=
"program"
>
<interface>
<inputVars>
<variable
name=
"Reset"
>
<type>
<BOOL/>
</type>
</variable>
</inputVars>
<outputVars>
<variable
name=
"Cnt0"
>
<type>
<INT/>
</type>
</variable>
<variable
name=
"Cnt1"
>
<type>
<INT/>
</type>
</variable>
</outputVars>
<localVars>
<variable
name=
"CounterST0"
>
<type>
<derived
name=
"CounterST"
/>
</type>
</variable>
</localVars>
</interface>
<body>
<FBD>
<comment
localId=
"1"
height=
"143"
width=
"201"
>
<position
x=
"566"
y=
"75"
/>
<content>
<xhtml:p>
<![CDATA[This PLC program is used in automated testing of beremiz' runtime / coupler integration]]>
</xhtml:p>
</content>
</comment>
<block
localId=
"2"
typeName=
"CounterST"
instanceName=
"CounterST0"
executionOrderId=
"0"
height=
"109"
width=
"99"
>
<position
x=
"288"
y=
"192"
/>
<inputVariables>
<variable
formalParameter=
"Reset"
>
<connectionPointIn>
<relPosition
x=
"0"
y=
"42"
/>
<connection
refLocalId=
"3"
>
<position
x=
"288"
y=
"234"
/>
<position
x=
"258"
y=
"234"
/>
<position
x=
"258"
y=
"218"
/>
<position
x=
"231"
y=
"218"
/>
</connection>
</connectionPointIn>
</variable>
</inputVariables>
<inOutVariables/>
<outputVariables>
<variable
formalParameter=
"Out1"
>
<connectionPointOut>
<relPosition
x=
"99"
y=
"42"
/>
</connectionPointOut>
</variable>
<variable
formalParameter=
"Out0"
>
<connectionPointOut>
<relPosition
x=
"99"
y=
"86"
/>
</connectionPointOut>
</variable>
</outputVariables>
</block>
<inVariable
localId=
"3"
executionOrderId=
"0"
height=
"24"
width=
"50"
negated=
"false"
>
<position
x=
"181"
y=
"206"
/>
<connectionPointOut>
<relPosition
x=
"50"
y=
"12"
/>
</connectionPointOut>
<expression>
Reset
</expression>
</inVariable>
<outVariable
localId=
"4"
executionOrderId=
"0"
height=
"24"
width=
"42"
negated=
"false"
>
<position
x=
"433"
y=
"266"
/>
<connectionPointIn>
<relPosition
x=
"0"
y=
"12"
/>
<connection
refLocalId=
"2"
formalParameter=
"Out0"
>
<position
x=
"433"
y=
"278"
/>
<position
x=
"387"
y=
"278"
/>
</connection>
</connectionPointIn>
<expression>
Cnt0
</expression>
</outVariable>
<outVariable
localId=
"6"
executionOrderId=
"0"
height=
"24"
width=
"42"
negated=
"false"
>
<position
x=
"435"
y=
"222"
/>
<connectionPointIn>
<relPosition
x=
"0"
y=
"12"
/>
<connection
refLocalId=
"2"
formalParameter=
"Out1"
>
<position
x=
"435"
y=
"234"
/>
<position
x=
"387"
y=
"234"
/>
</connection>
</connectionPointIn>
<expression>
Cnt1
</expression>
</outVariable>
</FBD>
</body>
</pou>
<pou
name=
"CounterST"
pouType=
"functionBlock"
>
<interface>
<inputVars>
<variable
name=
"Reset"
>
<type>
<BOOL/>
</type>
</variable>
</inputVars>
<outputVars>
<variable
name=
"Out1"
>
<type>
<INT/>
</type>
</variable>
<variable
name=
"Out0"
>
<type>
<INT/>
</type>
</variable>
</outputVars>
<localVars>
<variable
name=
"Cnt1"
>
<type>
<INT/>
</type>
</variable>
<variable
name=
"Cnt0"
>
<type>
<INT/>
</type>
</variable>
</localVars>
<externalVars>
<variable
name=
"ResetCounterValue"
>
<type>
<INT/>
</type>
</variable>
<variable
name=
"Relay0"
>
<type>
<DINT/>
</type>
</variable>
<variable
name=
"Relay1"
>
<type>
<DINT/>
</type>
</variable>
<variable
name=
"Relay2"
>
<type>
<DINT/>
</type>
</variable>
<variable
name=
"Relay3"
>
<type>
<DINT/>
</type>
</variable>
<variable
name=
"Relay4"
>
<type>
<DINT/>
</type>
</variable>
<variable
name=
"Relay5"
>
<type>
<DINT/>
</type>
</variable>
<variable
name=
"Relay6"
>
<type>
<DINT/>
</type>
</variable>
<variable
name=
"Relay7"
>
<type>
<DINT/>
</type>
</variable>
</externalVars>
</interface>
<body>
<ST>
<xhtml:p>
<![CDATA[Cnt1 := Cnt1 + 1;
IF Cnt1 = 100 THEN
Relay0 := Relay0 + 1;
Cnt1 := 0;
Relay7 := Relay0;
END_IF;
Out1 := Cnt1;
Out0 := Cnt0;]]>
</xhtml:p>
</ST>
</body>
</pou>
</pous>
</types>
<instances>
<configurations>
<configuration
name=
"config"
>
<resource
name=
"resource1"
>
<task
name=
"task0"
priority=
"0"
interval=
"T#20ms"
>
<pouInstance
name=
"instance0"
typeName=
"plc_prg"
/>
</task>
</resource>
<globalVars>
<variable
name=
"ResetCounterValue"
>
<type>
<INT/>
</type>
<initialValue>
<simpleValue
value=
"0"
/>
</initialValue>
</variable>
<variable
name=
"Relay0"
address=
"%QD1.0"
>
<type>
<DINT/>
</type>
<initialValue>
<simpleValue
value=
"0"
/>
</initialValue>
<documentation>
<xhtml:p>
<![CDATA[OPC-UA relay 0 at coupler 0]]>
</xhtml:p>
</documentation>
</variable>
<variable
name=
"Relay1"
address=
"%QD1.1"
>
<type>
<DINT/>
</type>
<initialValue>
<simpleValue
value=
"0"
/>
</initialValue>
<documentation>
<xhtml:p>
<![CDATA[OPC-UA relay 1 at coupler 0]]>
</xhtml:p>
</documentation>
</variable>
<variable
name=
"Relay2"
address=
"%QD1.2"
>
<type>
<DINT/>
</type>
<initialValue>
<simpleValue
value=
"0"
/>
</initialValue>
<documentation>
<xhtml:p>
<![CDATA[OPC-UA relay 2 at coupler 0]]>
</xhtml:p>
</documentation>
</variable>
<variable
name=
"Relay3"
address=
"%QD1.3"
>
<type>
<DINT/>
</type>
<initialValue>
<simpleValue
value=
"0"
/>
</initialValue>
<documentation>
<xhtml:p>
<![CDATA[OPC-UA relay 3 at coupler 0]]>
</xhtml:p>
</documentation>
</variable>
<variable
name=
"Relay4"
address=
"%QD0.0"
>
<type>
<DINT/>
</type>
<initialValue>
<simpleValue
value=
"0"
/>
</initialValue>
<documentation>
<xhtml:p>
<![CDATA[OPC-UA relay 0 at coupler 1]]>
</xhtml:p>
</documentation>
</variable>
<variable
name=
"Relay5"
address=
"%QD0.1"
>
<type>
<DINT/>
</type>
<initialValue>
<simpleValue
value=
"0"
/>
</initialValue>
<documentation>
<xhtml:p>
<![CDATA[OPC-UA relay 1 at coupler 1]]>
</xhtml:p>
</documentation>
</variable>
<variable
name=
"Relay6"
address=
"%QD0.2"
>
<type>
<DINT/>
</type>
<initialValue>
<simpleValue
value=
"0"
/>
</initialValue>
<documentation>
<xhtml:p>
<![CDATA[OPC-UA relay 2 at coupler 1]]>
</xhtml:p>
</documentation>
</variable>
<variable
name=
"Relay7"
address=
"%QD0.3"
>
<type>
<DINT/>
</type>
<initialValue>
<simpleValue
value=
"0"
/>
</initialValue>
<documentation>
<xhtml:p>
<![CDATA[OPC-UA relay 3 at coupler 1]]>
</xhtml:p>
</documentation>
</variable>
</globalVars>
</configuration>
</configurations>
</instances>
</project>
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment