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

2014-01-153万
精华项目
AI 快速预览详细 收起
本文介绍了如何在Arduino编程中使用状态机方法来实现复杂的控制逻辑。通过一个简单的LED示例,展示了状态转换条件和Switch语句的应用。首先定义了三个状态:亮、灭、闪烁,通过按键触发状态转换。代码示例详细说明了如何使用Switch语句和状态标志变量实现状态机。这种编程方法可以简化复杂的控制逻辑,使其更易于理解和维护。


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

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

以一个人生病为例。
Arduino编程之----如何让你Arduino以状态机方式运行图1


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

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

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

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

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

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

首先画出状态转移图


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


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


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


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

  1. // Pin 13 has an LED connected on most Arduino boards.
  2. // give it a name:
  3. const int led = 13;
  4. const int buttonPin = 2;
  5. volatile int stateFlag = 1;
  6. // the setup routine runs once when you press reset:
  7. void setup()
  8. {
  9.    // initialize the digital pin as an output.
  10.    pinMode(led, OUTPUT);
  11.    pinMode(buttonPin,INPUT);
  12. }
  13. // the loop routine runs over and over again forever:
  14. void loop()
  15. {
  16.    switch (stateFlag)
  17.    {
  18.           case 1:
  19.           digitalWrite(led, HIGH);
  20.           if(digitalRead(buttonPin))stateFlag=2;
  21.           break;
  22.           case 2:
  23.           digitalWrite(led, LOW);
  24.           if(digitalRead(buttonPin))stateFlag=3;
  25.           break;
  26.           case 3:
  27.           LED_Blink(1000);
  28.           if(digitalRead(buttonPin))stateFlag=1;
  29.           break;
  30.           default:
  31.           break;
  32.   }
  33. }
  34. void LED_Blink (unsigned int time_ms)
  35. {
  36.   static unsigned long int n=0;
  37.   static int stateLed = LOW;
  38.   if (millis()-n>=time_ms)
  39.   {
  40.      stateLed=!stateLed;
  41.      digitalWrite(led, stateLed);
  42.      n=millis();
  43.   }
  44. }
复制代码




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

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




















创作许可协议

本项目采用 None(不开放任何权利,保留所有权利) 进行许可。

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

什么bug啊 实测应该是正常的,当然是在循环时间很短的情况下 算是伪实时吧
phoebe.wang40
phoebe.wang40
最后一张图不错;P
Holiday
Holiday
发完贴还要镇楼,不过这个状态机不错:lol
- 没有更多了 -