您的位置:首页 > 其它

基于状态机的简单控制

2016-09-27 11:45 148 查看
基于状态机的简单控制:

公司是做一些简单的夹具的,大部分功能是几个按键加上几个电磁阀,再加一个显示屏就构成了一个简单的控制系统。

工控行业一般要求是比较稳定的,所以我需要在启动电磁阀之后去判断我的气缸是否到了指定位置,这样我们就需要用到了Sensor,那么问题来了

首先我按下了按键,气缸也动作了,接下来我就要等待气缸到达位置,之前一直用的是while(Sensor),但是这样就出现了一个问题,气缸压着手了,气缸没到位就一直等待,而我需要急停,可是我的这个急停按钮检测放在哪里呢?

1:放在中断中,这个方法无疑是最快的,可以立刻关闭电磁阀,但是,关闭电磁阀之后呢,很明显是退出中断,继续执行之前的程序,这很明显不是我想要的结果,因为既然急停了,就说明我这里有情况了,要么产品有问题,要么外部环境有阻碍,理想状态下应该是复位才对!

2:用一个定时器每间隔多久采集一次,这个问题和外部中断的问题是一样的。

下面就引入我要介绍的这种基于状态机的控制,状态机想必大家都知道了

举个最简单的例子。人有三个状态健康,感冒,康复中。触发的条件有淋雨(t1),吃药(t2),打针(t3),休息(t4)。所以状态机就是健康-(t4)->健康;健康-(t1)->感冒;感冒-(t3)->健康;感冒-(t2)->康复中;康复中-(t4)->健康,等等。就是这样状态在不同的条件下跳转到自己或不同状态的图。

那么我们的触发条件就是Sensor到位,定时器到时间(这里我们有数码管按时刷新),等等

这样的话,我们的主程序只需要去switch状态机,然后根据状态机做动作就行了,这样的好处就是我们不需要去等待气缸到位

case 3:Y2=0;ActionStatus=4;break;

case 4:if(!X7) {ActionStatus=5;};break;

case 6:Y2=1;ActionStatus=7;break;

case 7:if(!X6) ActionStatus=0; break;

有代码可以看出Y2是打开气缸,x7是气缸sensor,这样的话,主程序便有大把时间去干其他事了!

那么,我们的主程序里或许还要去检测其他按键,这样我们的按键处理可以用消息机制来处理

 

void SysTick_Handler(void)//10ms中断

{

   static uint32_t time,temp;

   KeyCheck();

   if(ActionStatus==2)

    {

       time++;

       if(time>=100)

       {

           ActionStatus=3;

           time=0;

       }

           

   }else   

   if(ActionStatus==5)

    {

       temp++;

       if(temp>=100)

       {

           temp=0;

           KeepPreTimeCount--;

           if(KeepPreTimeCount<1)

           {

               KeepPreTimeCount=KeepPreTime;            

                ActionStatus=6;

           }

           OLED_8x16Str(0,2,ToStr(KeepPreTimeCount));

           

       }

   }else

   if(ActionStatus==0x0a)//stop

    {

       time=0;

       temp=0;

       KeepPreTimeCount=KeepPreTime;

       OLED_8x16Str(0,2,ToStr(KeepPreTimeCount));

       ActionStatus=0xa6;

    }

        

}

switch(Messange)

{

       case 3:ActionStatus=0x0a;Messange=0;break;

       case 11: KeepPreTime++;FreshTime();Messange=0;break;

       case 12: KeepPreTime--;FreshTime();Messange=0;break;

       default:break;

}

我们用10ms中断去检测按键,同时也做了消抖处理,不知道大家是否看了出来

Switch message仍然放在主函数中去判断,进行处理,如果有数码管需要进行刷新的话也可以在定时器中发出一个消息,然后在主程序中进行处理,这样免得在中断中耽误太多时间!

回归到我们刚开始提出的中断,通过程序可以看出急停按下后会发出消息,主程序会立刻对消息进行处理,然后可以改变当前状态,这样很容易就改变了程序的运行方向

偶然心血来潮总结了自己的历程,希望对大家有所帮助!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: