- 在顺序功能图(SFC)的代码中,data__->STEP0.X中的X表示步骤STEP0的当前状态(激活或者未激活)
- 整体结构:
- PROGRAM0_init__函数对SFC进行初始化,包括步数量、动作数量、时间等
- 定义步进START, STEP0, STEP1, STEP2
- 定义动作ACTION0
- 在PROGRAM0_body__函数中计算经过时间,初始化步和动作
- 计算步进BOOL_A和BOOL_B的状态,用于转移条件
- 生成STEP0的动作关联逻辑
- 计算动作的状态变化
- 执行动作ACTION0,递增CNT变量
- 根据转移状态复位相应步进
- 根据转移状态设置相应步进
- data__->STEP0.T.value 是STEP0的计时器T的值,表示STEP0已经经过的时间
- __time_to_timespec(1, 0, 2, 0, 0, 0)将时间转换为时间规格结构体,这里表示2秒
- __time_cmp是时间比较函数,比较两个时间规格的值。>= 0表示STEP0.T.value大于等于2秒
执行流程图
// Calculate elapsed_time
current_time = __CURRENT_TIME;
elapsed_time = __time_sub(current_time, data__->__lasttick_time);
data__->__lasttick_time = current_time;
// Steps initialization
for (i = 0; i < data__->__nb_steps; i++) {
data__->__step_list[i].prev_state = __GET_VAR(data__->__step_list[i].X);
if (__GET_VAR(data__->__step_list[i].X)) {
data__->__step_list[i].T.value = __time_add(data__->__step_list[i].T.value, elapsed_time);
}
}
// Actions initialization
__SET_VAR(data__->,__action_list[i].state,,0);
// Transitions fire test
if (__GET_VAR(data__->START.X)) {
__SET_VAR(data__->,__transition_list[0],,__GET_VAR(data__->BOOL_A,))
}
__SET_VAR(data__->,__transition_list[1],,0);
__SET_VAR(data__->,__transition_list[2],,0);
__SET_VAR(data__->,__transition_list[3],,0);
// Transitions reset steps
if (__GET_VAR(data__->__transition_list[0])) {
__SET_VAR(data__->,START.X,,0);
// Transitions set steps
if (__GET_VAR(data__->__transition_list[0])) {
__SET_VAR(data__->,STEP0.X,,1);
data__->STEP0.T.value = __time_to_timespec(1, 0, 0, 0, 0, 0);
}
// Steps association
// STEP0 action associations
{
char active = __GET_VAR(data__->STEP0.X);
char activated = active && !data__->STEP0.prev_state;
char desactivated = !active && data__->STEP0.prev_state;
if (active && __time_cmp(data__->STEP0.T.value, __time_to_timespec(1, 0, 2, 0, 0, 0)) >= 0)
{__SET_VAR(data__->,__action_list[__SFC_ACTION0].state,,1);}
else if (desactivated)
{__SET_VAR(data__->,__action_list[__SFC_ACTION0].state,,0);};
}
// Actions state evaluation
__SET_VAR(data__->,__action_list[i].state,,__GET_VAR(data__->__action_list[i].state) | data__->__action_list[i].stored);
// Actions execution
if(__GET_VAR(data__->__action_list[__SFC_ACTION0].state)) {
__SET_VAR(data__->,CNT,,(__GET_VAR(data__->CNT,) + 1));
}
OpenPLC执行步骤
- 设置每个step的前一步状态和当前激活的step对应的时间T
- 设置action的状态为FALSE
- 获取当前激活的step对应的transition
- 如果transition为TRUE则设置当前激活的step为FALSE,设置下一step状态为TRUE并且时间T为0
- 根据当前step的状态(激活,上升沿,下降沿)决定action的状态
- 如果action状态为TRUE,则执行action对应的操作
修改后的执行步骤
- 设置当前激活的step对应的时间T
- 设置action的状态为FALSE
- 根据当前step的状态(激活,上升沿,下降沿)决定action的状态
- 如果action状态为TRUE,则执行action对应的操作
- 获取当前激活的step对应的transition
- 如果transition为TRUE则记录step状态转换前每个step的状态,然后设置当前激活的step为FALSE,设置下一step状态为TRUE并且重置时间T为0
S限定符和R限定符
// Calculate elapsed_time
current_time = __CURRENT_TIME;
elapsed_time = __time_sub(current_time, data__->__lasttick_time);
data__->__lasttick_time = current_time;
// Steps initialization
for (i = 0; i < data__->__nb_steps; i++) {
data__->__step_list[i].prev_state = __GET_VAR(data__->__step_list[i].X);
if (__GET_VAR(data__->__step_list[i].X)) {
data__->__step_list[i].T.value = __time_add(data__->__step_list[i].T.value, elapsed_time);
}
}
// Actions initialization
for (i = 0; i < data__->__nb_actions; i++) {
__SET_VAR(data__->,__action_list[i].state,,0);
data__->__action_list[i].set = 0;
data__->__action_list[i].reset = 0;
if (__time_cmp(data__->__action_list[i].set_remaining_time, __time_to_timespec(1, 0, 0, 0, 0, 0)) > 0) {
data__->__action_list[i].set_remaining_time = __time_sub(data__->__action_list[i].set_remaining_time, elapsed_time);
if (__time_cmp(data__->__action_list[i].set_remaining_time, __time_to_timespec(1, 0, 0, 0, 0, 0)) <= 0) {
data__->__action_list[i].set_remaining_time = __time_to_timespec(1, 0, 0, 0, 0, 0);
data__->__action_list[i].set = 1;
}
}
if (__time_cmp(data__->__action_list[i].reset_remaining_time, __time_to_timespec(1, 0, 0, 0, 0, 0)) > 0) {
data__->__action_list[i].reset_remaining_time = __time_sub(data__->__action_list[i].reset_remaining_time, elapsed_time);
if (__time_cmp(data__->__action_list[i].reset_remaining_time, __time_to_timespec(1, 0, 0, 0, 0, 0)) <= 0) {
data__->__action_list[i].reset_remaining_time = __time_to_timespec(1, 0, 0, 0, 0, 0);
data__->__action_list[i].reset = 1;
}
}
}
// Transitions fire test
if (__GET_VAR(data__->INIT.X)) {
__SET_VAR(data__->,__transition_list[0],,__BOOL_LITERAL(TRUE));
}
else {
__SET_VAR(data__->,__transition_list[0],,0);
}
if (__GET_VAR(data__->STEP0.X)) {
__SET_VAR(data__->,__transition_list[1],,__BOOL_LITERAL(TRUE));
}
else {
__SET_VAR(data__->,__transition_list[1],,0);
}
if (__GET_VAR(data__->STEP1.X)) {
__SET_VAR(data__->,__transition_list[2],,__BOOL_LITERAL(TRUE));
}
else {
__SET_VAR(data__->,__transition_list[2],,0);
}
if (__GET_VAR(data__->STEP2.X)) {
__SET_VAR(data__->,__transition_list[3],,__BOOL_LITERAL(TRUE));
}
else {
__SET_VAR(data__->,__transition_list[3],,0);
}
// Transitions reset steps
if (__GET_VAR(data__->__transition_list[0])) {
__SET_VAR(data__->,INIT.X,,0);
}
if (__GET_VAR(data__->__transition_list[1])) {
__SET_VAR(data__->,STEP0.X,,0);
}
if (__GET_VAR(data__->__transition_list[2])) {
__SET_VAR(data__->,STEP1.X,,0);
}
if (__GET_VAR(data__->__transition_list[3])) {
__SET_VAR(data__->,STEP2.X,,0);
}
// Transitions set steps
if (__GET_VAR(data__->__transition_list[0])) {
__SET_VAR(data__->,STEP0.X,,1);
data__->STEP0.T.value = __time_to_timespec(1, 0, 0, 0, 0, 0);
}
if (__GET_VAR(data__->__transition_list[1])) {
__SET_VAR(data__->,STEP1.X,,1);
data__->STEP1.T.value = __time_to_timespec(1, 0, 0, 0, 0, 0);
}
if (__GET_VAR(data__->__transition_list[2])) {
__SET_VAR(data__->,STEP2.X,,1);
data__->STEP2.T.value = __time_to_timespec(1, 0, 0, 0, 0, 0);
}
if (__GET_VAR(data__->__transition_list[3])) {
__SET_VAR(data__->,INIT.X,,1);
data__->INIT.T.value = __time_to_timespec(1, 0, 0, 0, 0, 0);
}
// Steps association
// STEP0 action associations
{
char active = __GET_VAR(data__->STEP0.X);
char activated = active && !data__->STEP0.prev_state;
char desactivated = !active && data__->STEP0.prev_state;
if (activated) {
data__->__action_list[__SFC_ACTION0].set = 1;
data__->__action_list[__SFC_ACTION0].reset_remaining_time = __time_to_timespec(1, 0, 12, 0, 0, 0);
}
}
// STEP1 action associations
{
char active = __GET_VAR(data__->STEP1.X);
char activated = active && !data__->STEP1.prev_state;
char desactivated = !active && data__->STEP1.prev_state;
if (active) {data__->__action_list[__SFC_ACTION0].reset = 1;}
}
// Actions state evaluation
for (i = 0; i < data__->__nb_actions; i++) {
if (data__->__action_list[i].set) {
data__->__action_list[i].set_remaining_time = __time_to_timespec(1, 0, 0, 0, 0, 0);
data__->__action_list[i].stored = 1;
}
if (data__->__action_list[i].reset) {
data__->__action_list[i].reset_remaining_time = __time_to_timespec(1, 0, 0, 0, 0, 0);
data__->__action_list[i].stored = 0;
}
__SET_VAR(data__->,__action_list[i].state,,__GET_VAR(data__->__action_list[i].state) | data__->__action_list[i].stored);
}
// Actions execution
if(__GET_VAR(data__->__action_list[__SFC_ACTION0].state)) {
__SET_VAR(data__->,A,,(__GET_VAR(data__->A,) + 1));
}
goto __end;
__end:
return;
} // PROGRAM0_body__()
主要程序
重点解释
- 当set_remaining_time减为0时,会设置动作的激活标志set=1。
- 当reset_remaining_time减为0时,会设置动作的禁用标志reset=1。
- stored就是动作被激活或者禁用的标志
- state是状态变量,通过将原来的值与stored做位或运算来更新状态
错误实例
- SL限定符启动的action和R限定符终止的action名称不同,将导致R限定符失效