饮水机复杂交互功能联网调试
引言
饮水机我们从最开始的放水和加热, 逐渐拓展到保温功能, 童锁功能, 红外检测功能, 对于这些复杂的交互功能, 我们如果通过按键进行调试, 会极大的增加我们的开发时间和成本, 如果我们频繁的进行烧录, 则如果涉及到一些中间变量, 则无法进行调试.
大家会想到串口, 串口也是可以的, 但是串口发送接受, 太频繁的话, 则会眼花缭乱, 如果我们能够成为上帝, 在程序运行的时候修改并查看变量, 之间的交互状态, 则会方便我们的开发.
解决方案
我们利用Onenet, 创建饮水机产品, 把能够上传的变量, 全部上传, 并且设置成可修改的变量, 我们把要上传的变量上传, 并且可以在服务器下发变量, 并让单片机读取到后, 赋值本地变量.
这样我们就可以取代按键和OLED, 观察交互现象了, 极大的提供了程序开发效率和可视化.
示例工程调试需求
我们通过分析我们之前饮水机的示例, 查看当时我们是怎么手动进行调试的, 我们从而抽取出我们需要远程上传, 远程控制的变量. 从而探索他们之间的交互逻辑.
加热系统达温即停和保温功能调试
对于饮水机的加热功能, 这个是日常生活所必须的, 并且其设计逻辑必须严密, 所以我们要进行逻辑清晰的系统设计, 多重保障, 如果只是通过简单的数据测试, 是不行的. 所以我们就需要频繁的给与初始数据和中间数据, 来测试他们之间的交互性。
比如我们加热水温, 我们不仅仅要调试水温阈值, 还要调试水温, 之前我们调试, 都是通过直接赋予水温初始值, 那么这只能调试一次, 并且调试不了他们之间的模式切换。
所以, 我们如果能快速控制水温, 快速控制水温阈值, 让饮水机自带的逻辑, 去判断,我们通过观察交互现象, 来测试我们的程序是否具有健壮性。
达温即停和保温功能手动调试
需要调试的变量
通过观看我们的博客
在加热模式下, 我们调试的是水温 water_temp 和加热阈值 heat_temp_th
在保温模式下,我们调试的是水温water_temp和保温阈值 KeepWarm_th
模式切换方面, 我们调试的是 控制模式切换的变量 heat_mode
加热系统模式交互测试
![image-20240826164054278](https://img-blog.csdnimg.cn/img_convert/5f98fb5424c56ed1e2470adcf91e030e.png)
通过观察博客, 我们知道, 加热模式, 我们用户切换到加热模式, 然后设置完加热阈值后, 饮水机把水加热到阈值后, 就会切换为关闭模式.
这个就是我们 加热模式的交互功能.
我们的调试思路就是, 通过先设置水温和加热阈值(水温 < 加热阈值), 然后把模式切换为加热模式, 查看, 是否会触发加热, 就是红色小灯是否会亮。
从而观察现象, 得出在加热模式下, 当水温 < 加热阈值, 是否会触发加热, 饮水机加热是否正常运行
接下来调试的是,加热模式下, 当加热系统把水温加热到所需阈值后, 是否会触发自动关闭加热.
我们的调试方法就是,在上一个模式的基础上 直接修改水温(充当上帝), 这样程序就会把水温读取到 加热处理函数, 我们查看是否会切换模式,
并且, 系统是否把加热小灯关掉.
从而得出结论:
在加热模式下, 当水温 >= 水温阈值, 是否能够触发自动关闭加热功能
保温系统可用性测试
相对于加热系统, 我们保温系统, 需要一直保温, 一直保温就代表着我们一旦 水温 < 保温阈值, 我们就要加热, 我们要测试的 就是
水温 < 保温阈值 : 饮水机能否加热
水温 >= 保温阈值 : 饮水机能否关闭加热
我们要重复的进行测试, 从而测试系统可用性.
1 测试功能: 在水温失温后, 加热到保温阈值的保温功能
测试方法: 我们把调整水温 和 保温阈值(水温 < 保温阈值), 然后把模式设置成 保温模式,
观察现象:查看是否会触发红灯加热
得出结论: 保温系统, 是否能够正常的加热保温
2 测试功能: 加热到保温阈值后的关闭加热功能.
测试方法: 在上一个功能调试的基础上, 调整水温 >= 保温阈值
观察现象:查看小灯是否会熄灭
得出结论: 保温系统, 能否保证达温即停
童锁功能交互
童锁功能, 是为了家庭避免儿童误触而开发的, 所以当童锁开启的时候, 饮水机是不能开水的, 所以我们在童锁打开的情况下, 不能开启水龙头
所以我们设置 童锁的状态 child_lock_info.Status
童锁锁住时
child_lock_info.Status = lock_child
童锁解开时
child_lock_info.Status = Unlock_child
童锁功能调试需要用到的变量
童锁变量分析
童锁控制的是开关水龙头, 所以所有关于开水的设置, 我们都要考虑在内。
在没有加任何安全措施的时候, 我们只是通过 直接控制io口, 进行开关水龙头的, 后来我们为了检测水龙头的状态,避免重复开关水龙头, 所以加了放水的状态控制变量 out_water_info.State .
开水
out_water_ON 1
关水
out_water_OFF 0
红外检测变量
后来为了防误触, 加了红外检测, 所以我们又加入了红外检测到杯子遮挡后, 触发中断, 我们把杯子状态设置成
Cup_placement 1 //杯子放置
如果没有触发中断, 则杯子状态是不存在
Cup_disappears 0 //杯子未检测到
所以我们加入了杯子状态变量 cup_place_info.Status
变量交互分析图
当保护措施过多的时候, 我们就很难分析他们之间的交互关系了, 但是我们转换一个思路来想, 他们都是为了开水安全, 也就是说, 当我发送开水指令的时候, 他们会千方百计的给我提条件, 当满足他们说的安全条件时, 才放行开水. 所以我们在 放水的函数里面做工作, 以不变应万变.
对应的底层开水状态控制代码
void OUT_water_Set(_Bool status)
{
if( status == out_water_ON && out_water_info.Status != out_water_ON &&
child_lock_info.Status == Unlock_child &&
cup_place_info.Status == Cup_placement
)
{
GPIO_SetBits(GPIOA, GPIO_Pin_7);
out_water_info.Status = out_water_ON;
}
else
if(
(status == out_water_OFF && out_water_info.Status != out_water_OFF) ||
child_lock_info.Status == lock_child ||
cup_place_info.Status == Cup_disappears
)
{
GPIO_ResetBits(GPIOA, GPIO_Pin_7);
out_water_info.Status = out_water_OFF;
}
}
童锁功能测试
1 测试目的: 测试童锁对水龙头的保护作用
测试方法:
我们开启童锁
设置童锁
out_water_info.State = lock_child;
然后让其他两个条件全部满足, 测试是否可以开水.
cup_place_info.Status = Cup_placement;//杯子放置 out_water_info.Status != out_water_ON;//水龙头未开
然后控制开水, 测试
OUT_water_Set(out_water_ON);
测试现象: 观察, 如果不能控制水龙头的io对应的小灯不亮, 则代表童锁起到了保护作用.
2 测试目的: 测试关闭童锁后, 满足其他两个条件后, 是否可以正常接水
我们解开童锁
设置童锁状态
out_water_info.State = Unlock_child;
然后让其他两个条件全部满足, 测试是否可以开水.
cup_place_info.Status = Cup_placement;//杯子放置 out_water_info.Status != out_water_ON;//水龙头未开
然后控制开水, 测试
OUT_water_Set(out_water_ON);
测试现象:观察, 如果不能控制水龙头的io对应的小灯亮起, 则用户可以正常关闭童锁, 然后正常接水 .
联网调试变量交互分析
加热系统
需要上传
//水温 water_temp //加热阈值 heat_temp_th //保温阈值 KeepWarm_th //加热模式 heat_mode
饮水系统
我们根据饮水机的童锁和红外的交互功能, 来判断, 是否可以控制底层开启水龙头
上图, 描述了他们之间的关系, 代码中也体现了出来, 所以我们上传的变量分别是
//童锁状态 child_lock_info.Status //杯子是否放置 cup_place_info.Status //水龙头出水状态 out_water_info.Status