22490浏览
查看: 22490|回复: 5

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

[复制链接]
本帖最后由 何处不江南 于 2014-1-15 14:00 编辑

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

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

以一个人生病为例。
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



















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()的定义说了:
  1. unsigned long millis (void)
  2. 毫秒时间
  3. 获取机器运行的时间长度, 单位毫秒. 系统最长的记录时间为9小时22分, 如果超出时间将从0开始.
复制代码
也就是说在arduino上电9小时22分unsigned long快要溢出的那一秒,闪烁会提前切换。
其实问题不大。


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4

© 2013-2024 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail