Files
coder_stm32f1/source/task/process.c

599 lines
12 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "board.h"
#include "rtthread.h"
#include "debug.h"
#include "string.h"
#include "dev_flash.h"
#include "prot_uc.h"
#include "input.h"
#include "mystdlib.h"
#include "transmit.h"
#include "mymisc.h"
#include "process.h"
#include "tran_for_coder2ch.h"
#include "coder_judge.h"
/*
赋码操作流程控制
*/
// 定义输入通道别名
#define INPUT_STOP_KEY 0
#define INPUT_CHECK_KEY 1
#define INPUT_MARK_END 2
#define INPUT_POS_LEFT 6
#define INPUT_POS_RIGHT 7
// 调试用输入通道别名
//#define INPUT_STOP_KEY 0
//#define INPUT_CHECK_KEY 1
//#define INPUT_MARK_END 2
//#define INPUT_POS_LEFT 3
//#define INPUT_POS_RIGHT 4
// 定义输出通道别名
#define OUTPUT_PUSH_CYLINDER 0
#define OUTPUT_SHELL_BAFFLE 1
#define OUTPUT_CLAMP_CYLINDER 2
#define OUTPUT_LED_OK 3
#define OUTPUT_LED_ERR 4
#define OUTPUT_MARK 9
// 定义总线选择
#define BUS_SELECT_LEFT 0
#define BUS_SELECT_RIGHT 1
// 定义推料气缸方向
#define PUSH_DIR_TO_RIGHT 1
#define PUSH_DIR_TO_LEFT 0
// 定义输出通道数量
#define OUTPUT_CHANNEL_NUM 10
// 急停时不动作
#define SAFE_CHECK(s)\
if(s->stop_state) return
// 设置当前步骤
#define SET_STEP(s,d)\
if(s/right_idle){s=right_##d;}else{s=left_##d;}
// 校验当前步骤是返回1不是返回0
#define CHECK_STEP(s,d)\
(s/right_idle)?(s==right_##d):(s==left_##d)
// 获取到位传感器通道
#define GET_POS_CHANNEL(s) \
(s/right_idle)?INPUT_POS_RIGHT:INPUT_POS_LEFT
// 获取当前使用的总线
#define GET_BUS_CHANNEL(s)\
(s/right_idle)?BUS_SELECT_RIGHT:BUS_SELECT_LEFT
// 获取当前推料气缸的方向
#define GET_PUSH_DIR(s)\
(s/right_idle)?PUSH_DIR_TO_LEFT:PUSH_DIR_TO_RIGHT
// 重置状态
#define RESET_STEP(s)\
if(s<right_idle){s=right_idle;}else{s=left_idle;}
// 设置指示灯状态
#define SET_LED_OK()\
{output_set(&s->output[OUTPUT_LED_ERR],0);\
output_set(&s->output[OUTPUT_LED_OK],1);}
#define SET_LED_ERR()\
{output_set(&s->output[OUTPUT_LED_ERR],1);\
output_set(&s->output[OUTPUT_LED_OK],0);}
#define SET_LED_OFF()\
{output_set(&s->output[OUTPUT_LED_ERR],0);\
output_set(&s->output[OUTPUT_LED_OK],0);}
// 设置输出通道状态
#define SET_OUTPUT(c,p)\
output_set(&s->output[c],p);
// 复位输出状态
#define RESET_OUTPUT()\
{output_set(&s->output[OUTPUT_SHELL_BAFFLE],0);\
output_set(&s->output[OUTPUT_CLAMP_CYLINDER],0);\
output_set(&s->output[OUTPUT_MARK],0);}
// 设置异常报警次数
#define SET_ERR_TIMES(t)\
{if(s->lederr_times>0){\
s->lederr_times=t;\
}else{\
s->lederr_times=t;\
later_execute(process_err,s,500);}\
}
typedef struct{
gpioout_def *dev;
int state;
}output_def;
// 设置输出状态
static int output_set(output_def *s,int state)
{
s->dev->set(s->dev,state);
s->state=state;
return 0;
}
typedef enum{
left_idle=0,
left_push,
left_requst,
left_code,
right_idle,
right_push,
right_requst,
right_code,
}process_step;
typedef struct{
int inited;
int run;
void *tran;
array_def *code_data;// 赋码数据
rt_timer_t timer;
int lederr_times;// 异常闪烁次数
int busy;// 忙,此时不再响应启动按键
process_step step;// 流程步数0为空闲
int stop_state;// 急停标志值1时不运行
output_def output[OUTPUT_CHANNEL_NUM];
output_def led;
output_def mod1_use;
output_def bus_sel;
output_def mod_sel;
}self_def;
static self_def g_self;
static const char *g_errinfo_table[]={
"",
"左侧到位检测失败",
"左侧请求三码数据失败",
"左侧赋码失败",
"",
"右侧到位检测失败",
"右侧请求三码数据失败",
"右侧赋码失败",
};
//static const char *g_errinfo_table[]={
// "",
// "left pos check failed",
// "left 3code request failed",
// "left code failed",
// "",
// "right pos check failed",
// "right 3code request failed",
// "right code failed",
//};
// 异常报警
static void process_err(void *arg)
{
self_def *s=arg;
if(s->lederr_times%2==1)
{
SET_LED_ERR();
}else{
SET_LED_OFF();
}
if(s->lederr_times>0){
s->lederr_times--;
later_execute(process_err,s,500);
}
}
// 急停按钮响应函数
static void process_stop(void *arg)
{
self_def *s=arg;
s->stop_state=1;
// 管壳挡板0是挡住
SET_OUTPUT(OUTPUT_SHELL_BAFFLE,0);
SET_ERR_TIMES(3);
DBG_LOG("stop key pressed.");
}
static void process_run(void *arg)
{
self_def *s=arg;
s->stop_state=0;
s->busy=0;
SET_LED_OFF();
DBG_LOG("stop key unpressed.");
}
// 异常上报函数
static void process_send_errinfo(void *arg)
{
self_def *s=arg;
const char *err_info=g_errinfo_table[s->step];
int errlen=strlen(err_info);
array_def *a=arr_creat();
arr_append(a,s->step);
arr_appends(a,err_info,errlen);
process_send_signal(s,0x8c,arr_temp(a));
}
// 超时响应函数
static void process_timeout(void *arg)
{
self_def *s=arg;
SAFE_CHECK(s);
// 上报异常信息
process_send_errinfo(s);
DBG_WARN("timeout,errcode=%d",s->step);
if(CHECK_STEP(s->step,push)){
// 取消到位回调
input_set_callback_once(GET_POS_CHANNEL(s->step),1,0,0);
}
// 重置状态
RESET_STEP(s->step);
// 复位输出状态
RESET_OUTPUT();
s->busy=0;
SET_ERR_TIMES(3);
}
// 重置定时器
static void process_timer_start(void *arg)
{
self_def *s=arg;
SAFE_CHECK(s);
if(s->timer==0)
{
s->timer=rt_timer_create("proc_tim",process_timeout,s,
rt_tick_from_millisecond(5000),
RT_TIMER_FLAG_ONE_SHOT|RT_TIMER_FLAG_SOFT_TIMER);
}
rt_timer_start(s->timer);
}
// 停止定时器
static void process_timer_stop(void *arg)
{
self_def *s=arg;
if(s->timer){
rt_timer_stop(s->timer);
}
}
// 检测按键响应函数
static void process_check_start(void *arg)
{
self_def *s=arg;
SAFE_CHECK(s);
if(s->busy) {
DBG_WARN("check is running.");
return;
}
s->busy=1;
SET_LED_OFF();
process_timer_start(s);
SET_STEP(s->step,push);
// 启动推料气缸
SET_OUTPUT(OUTPUT_PUSH_CYLINDER,GET_PUSH_DIR(s->step));
// 设置到位回调
void process_pos(void *arg);
input_set_callback_once(GET_POS_CHANNEL(s->step),1,process_pos,s);
// 选择当前使用的总线
output_set(&s->bus_sel,GET_BUS_CHANNEL(s->step));
DBG_LOG("check_start key pressed.");
}
// 到位响应函数
static void process_pos(void *arg)
{
self_def *s=arg;
SAFE_CHECK(s);
int chip=coder_extract_chip(0);
// 请求三码数据
array_def *a=arr_creat();
arr_append(a,chip);
emit process_send_signal(s,0x8b,arr_temp(a));
SET_STEP(s->step,requst);
process_timer_start(s);
// 打开线夹
SET_OUTPUT(OUTPUT_CLAMP_CYLINDER,1);
DBG_LOG("pos in place.");
}
// 开始注码响应函数
static void process_start_slot(void *arg)
{
self_def *s=arg;
SAFE_CHECK(s);
SET_STEP(s->step,code);
process_timer_stop(s);
DBG_LOG("start code.");
}
// 赋码结束响应函数
static void process_end_slot(void *obj,int ack,array_def *data)
{
self_def *s=obj;
SAFE_CHECK(s);
if(ack){
SET_ERR_TIMES(3);
// 发送异常信息
process_send_errinfo(s);
// 发送赋码结果
emit tran_send_signal(s->tran,0x82,data);
// 复位输出状态
RESET_OUTPUT();
// 复位步骤
RESET_STEP(s->step);
s->busy=0;
return;
}else{
SET_LED_OK();
}
// 保存到内部存储
if(s->code_data){
arr_delete(s->code_data);
}
s->code_data=arr_duplicate(data);
// 关闭线夹
SET_OUTPUT(OUTPUT_CLAMP_CYLINDER,0);
// 打开挡板
SET_OUTPUT(OUTPUT_SHELL_BAFFLE,1);
// 400ms 后开始打标
void process_mark_start(void *arg);
later_execute(process_mark_start,s,400);
// 5s 后打标结束
void process_mark_end(void *arg);
later_execute(process_mark_end,s,5000);
}
// 开始打标回调函数
static void process_mark_start(void *arg)
{
self_def *s=arg;
SAFE_CHECK(s);
SET_OUTPUT(OUTPUT_MARK,1);
DBG_LOG("mark start.");
}
// 打标结束回调函数
static void process_mark_end(void *arg)
{
self_def *s=arg;
SAFE_CHECK(s);
// 关闭挡板
SET_OUTPUT(OUTPUT_SHELL_BAFFLE,0);
SET_OUTPUT(OUTPUT_MARK,0);
// 发送注码结果
if(s->code_data){
emit tran_send_signal(s->tran,0x82,s->code_data);
}
// 复位输出状态
RESET_OUTPUT();
// 复位步骤
RESET_STEP(s->step);
s->busy=0;
DBG_LOG("mark end.");
}
// 线程初始化
static void process_init(void *arg)
{
self_def *s=arg;
// 初始化输出通道
char gpioout_name[]="gpioout0";
for(int i=0;i<OUTPUT_CHANNEL_NUM;i++)
{
gpioout_name[7]='0'+i;
s->output[i].dev=dev_get(gpioout_name);
s->output[i].dev->init(s->output[i].dev);
}
// 初始化led
s->led.dev=dev_get("led");
s->led.dev->init(s->led.dev);
// 初始化模块1使用0把模块1连接到总线11不连接到总线1
// 如果要两个总线同时使用则模块0必须连接到总线2
s->mod1_use.dev=dev_get("mod1_use");
s->mod1_use.dev->init(s->mod1_use.dev);
output_set(&s->mod1_use,1);
// 初始化总线选择0选择bus11选择bus2
s->bus_sel.dev=dev_get("bus_sel");
s->bus_sel.dev->init(s->bus_sel.dev);
output_set(&s->bus_sel,0);
// 初始化模块选择,0选择模块01选择模块1
s->mod_sel.dev=dev_get("mod_sel");
s->mod_sel.dev->init(s->mod_sel.dev);
output_set(&s->mod_sel,0);
// 设置急停按钮
input_set_callback_always(INPUT_STOP_KEY,1,process_stop,s);
input_set_callback_always(INPUT_STOP_KEY,0,process_run,s);
// 设置启动按钮
input_set_callback_always(INPUT_CHECK_KEY,1,process_check_start,s);
}
static void process_thread(void *arg)
{
self_def *s=arg;
process_init(s);
while (s->run)
{
rt_thread_mdelay(200);
output_set(&s->led,1);
rt_thread_mdelay(200);
output_set(&s->led,0);
}
}
static void init_later(void *t)
{
void *protu=app_variable("protu",0,0);
if(protu){
protu_codec_set(protu,protu_find_codec("ym_checker"));
connect(t,process_send_signal,0,protu,protu_send_call);
DBG_LOG("process thread created");
}else{
DBG_WARN("can not fond variable \"protu\"");
}
}
static void init_tran(void *t)
{
self_def *s=t;
s->tran=app_variable("tran",0,0);
if(s->tran){
connect(s->tran,code2_end_signal,0, t,process_end_slot);
connect(s->tran,code2_start_signal,0,t,process_start_slot);
}else{
DBG_WARN("can not fond variable \"tran\"");
}
}
static int init_thread(void)
{
self_def *s=&g_self;
s->inited=1;
s->run=1;
rt_thread_t rt_t=rt_thread_create("process_t",process_thread,s,1024,15,20);
rt_thread_startup(rt_t);
app_valid_call("protu",init_later,s);
app_valid_call("tran",init_tran,s);
return 0;
}
app_init_export(init_thread)
// 定义接收上位机命令用于模拟输入通道触发
typedef struct{
ucport_def u;
}pccmd_def;
void (*g_input_fun_table[])(void *t)={
process_stop,
process_run,
process_check_start,
process_pos,
};
static ucport_def *process_pccmd(tran_def *t, uint8_t cmd,array_def *data)
{
if(arr_length(data)<1){
DBG_WARN("cmd format err.");
return 0;
}
int ret=0;
pccmd_def *u=calloc(1,sizeof(pccmd_def));
int table_len=LENGTH(g_input_fun_table);
int index=arr_get(data,0);
if(index>=0&&index<table_len){
DBG_LOG("call the pccmd fun.index=%d",index);
g_input_fun_table[index](&g_self);
}else{
DBG_WARN("can not find the pccmd fun.index=%d",index);
}
return (ucport_def *)u;
}
transmit_export(ym_checker,0x90,process_pccmd)