移植到stm32f1,实现手动线赋码控制器功能

This commit is contained in:
ranchuan
2023-09-09 17:27:06 +08:00
parent 8d779a68f3
commit 7baa63de05
382 changed files with 36618 additions and 148064 deletions

569
source/task/process.c Normal file
View File

@@ -0,0 +1,569 @@
#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 7
// 定义总线选择
#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);}
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 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_stop(void *arg)
{
self_def *s=arg;
s->stop_state=1;
SET_LED_ERR();
DBG_LOG("stop key pressed.");
}
static void process_run(void *arg)
{
self_def *s=arg;
s->stop_state=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_LED_ERR();
}
// 重置定时器
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_LED_ERR();
// 发送异常信息
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,1);
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)