何处不江南 发表于 2014-1-15 13:59:01

Arduino编程之----如何让你Arduino以状态机方式运行

本帖最后由 何处不江南 于 2014-1-15 14:00 编辑

首先一个问题,何为状态机?
不用各位看官去百度状态机那些艰深的定义。简单的描述下就能知道。

在这里我所说状态机是一种编程方式,在现实中是广泛存在的。

以一个人生病为例。



健康 感冒 康复中分别就是3个状态。

状态与状态之间转换的条件就叫状态转换条件

用这种方法编程就叫有限状态机(FSM)。

其思想广泛应用于硬件控制电路设计,也是软件上常用的一种处理方法(软 件上称为FMM--有限消息机)。
它把复杂的控制逻辑分解成有限个稳定状态,在每个状态上判断事件,变连续处理为离散数字处理,符合计算机的工作特点。
同时,因为有限状态机具有有限个状态,所以可以在实际的工程上实现。但这并不意味着其只能进行有限次的处理,相反,有限状态机是闭环系统,有限无穷,可以用有限的状态,处理无穷的事务。

重点来了,我们如何在Arduino编程中实现这种方法?

还是用实际的程序来说明吧,假设我们现在有3个状态,为简单起见现在以灯(LED)的状态来代替。
分为亮,灭,闪烁三个状态(实际应用中可以是小车左转,右转,停止,再比如舵机转动,发送一个信息。。。。。),状态转移条件都为按按键一次。

首先画出状态转移图





那么我们如何将其变为C语言呢。
一个重要的语句为Switch语句。
这个语句就是用来判断状态的,我们可以用一个标志数据来记录现在的状态并为其编号





这样我们就可以开始写代码了,下面给出参考代码。

// Pin 13 has an LED connected on most Arduino boards.
// give it a name:
const int led = 13;
const int buttonPin = 2;
volatile int stateFlag = 1;
// the setup routine runs once when you press reset:
void setup()
{
   // initialize the digital pin as an output.
   pinMode(led, OUTPUT);
   pinMode(buttonPin,INPUT);
}
// the loop routine runs over and over again forever:
void loop()
{
   switch (stateFlag)
   {
          case 1:
          digitalWrite(led, HIGH);
          if(digitalRead(buttonPin))stateFlag=2;
          break;
          case 2:
          digitalWrite(led, LOW);
          if(digitalRead(buttonPin))stateFlag=3;
          break;
          case 3:
          LED_Blink(1000);
          if(digitalRead(buttonPin))stateFlag=1;
          break;
          default:
          break;
}
}
void LED_Blink (unsigned int time_ms)
{
static unsigned long int n=0;
static int stateLed = LOW;
if (millis()-n>=time_ms)
{
   stateLed=!stateLed;
   digitalWrite(led, stateLed);
   n=millis();
}
}



好了,第一个状态机程序就完成了。希望对大家有帮助啊
说完发图一副,镇楼。





















Holiday 发表于 2014-1-15 18:00:24

发完贴还要镇楼,不过这个状态机不错:lol

Phoebe 发表于 2014-1-15 23:28:12

最后一张图不错;P

nemon 发表于 2014-1-16 15:00:27

millis()-n>=time_ms
有bug

何处不江南 发表于 2014-1-16 16:17:31

nemon 发表于 2014-1-16 15:00
millis()-n>=time_ms
有bug
什么bug啊 实测应该是正常的,当然是在循环时间很短的情况下 算是伪实时吧 {:3_52:}

nemon 发表于 2014-1-16 16:56:01

何处不江南 发表于 2014-1-16 16:17
什么bug啊 实测应该是正常的,当然是在循环时间很短的情况下 算是伪实时吧...

实时做的相当好,如果把按键代码放在中断里可作为范本了。
但是millis()的定义说了:unsigned long millis (void)
毫秒时间
获取机器运行的时间长度, 单位毫秒. 系统最长的记录时间为9小时22分, 如果超出时间将从0开始.也就是说在arduino上电9小时22分unsigned long快要溢出的那一秒,闪烁会提前切换。
其实问题不大。


页: [1]
查看完整版本: Arduino编程之----如何让你Arduino以状态机方式运行