STM32状态机编程实例——全自动洗衣机(上)
本篇,继续使用状态机编程,来实现一个更有趣的功能——全自动洗衣机。
下面是一个全自动洗衣机的控制面板:

面板上有4个按键:
电源:控制洗衣机通电与断电
水位:选择洗衣时需要的水位,有1~8个水位
程序:选择不同的洗衣模式,有1~10个模式
01:标准
02:轻柔
03:快速
...
10:桶风干
启动/暂停:用于启动或暂停洗衣任务
面板上还有一个数码管,用于显示当前的工作状态与剩余时间,可显示的工作模式有:
AA:浸泡
BB:洗涤
CC:漂洗
DD:脱水
本篇,就按照这款洗衣机的操作方式实现对应的洗衣机控制逻辑。需注意的是:
实际的洗衣机有水位检测传感器,本篇中,暂用时间延时模拟水位的增加,且默认开机时水位为0
实际的洗衣机中的洗衣模式,会根据不同的模式自动设置清洗次数与每次清洗的时间以及清洗力度,本篇为了简化起见,清洗模式的设置仅用于区分不同的清洗次数
某些特殊的清洗模式,如单独的脱水,桶风干等,本篇暂不实现
对于状态的显示 ,本篇先以串口打印的实现展示,下篇使用OLED小屏幕来显示不同清洗状态的图标等信息
2 画状态图
根据上面分析的全自动洗衣机的功能,以及我们自己使用洗衣机时的经验,可以画出如下的全自动洗衣机的状态图:

首先是上电开机,洗衣机可能会开机自检,检测洗衣机的各个部件是否正常,次过程很短。
然后就处于空闲状态,此时用户可以设置水位与清洗模式,若不设置,则为默认的水位与洗衣模式。
接着触发开始按键后,就开始清洗了,一般流程就是:加水、清洗、排水、甩干、结束。
根据不同的清洗模式,加水、清洗和排水这3个过程会循环执行一定的次数。
另外,在不同的工作阶段,按下暂停键可以让洗衣任务暂停,再按继续可让洗衣任务继续。
3 编程实现
3.1 多按键检测功能
本篇介绍的洗衣机的按键,仅需要检测按键单击即可,不需要双击与长按功能,因此,可使用之前文章介绍的最基础的按键状态机来为洗衣机状态机提供按键事件。
之前介绍的按键状态机,只有一个按键,本篇需要用到4个按键(除去电源键,3个也可以),因此,需要对按键状态机稍加修改,实现按键状态机的复用。
之前介绍的按键状态机,使用了几个全局变量来表示状态,更合理的做法是将其封装起来:
注意,额外增加了一个按键索引值,用来告诉状态机要检测哪个按键。
再将原来的按键状态机程序,通过入参的形式将上述定义的结构体传入,并通过函数返回的形式返回按键是否被按下。
这样修改后的按键状态机,就是一个独立的模块了,可以通过传入不同的参数,实现不同按键的检测。
对于本篇需要的4个按键的检测,就可以定义4个数据结构体,分别调用4次状态机函数即可,实现代码的复用。
其中,multi_key_check函数,放到50ms周期的定时器中断服务函数中,使按键状态机程序运行起来。
get_press_key_idx函数,用于洗衣机程序来获取不同按键的按下事件,每次获取后,将按键事件清除(g_keyPressIdx设为无效值-1)
3.2 洗衣功能
按照上面绘制的洗衣机状态图,使用switch-case法编写对应的程序即可:
这里将洗衣机不同状态时的处理逻辑,都分别使用函数来实现,并将其返回值作为下一个要跳转的状态。
各个状态的处理函数如下:
对于按键的获取,这里定义了几个对应的功能按键,并从按键状态机函数中获取按键索引,再转为洗衣机程序所需的对应功能按键:
洗衣机状态机主程序,可以放到main函数中,每隔100ms调用一次,使其运行起来:
3.3 测试
将代码烧写到STM32板子中,通过3个按键(电源键暂不使用)操作,并通过串口打印,查看全自动洗衣机的运行情况:

4 总结
本篇实现了一款全自动洗衣机的基础洗衣控制流程,可实现不同水位与清洗次数的设置,以及任务的暂停与继续。此外,通过对之前按键状态机的进一步优化修改,实现了按键状态机的复用,实现多个按键的检测。下篇文章将进一步进行功能优化,添加OLED小屏幕实现不同状态的可视化展示。