结项 全编程高速自动控制系统
时间:10-02
整理:3721RD
点击:
项目描述:
用户可根据不同加工产品或控制需求,通过人机界面间单直观的输入操作自主编写加工或动作程序 。在用户所编程序中自动编写各个输出点、输入触点检测,动作时间延时等,而且所编写的程序都可以多次保存、修改。同时支持自动加工(动作)流程程序,且每条自动加工程序可以任意修改保存,提高现场编程时间,大大提高了工作效率,减轻操作者的劳动强度。全功能开放式设计,用户可根据实际机械结构要求和平时操作习惯,来设定最合适的参数,不用更改芯片或程序,为用户获得宝贵试机和开发时间。
项目需求:
归结为数字端口的输出与输入,延时,流程的编写,涉及到流程的编写首当,应该就是UML流程图。很多的动作流程都是通过流程图进行整理动作流程。
以一个小项目为例:
电动卷闸
关门的流程图所下:
结论:
由流程图看出,可以归结为节点与线,其中线只是表示节点的流向,那么关键就在于节点的表示,以及节点的转换。
节点种类有 椭圆(开始、结束)、菱形(判断)、长方形(动作)
- typedef enum flow_mode_typedef {
- Value_Flow_Start,//延时 开始 结束
- Value_Flow_Work,//动作
- Value_Flow_Judge,//判断
- Value_Flow_Delay,//延时
- }flow_mode_e;
开始 0入1出
结束 1入0出
动作 1入1出
判断 1入2出 (可能有人疑问不是1入3出,其实其相当于if,最多也只能是1入2出)
其实上面还隐含一个关系, 就是从程序的过程角度出法,其实 开始与结束是结合在一起的。
结束 的一个动作就是开始。
开始的数据结构
- typedef struct flow_start_typedef{
- uint8_t ucR_Num;//序列号
- flow_mode_e eR_Mode;
- uint8_t ucR_NumNext;
- uint32_t ul_DelayMs;
- }flow_start_t;
动作的数据结构
- typedef struct flow_work_typedef{
- uint8_t ucR_Num;//序列号
- flow_mode_e eR_Mode;
- uint8_t ucR_NumNext;
- output_t ucR_OutPutNum;
- uint8_t ucR_OutPutData;
- //void (* funP_Word)(output_t ); //Value_Flow_Start Value_Flow_Work
- }flow_work_t;
- typedef struct flow_judge_typedef{
- uint8_t ucR_Num;//序列号
- flow_mode_e eR_Mode;
- uint8_t ucR_NumNext;//正确的出口
- uint8_t ucR_NumFalseNext;//错误的出口
- input_t ucR_InPutNum;
- //bool (* funP_Judge)(input_t );
- }flow_judge_t;
但是再从编写的角度,归结到一类的写法就不方便。所以最后,结束在一起。如下所示:
- typedef enum flow_mode_typedef {
- Value_Flow_Start,//延时 开始 结束
- Value_Flow_Work,//动作
- Value_Flow_Judge,//判断
- Value_Flow_Delay,//延时
- }flow_mode_e;
- typedef uint8_t output_t;
- typedef uint8_t input_t;
- typedef struct flow_typedef{
- uint8_t ucR_Num;//序列号
- flow_mode_e eR_Mode;
- uint8_t ucR_NumNext;
-
- uint32_t ul_DelayMs;
-
- output_t ucR_OutPutNum;
- uint8_t ucR_OutPutData;
-
- uint8_t ucR_NumFalseNext;//错误的出口
- input_t ucR_InPutNum;
- }flow_t;
- flow_t * S_Log_Flow_Found(uint8_t ucR_Num)
- {
- uint8_t i = 0;
- for(i=0;i<Value_ArraryFlowNum;i++)
- {
- if(stA_Flow[i].ucR_Num==ucR_Num)
- {
- return &stA_Flow[i];
- }
- }
- return (flow_t*)0; //没有找到
- }
- flow_t * S_Log_Flow_Ctrl(flow_t * stP_Flow)
- {
- switch(stP_Flow->eR_Mode)
- {
- case Value_Flow_Start:
- case Value_Flow_Delay:
- {
- delay_ms(stP_Flow->ul_DelayMs);
- return S_Log_Flow_Found(stP_Flow->ucR_NumNext);
- }
- //break;
- case Value_Flow_Work:
- {
- MX_GPIO_Set(stP_Flow->ucR_OutPutNum,stP_Flow->ucR_OutPutData);
- return S_Log_Flow_Found(stP_Flow->ucR_NumNext);
- }
- //break;
- case Value_Flow_Judge:
- {
- if(MX_GPIO_Get(stP_Flow->ucR_InPutNum))
- {
- return S_Log_Flow_Found(stP_Flow->ucR_NumNext);
- }
- else
- {
- return S_Log_Flow_Found(stP_Flow->ucR_NumFalseNext);
- }
-
- }
- //break;
- default:
- {
- return stP_Flow;
- }
- //break;
- }
- //return stP_Flow;
- }
- while(1)
- {
- stP_Flow=S_Log_Flow_Ctrl(stP_Flow);
- //OSTimeDlyHMSM(0,0,0,5,OS_OPT_TIME_PERIODIC,&err);//延时5ms
- }
回到例子,任务函数如下所示
- void flow_ctrl_task(void *p_arg)
- {
- flow_t * stP_Flow = &stA_Flow[0];
-
-
- //开始
- S_Log_Flow_Free(&stA_Flow[0]);
- stA_Flow[0].ucR_Num = 0;
- stA_Flow[0].eR_Mode = Value_Flow_Start;
- stA_Flow[0].ucR_NumNext = 1;
- stA_Flow[0].ul_DelayMs = 500;
- stA_Flow[0].ucR_OutPutNum = 0;
- stA_Flow[0].ucR_OutPutData = 0;
- stA_Flow[0].ucR_NumFalseNext = ucR_Num_Null;
- stA_Flow[0].ucR_InPutNum = 0;
-
- //按钮停==true
- S_Log_Flow_Free(&stA_Flow[1]);
- stA_Flow[1].ucR_Num = 1;
- stA_Flow[1].eR_Mode = Value_Flow_Judge;
- stA_Flow[1].ucR_NumNext = 5;//电机停止
- stA_Flow[1].ul_DelayMs = 500;
- stA_Flow[1].ucR_OutPutNum = 0;
- stA_Flow[1].ucR_OutPutData = 0;
- stA_Flow[1].ucR_NumFalseNext = 2;//限位开关==true
- stA_Flow[1].ucR_InPutNum = 0;//端口0输入
-
- //限位开关==true
- S_Log_Flow_Free(&stA_Flow[2]);
- stA_Flow[2].ucR_Num = 2;
- stA_Flow[2].eR_Mode = Value_Flow_Judge;
- stA_Flow[2].ucR_NumNext = 5;//电机停止
- stA_Flow[2].ul_DelayMs = 0;
- stA_Flow[2].ucR_OutPutNum = 0;
- stA_Flow[2].ucR_OutPutData = 0;
- stA_Flow[2].ucR_NumFalseNext = 3;//按钮关门==true
- stA_Flow[2].ucR_InPutNum = 1;//端口1输入
-
- //按钮关门==true
- S_Log_Flow_Free(&stA_Flow[3]);
- stA_Flow[3].ucR_Num = 3;
- stA_Flow[3].eR_Mode = Value_Flow_Judge;
- stA_Flow[3].ucR_NumNext = 4;//电机正转
- stA_Flow[3].ul_DelayMs = 0;
- stA_Flow[3].ucR_OutPutNum = 0;
- stA_Flow[3].ucR_OutPutData = 0;
- stA_Flow[3].ucR_NumFalseNext = 5;//电机停止
- stA_Flow[3].ucR_InPutNum = 2;//端口2输入
-
- //电机正转
- S_Log_Flow_Free(&stA_Flow[4]);
- stA_Flow[4].ucR_Num = 4;
- stA_Flow[4].eR_Mode = Value_Flow_Work;
- stA_Flow[4].ucR_NumNext = 0;//开始
- stA_Flow[4].ul_DelayMs = 0;
- stA_Flow[4].ucR_OutPutNum = 0;
- stA_Flow[4].ucR_OutPutData = 1;//正转
- stA_Flow[4].ucR_NumFalseNext = ucR_Num_Null;
- stA_Flow[4].ucR_InPutNum = 0;
-
- //电机停止
- S_Log_Flow_Free(&stA_Flow[5]);
- stA_Flow[5].ucR_Num = 5;
- stA_Flow[5].eR_Mode = Value_Flow_Work;
- stA_Flow[5].ucR_NumNext = 0;//开始
- stA_Flow[5].ul_DelayMs = 0;
- stA_Flow[5].ucR_OutPutNum = 0;
- stA_Flow[5].ucR_OutPutData = 0;//停止
- stA_Flow[5].ucR_NumFalseNext = ucR_Num_Null;
- stA_Flow[5].ucR_InPutNum = 0;
-
- while(1)
- {
- stP_Flow=S_Log_Flow_Ctrl(stP_Flow);
- //OSTimeDlyHMSM(0,0,0,5,OS_OPT_TIME_PERIODIC,&err);//延时5ms
- }
- }
二、显示
只能说是丑陋的界面,满屏的文字,其实还有很多优化的地方。日后再来慢慢改善。
三、缺点与日后改善
时间过得真的很快,不经不觉就两个月。对于一个全新的项目与思维,真心觉得两个月的时间是不够的。现在只能做到这个样子,下一步,
1、应该是流程图支持拖放,
2、依据类型自动变换形状,
3、流程节点采用动作生成
4、利用连线进行按序
5、多流程的并行操作
6、流程图的掉电保存
。
要做的东西很多,只能一步步来了!后面还要继续完美代码。代码就迟些上传
四、感悟
ALIENTEK 阿波罗 STM32F767 开发板确实是做得很好的板子,更给力的是有丰富的例程,提供给新手们参考学习。
特别是
STM32F7开发指南-HAL库版本_V1.0.pdf
STM32F767 EMWIN开发手册_V1.0.pdf
节省了很多的时间,为项目争取更多时间
小编有演示视频嘛?
强强
小编有演示视频嘛