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
1
Merge Requests
1
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
nexedi
osie
Commits
69802cac
Commit
69802cac
authored
Oct 25, 2021
by
Ivan Tyagov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
First cherry-picker PLC program demo / POC.
parent
1eaf9514
Changes
27
Show whitespace changes
Inline
Side-by-side
Showing
27 changed files
with
2817 additions
and
0 deletions
+2817
-0
Beremiz/cherry_picker_opc_ua_prod/beremiz.xml
Beremiz/cherry_picker_opc_ua_prod/beremiz.xml
+4
-0
Beremiz/cherry_picker_opc_ua_prod/build/LOCATED_VARIABLES.h
Beremiz/cherry_picker_opc_ua_prod/build/LOCATED_VARIABLES.h
+4
-0
Beremiz/cherry_picker_opc_ua_prod/build/POUS.c
Beremiz/cherry_picker_opc_ua_prod/build/POUS.c
+285
-0
Beremiz/cherry_picker_opc_ua_prod/build/POUS.h
Beremiz/cherry_picker_opc_ua_prod/build/POUS.h
+143
-0
Beremiz/cherry_picker_opc_ua_prod/build/VARIABLES.csv
Beremiz/cherry_picker_opc_ua_prod/build/VARIABLES.csv
+30
-0
Beremiz/cherry_picker_opc_ua_prod/build/beremiz.h
Beremiz/cherry_picker_opc_ua_prod/build/beremiz.h
+35
-0
Beremiz/cherry_picker_opc_ua_prod/build/cherry_picker_opc_ua_prod.so
...rry_picker_opc_ua_prod/build/cherry_picker_opc_ua_prod.so
+0
-0
Beremiz/cherry_picker_opc_ua_prod/build/config.c
Beremiz/cherry_picker_opc_ua_prod/build/config.c
+46
-0
Beremiz/cherry_picker_opc_ua_prod/build/config.h
Beremiz/cherry_picker_opc_ua_prod/build/config.h
+7
-0
Beremiz/cherry_picker_opc_ua_prod/build/config.o
Beremiz/cherry_picker_opc_ua_prod/build/config.o
+0
-0
Beremiz/cherry_picker_opc_ua_prod/build/generated_plc.st
Beremiz/cherry_picker_opc_ua_prod/build/generated_plc.st
+76
-0
Beremiz/cherry_picker_opc_ua_prod/build/lastbuildPLC.md5
Beremiz/cherry_picker_opc_ua_prod/build/lastbuildPLC.md5
+1
-0
Beremiz/cherry_picker_opc_ua_prod/build/opcua_client__1.c
Beremiz/cherry_picker_opc_ua_prod/build/opcua_client__1.c
+107
-0
Beremiz/cherry_picker_opc_ua_prod/build/opcua_client__1.o
Beremiz/cherry_picker_opc_ua_prod/build/opcua_client__1.o
+0
-0
Beremiz/cherry_picker_opc_ua_prod/build/plc.st
Beremiz/cherry_picker_opc_ua_prod/build/plc.st
+170
-0
Beremiz/cherry_picker_opc_ua_prod/build/plc_debugger.c
Beremiz/cherry_picker_opc_ua_prod/build/plc_debugger.c
+415
-0
Beremiz/cherry_picker_opc_ua_prod/build/plc_debugger.o
Beremiz/cherry_picker_opc_ua_prod/build/plc_debugger.o
+0
-0
Beremiz/cherry_picker_opc_ua_prod/build/plc_main.c
Beremiz/cherry_picker_opc_ua_prod/build/plc_main.c
+951
-0
Beremiz/cherry_picker_opc_ua_prod/build/plc_main.o
Beremiz/cherry_picker_opc_ua_prod/build/plc_main.o
+0
-0
Beremiz/cherry_picker_opc_ua_prod/build/py_ext.c
Beremiz/cherry_picker_opc_ua_prod/build/py_ext.c
+221
-0
Beremiz/cherry_picker_opc_ua_prod/build/py_ext.o
Beremiz/cherry_picker_opc_ua_prod/build/py_ext.o
+0
-0
Beremiz/cherry_picker_opc_ua_prod/build/resource1.c
Beremiz/cherry_picker_opc_ua_prod/build/resource1.c
+37
-0
Beremiz/cherry_picker_opc_ua_prod/build/resource1.o
Beremiz/cherry_picker_opc_ua_prod/build/resource1.o
+0
-0
Beremiz/cherry_picker_opc_ua_prod/opcua_0@opcua/baseconfnode.xml
.../cherry_picker_opc_ua_prod/opcua_0@opcua/baseconfnode.xml
+2
-0
Beremiz/cherry_picker_opc_ua_prod/opcua_0@opcua/confnode.xml
Beremiz/cherry_picker_opc_ua_prod/opcua_0@opcua/confnode.xml
+2
-0
Beremiz/cherry_picker_opc_ua_prod/opcua_0@opcua/selected.csv
Beremiz/cherry_picker_opc_ua_prod/opcua_0@opcua/selected.csv
+8
-0
Beremiz/cherry_picker_opc_ua_prod/plc.xml
Beremiz/cherry_picker_opc_ua_prod/plc.xml
+273
-0
No files found.
Beremiz/cherry_picker_opc_ua_prod/beremiz.xml
0 → 100644
View file @
69802cac
<?xml version='1.0' encoding='utf-8'?>
<BeremizRoot
xmlns:xsd=
"http://www.w3.org/2001/XMLSchema"
URI_location=
"LOCAL://"
>
<TargetType/>
</BeremizRoot>
Beremiz/cherry_picker_opc_ua_prod/build/LOCATED_VARIABLES.h
0 → 100644
View file @
69802cac
__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
)
Beremiz/cherry_picker_opc_ua_prod/build/POUS.c
0 → 100644
View file @
69802cac
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
)
}
// 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
if
(
__GET_VAR
(
data__
->
RESET
,))
{
__SET_VAR
(
data__
->
,
CNT0
,,
__GET_EXTERNAL
(
data__
->
RESETCOUNTERVALUE
,));
__SET_VAR
(
data__
->
,
CNT1
,,
__GET_EXTERNAL
(
data__
->
RESETCOUNTERVALUE
,));
__SET_VAR
(
data__
->
,
RESET
,,
__BOOL_LITERAL
(
FALSE
));
}
else
{
__SET_VAR
(
data__
->
,
CNT0
,,(
__GET_VAR
(
data__
->
CNT0
,)
+
1
));
__SET_VAR
(
data__
->
,
CNT1
,,(
__GET_VAR
(
data__
->
CNT1
,)
+
1
));
if
((
__GET_VAR
(
data__
->
CNT1
,)
==
50
))
{
__SET_EXTERNAL
(
data__
->
,
RELAY0
,,
1
);
__SET_EXTERNAL
(
data__
->
,
RELAY1
,,
1
);
};
if
((
__GET_VAR
(
data__
->
CNT1
,)
==
100
))
{
__SET_EXTERNAL
(
data__
->
,
RELAY0
,,
1
);
__SET_EXTERNAL
(
data__
->
,
RELAY1
,,
0
);
__SET_VAR
(
data__
->
,
CNT1
,,
0
);
};
};
__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__()
Beremiz/cherry_picker_opc_ua_prod/build/POUS.h
0 → 100644
View file @
69802cac
#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
)
}
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
Beremiz/cherry_picker_opc_ua_prod/build/VARIABLES.csv
0 → 100644
View file @
69802cac
// 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;FB;CONFIG.RESOURCE1.INSTANCE0;CONFIG.RESOURCE1.INSTANCE0;PLC_PRG;;
6;VAR;CONFIG.RESOURCE1.INSTANCE0.RESET;CONFIG.RESOURCE1.INSTANCE0.RESET;BOOL;BOOL;
7;VAR;CONFIG.RESOURCE1.INSTANCE0.CNT0;CONFIG.RESOURCE1.INSTANCE0.CNT0;INT;INT;
8;VAR;CONFIG.RESOURCE1.INSTANCE0.CNT1;CONFIG.RESOURCE1.INSTANCE0.CNT1;INT;INT;
9;FB;CONFIG.RESOURCE1.INSTANCE0.COUNTERST0;CONFIG.RESOURCE1.INSTANCE0.COUNTERST0;COUNTERST;;
10;VAR;CONFIG.RESOURCE1.INSTANCE0.COUNTERST0.EN;CONFIG.RESOURCE1.INSTANCE0.COUNTERST0.EN;BOOL;BOOL;
11;VAR;CONFIG.RESOURCE1.INSTANCE0.COUNTERST0.ENO;CONFIG.RESOURCE1.INSTANCE0.COUNTERST0.ENO;BOOL;BOOL;
12;VAR;CONFIG.RESOURCE1.INSTANCE0.COUNTERST0.RESET;CONFIG.RESOURCE1.INSTANCE0.COUNTERST0.RESET;BOOL;BOOL;
13;VAR;CONFIG.RESOURCE1.INSTANCE0.COUNTERST0.OUT1;CONFIG.RESOURCE1.INSTANCE0.COUNTERST0.OUT1;INT;INT;
14;VAR;CONFIG.RESOURCE1.INSTANCE0.COUNTERST0.OUT0;CONFIG.RESOURCE1.INSTANCE0.COUNTERST0.OUT0;INT;INT;
15;VAR;CONFIG.RESOURCE1.INSTANCE0.COUNTERST0.CNT1;CONFIG.RESOURCE1.INSTANCE0.COUNTERST0.CNT1;INT;INT;
16;VAR;CONFIG.RESOURCE1.INSTANCE0.COUNTERST0.CNT0;CONFIG.RESOURCE1.INSTANCE0.COUNTERST0.CNT0;INT;INT;
17;EXT;CONFIG.RESOURCE1.INSTANCE0.COUNTERST0.RESETCOUNTERVALUE;CONFIG.RESOURCE1.INSTANCE0.COUNTERST0.RESETCOUNTERVALUE;INT;INT;
18;EXT;CONFIG.RESOURCE1.INSTANCE0.COUNTERST0.RELAY0;CONFIG.RESOURCE1.INSTANCE0.COUNTERST0.RELAY0;DINT;DINT;
19;EXT;CONFIG.RESOURCE1.INSTANCE0.COUNTERST0.RELAY1;CONFIG.RESOURCE1.INSTANCE0.COUNTERST0.RELAY1;DINT;DINT;
20;EXT;CONFIG.RESOURCE1.INSTANCE0.COUNTERST0.RELAY2;CONFIG.RESOURCE1.INSTANCE0.COUNTERST0.RELAY2;DINT;DINT;
21;EXT;CONFIG.RESOURCE1.INSTANCE0.COUNTERST0.RELAY3;CONFIG.RESOURCE1.INSTANCE0.COUNTERST0.RELAY3;DINT;DINT;
// Ticktime
20000000
Beremiz/cherry_picker_opc_ua_prod/build/beremiz.h
0 → 100644
View file @
69802cac
#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
Beremiz/cherry_picker_opc_ua_prod/build/cherry_picker_opc_ua_prod.so
0 → 100755
View file @
69802cac
File added
Beremiz/cherry_picker_opc_ua_prod/build/config.c
0 → 100644
View file @
69802cac
/*******************************************/
/* 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
)
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
)
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*/
Beremiz/cherry_picker_opc_ua_prod/build/config.h
0 → 100644
View file @
69802cac
#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
)
Beremiz/cherry_picker_opc_ua_prod/build/config.o
0 → 100644
View file @
69802cac
File added
Beremiz/cherry_picker_opc_ua_prod/build/generated_plc.st
0 → 100644
View file @
69802cac
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
;
END_VAR
IF
Reset
THEN
Cnt0
:=
ResetCounterValue
;
Cnt1
:=
ResetCounterValue
;
Reset
:=
False
;
ELSE
Cnt0
:=
Cnt0
+
1
;
Cnt1
:=
Cnt1
+
1
;
IF
Cnt1
=
50
THEN
Relay0
:=
1
;
Relay1
:=
1
;
END_IF
;
IF
Cnt1
=
100
THEN
Relay0
:=
1
;
Relay1
:=
0
;
Cnt1
:=
0
;
END_IF
;
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
;
END_VAR
RESOURCE
resource1
ON
PLC
TASK
task0
(
INTERVAL
:=
T
#20ms
,
PRIORITY
:=
0
);
PROGRAM
instance0
WITH
task0
:
plc_prg
;
END_RESOURCE
END_CONFIGURATION
Beremiz/cherry_picker_opc_ua_prod/build/lastbuildPLC.md5
0 → 100644
View file @
69802cac
5872cdee1c8e83c0f2e6225bddbac9ab
\ No newline at end of file
Beremiz/cherry_picker_opc_ua_prod/build/opcua_client__1.c
0 → 100644
View file @
69802cac
/* 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
,
__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
)
#define FREE_VARIANT(ua_type, c_loc_name) \
UA_Variant_delete(c_loc_name##_variant);
void
__cleanup_1
(
void
)
{
UA_Client_disconnect
(
client
);
UA_Client_delete
(
client
);
FREE_VARIANT
(
UA_Int32
,
__ID1_0
)
FREE_VARIANT
(
UA_Int32
,
__ID1_1
)
FREE_VARIANT
(
UA_Int32
,
__ID1_2
)
FREE_VARIANT
(
UA_Int32
,
__ID1_3
)
FREE_VARIANT
(
UA_Int32
,
__QD1_0
)
FREE_VARIANT
(
UA_Int32
,
__QD1_1
)
FREE_VARIANT
(
UA_Int32
,
__QD1_2
)
FREE_VARIANT
(
UA_Int32
,
__QD1_3
)
}
#define ALLOC_VARIANT(ua_type, c_loc_name) \
c_loc_name##_variant = UA_Variant_new();
int
__init_1
(
int
argc
,
char
**
argv
)
{
UA_StatusCode
retval
;
client
=
UA_Client_new
();
UA_ClientConfig_setDefault
(
UA_Client_getConfig
(
client
));
ALLOC_VARIANT
(
UA_Int32
,
__ID1_0
)
ALLOC_VARIANT
(
UA_Int32
,
__ID1_1
)
ALLOC_VARIANT
(
UA_Int32
,
__ID1_2
)
ALLOC_VARIANT
(
UA_Int32
,
__ID1_3
)
ALLOC_VARIANT
(
UA_Int32
,
__QD1_0
)
ALLOC_VARIANT
(
UA_Int32
,
__QD1_1
)
ALLOC_VARIANT
(
UA_Int32
,
__QD1_2
)
ALLOC_VARIANT
(
UA_Int32
,
__QD1_3
)
/* Connect to server */
retval
=
UA_Client_connect
(
client
,
"opc.tcp://192.168.0.114: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; \
}
void
__retrieve_1
(
void
)
{
UA_StatusCode
retval
;
READ_VALUE
(
UA_Int32
,
UA_TYPES_INT32
,
__ID1_0
,
UA_NODEID_STRING
,
1
,
"relay0"
)
READ_VALUE
(
UA_Int32
,
UA_TYPES_INT32
,
__ID1_1
,
UA_NODEID_STRING
,
1
,
"relay1"
)
READ_VALUE
(
UA_Int32
,
UA_TYPES_INT32
,
__ID1_2
,
UA_NODEID_STRING
,
1
,
"relay2"
)
READ_VALUE
(
UA_Int32
,
UA_TYPES_INT32
,
__ID1_3
,
UA_NODEID_STRING
,
1
,
"relay3"
)
READ_VALUE
(
UA_Int32
,
UA_TYPES_INT32
,
__QD1_0
,
UA_NODEID_STRING
,
1
,
"relay0"
)
READ_VALUE
(
UA_Int32
,
UA_TYPES_INT32
,
__QD1_1
,
UA_NODEID_STRING
,
1
,
"relay1"
)
READ_VALUE
(
UA_Int32
,
UA_TYPES_INT32
,
__QD1_2
,
UA_NODEID_STRING
,
1
,
"relay2"
)
READ_VALUE
(
UA_Int32
,
UA_TYPES_INT32
,
__QD1_3
,
UA_NODEID_STRING
,
1
,
"relay3"
)
}
#define WRITE_VALUE(ua_type, ua_type_enum, c_loc_name, ua_nodeid_type, ua_nsidx, ua_node_id) \
UA_Variant_setScalarCopy(c_loc_name##_variant, (ua_type*)c_loc_name, &UA_TYPES[ua_type_enum]); \
UA_Client_writeValueAttribute(client, ua_nodeid_type(ua_nsidx, ua_node_id), c_loc_name##_variant);
void
__publish_1
(
void
)
{
WRITE_VALUE
(
UA_Int32
,
UA_TYPES_INT32
,
__ID1_0
,
UA_NODEID_STRING
,
1
,
"relay0"
)
WRITE_VALUE
(
UA_Int32
,
UA_TYPES_INT32
,
__ID1_1
,
UA_NODEID_STRING
,
1
,
"relay1"
)
WRITE_VALUE
(
UA_Int32
,
UA_TYPES_INT32
,
__ID1_2
,
UA_NODEID_STRING
,
1
,
"relay2"
)
WRITE_VALUE
(
UA_Int32
,
UA_TYPES_INT32
,
__ID1_3
,
UA_NODEID_STRING
,
1
,
"relay3"
)
WRITE_VALUE
(
UA_Int32
,
UA_TYPES_INT32
,
__QD1_0
,
UA_NODEID_STRING
,
1
,
"relay0"
)
WRITE_VALUE
(
UA_Int32
,
UA_TYPES_INT32
,
__QD1_1
,
UA_NODEID_STRING
,
1
,
"relay1"
)
WRITE_VALUE
(
UA_Int32
,
UA_TYPES_INT32
,
__QD1_2
,
UA_NODEID_STRING
,
1
,
"relay2"
)
WRITE_VALUE
(
UA_Int32
,
UA_TYPES_INT32
,
__QD1_3
,
UA_NODEID_STRING
,
1
,
"relay3"
)
}
Beremiz/cherry_picker_opc_ua_prod/build/opcua_client__1.o
0 → 100644
View file @
69802cac
File added
Beremiz/cherry_picker_opc_ua_prod/build/plc.st
0 → 100644
View file @
69802cac
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
;
END_VAR
IF
Reset
THEN
Cnt0
:=
ResetCounterValue
;
Cnt1
:=
ResetCounterValue
;
Reset
:=
False
;
ELSE
Cnt0
:=
Cnt0
+
1
;
Cnt1
:=
Cnt1
+
1
;
IF
Cnt1
=
50
THEN
Relay0
:=
1
;
Relay1
:=
1
;
END_IF
;
IF
Cnt1
=
100
THEN
Relay0
:=
1
;
Relay1
:=
0
;
Cnt1
:=
0
;
END_IF
;
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
;
END_VAR
RESOURCE
resource1
ON
PLC
TASK
task0
(
INTERVAL
:=
T
#20ms
,
PRIORITY
:=
0
);
PROGRAM
instance0
WITH
task0
:
plc_prg
;
END_RESOURCE
END_CONFIGURATION
Beremiz/cherry_picker_opc_ua_prod/build/plc_debugger.c
0 → 100644
View file @
69802cac
/*
* 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 52
/* 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
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
},
{
&
(
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
}
};
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
Beremiz/cherry_picker_opc_ua_prod/build/plc_debugger.o
0 → 100644
View file @
69802cac
File added
Beremiz/cherry_picker_opc_ua_prod/build/plc_main.c
0 → 100644
View file @
69802cac
/**
* 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_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_1
();
/*__retrieve_debug();*/
config_run__
(
__tick
);
__publish_debug
();
__publish_1
();
__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_1
(
argc
,
argv
))){
return
res
;}
return
res
;
}
/*
* Calls plugin cleanup proc.
**/
void
__cleanup
(
void
)
{
if
(
init_level
>=
2
)
__cleanup_1
();
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
Beremiz/cherry_picker_opc_ua_prod/build/plc_main.o
0 → 100644
View file @
69802cac
File added
Beremiz/cherry_picker_opc_ua_prod/build/py_ext.c
0 → 100644
View file @
69802cac
/*
* 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
;
}
Beremiz/cherry_picker_opc_ua_prod/build/py_ext.o
0 → 100644
View file @
69802cac
File added
Beremiz/cherry_picker_opc_ua_prod/build/resource1.c
0 → 100644
View file @
69802cac
/*******************************************/
/* 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
);
}
}
Beremiz/cherry_picker_opc_ua_prod/build/resource1.o
0 → 100644
View file @
69802cac
File added
Beremiz/cherry_picker_opc_ua_prod/opcua_0@opcua/baseconfnode.xml
0 → 100644
View file @
69802cac
<?xml version='1.0' encoding='utf-8'?>
<BaseParams
xmlns:xsd=
"http://www.w3.org/2001/XMLSchema"
IEC_Channel=
"1"
Name=
"opcua_0"
/>
Beremiz/cherry_picker_opc_ua_prod/opcua_0@opcua/confnode.xml
0 → 100644
View file @
69802cac
<?xml version='1.0' encoding='utf-8'?>
<OPCUAClient
xmlns:xsd=
"http://www.w3.org/2001/XMLSchema"
Server_URI=
"opc.tcp://192.168.0.114:4840"
/>
Beremiz/cherry_picker_opc_ua_prod/opcua_0@opcua/selected.csv
0 → 100644
View file @
69802cac
input,"LocalizedText(Encoding:3, Locale:en-US, Text:Relay 0)",1,str,relay0,Int32,0
input,"LocalizedText(Encoding:3, Locale:en-US, Text:Relay 1)",1,str,relay1,Int32,1
input,"LocalizedText(Encoding:3, Locale:en-US, Text:Relay 2)",1,str,relay2,Int32,2
input,"LocalizedText(Encoding:3, Locale:en-US, Text:Relay 3)",1,str,relay3,Int32,3
output,"LocalizedText(Encoding:3, Locale:en-US, Text:Relay 0)",1,str,relay0,Int32,0
output,"LocalizedText(Encoding:3, Locale:en-US, Text:Relay 1)",1,str,relay1,Int32,1
output,"LocalizedText(Encoding:3, Locale:en-US, Text:Relay 2)",1,str,relay2,Int32,2
output,"LocalizedText(Encoding:3, Locale:en-US, Text:Relay 3)",1,str,relay3,Int32,3
Beremiz/cherry_picker_opc_ua_prod/plc.xml
0 → 100644
View file @
69802cac
<?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=
"2021-10-25T16:19:46"
>
<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[Test Ivan: this PLC will switch ON / OFF attached over modbus relays {0..3} of a Lime2 coupler.]]>
</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>
</externalVars>
</interface>
<body>
<ST>
<xhtml:p>
<![CDATA[IF Reset THEN
Cnt0 := ResetCounterValue;
Cnt1 := ResetCounterValue;
Reset := False;
ELSE
Cnt0 := Cnt0 + 1;
Cnt1 := Cnt1 + 1;
IF Cnt1 = 50 THEN
Relay0 := 1;
Relay1 := 1;
END_IF;
IF Cnt1 = 100 THEN
Relay0 := 1;
Relay1 := 0;
Cnt1 := 0;
END_IF;
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]]>
</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]]>
</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]]>
</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 2]]>
</xhtml:p>
</documentation>
</variable>
</globalVars>
</configuration>
</configurations>
</instances>
</project>
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