做了一个能常亮24天的多功能时钟,也是一个指南针!

为什么它能续航这么久?我做对了什么?(见第3章)
其有哪些功能?(见第1章)
硬件设计注意事项?(见第2章)
下面就一一为你解答!
一、时钟的功能/亮点展示
1.指南针功能
使用时先原地慢慢转一圈即可校准。
此模式下功耗:1.3mA。

2.TV模式(时钟等基础显示)
40秒显示时间,电池电量。
此模式下功耗:1.7~1.9mA

10秒显示温度、湿度、气压

10秒显示电池状态循环(持续时间可按喜好调整)

3.菜单设置
设置了三级菜单。
主菜单:见图,这里预设了16个二级菜单。
滚动时总功耗:2mA

二级菜单:见图,按确定进行设置
滚动时总功耗:4mA

三级菜单:见图,按确定进行设置
页面总功耗:1.4mA

支持开发:水平尺、增量闹钟、秒表、手电筒、系统设置、工厂模式
未来加入亮度自动调节机制,可坚持超过一个月
二、硬件说明
使用STC32F12K54芯片作为主控,在TV模式可运行大约24天,以下是相关电路图。

控制板原理图

控制板PCB图

电源板原理图

电源板PCB图
1.控制板参数介绍
主控:STC32F12K541.3寸OLED:SSD1315(使用SPI)温湿度计:SHT40气压计:SPL-06RTC:INS5699光强计:BH1745磁强计+加速度计:BMC050无源蜂鸣器(但有独立4K方波产生电路,不占用MCU资源)震动开关按键X5:+、-、确定键、退出键、复位键2.电源板参数介绍
电源板2.8V空载,5V OFF的情况下,待机电流1.6uA(电池3.83V)
DC-DC锂电池充电:ME4059ASPG-N)锂电池保护:ME4211AM6GDC-DC降压(主板供电):TPS62740DSSRDC-DC升压(OLED供电):MT9700+MT3608L,可以通过主板的两个IO口控制反馈电阻,从而获得5V、6V、7V、8V充电电流检测:INA181A2IDBVT+50mΩ电阻三、续航24天,我做对了什么?
本项目之所以可以这么省电,是因为MCU不会干多余的事情,有任务的时候才会运行,其他时间都在休眠。
但,事情怎么会这么简单呢?
1.发现的第一个问题
之前做第一代第二代时钟的时候,就发现一个事情:
MCU在执行任务的时候,很多时候都在delay
例如滚动数字的时候,平移32格像素,需要平移32次,每次平移后间隔6毫秒才能执行下一次的平移,这个时候,空跑的的时间就是31×6=186ms。
这是非常致命的。
如果一秒刷新一次,就有18.6%的时间浪费在等待上。
再例如给传感器发送测量指令后,需要等待一段时间才能读取测量后的值……
这一段时间也是需要等待的。
解决思路
为了解决MCU在等待时摸鱼的情况,可以让MCU在等待的时候进入掉电模式,从而降低功耗。
2.第二个问题
但这样又不得不面临一个新的问题,就是
MCU怎么知道自己什么时候醒过来?
解决思路
针对这个问题,可以使用:
掉电唤醒定时器
通过设置掉电唤醒定时器的时间,控制MCU休眠后在我们指定的时间醒过来
3.第三个问题
但这样又有一个问题,那就是:
MCU怎么知道下次什么时候醒过来?
例如执行一个32格像素的平移,要执行32次,MCU执行了第一次,它怎么知道还要执行32次间隔6ms的任务?
解决思路
为了解决这个问题,我想了个办法:
引入两个数组
一个是“休眠时间数组”,一个是“任务号数组”(每个bit代表一个任务),两个数组的值一一对应。
例如执行一个32格像素的平移,要执行32次,我就先在“休眠时间数组”和“任务号数组”中预约32个任务,如下图所示。

每次MCU检测数组“休眠时间数组”[0]和“任务号数组”[0]中的数值,如果不等于0,则将“休眠时间数组”[0]的值装入掉电唤醒寄存器,进行休眠,唤醒后再根据“任务号数组”[0]的值匹配相应的任务。
任务完成后整个数组的值向左移动一位。
当检测到“休眠时间数组”[0]和“任务号数组”[0]中的数值为0时,说明UI刷新任务已经完成,掉电唤醒寄存器关闭,彻底进入休眠,等待外部按键中断任务的唤醒。
但项目中并非只有一个OLED屏幕刷新的任务
对于传感器测量等待的任务,为了尽可能保证时效性,不可能排在UI刷新完成之后再测量。
我们当然希望能两不误。
这时就需要写插入算法将任务插入任务队列中。
例如在队列中插入一个气压测量的任务(“任务号数组”bit1 =1),需要等待15ms(6+6+3),插入上图的队列中,如下图。
可以看到当数值不可以重合时,需要打断队列插入数值。

再例如在队列中插入一个气压测量的任务,需要等待12ms,插入上图的队列中,如下图。
可以看到当数值重合时,不需要打断队列插入数值。
只需要添加任务号所对应的bit位。

4.第四个问题
到目前为止,低功耗任务预约的算法算是弄完了,但还有一个问题,就是:
在休眠的过程中,如果有外部中断输入,就会让MCU提前结束休眠。
这样可能会导致传感器采样异常,影响用户体验。
解决思路
这个时候,就需要:
优化睡眠的算法
检测醒来的时候,如果掉电唤醒寄存器内的时间还没有走完,就把值装填回去再次休眠,直到定时器内的值是0为止。
5.最后一步,将MCU性能榨干
事情还没有结束,我们还可以进一步降低功耗,争取榨干MCU性能!
MCU最耗电的任务其实是在刷屏的时候——这时候使用SPI发送数据,需要MCU参与其中,不能去干别的事情。
这个时候我们可以使用DMA功能,使用双缓冲区,先装填1区,DMA发送1区的数据,在1区发送的时候,装填2区,轮流发送,循环往复,提高MCU的工作效率。
但单纯DMA发送数据的话,其实还是会更耗电。
因为需要将数据从flash搬到XRAM里面,再通过DMA发出去是需要时间的,效率上不如把flash的数据直接发送出去。
这个时候可以利用MCU进入停IDLE模式时,MCU停止工作,但外设还在可以工作的特点。
如果在2区填充完成,但1区还没发完的情况下,还可以让MCU进入停IDLE模式,这个时候MCU停止工作,但外设还在可以工作,在IDLE模式等待SPI DMA 发送完成后再唤醒执行别的程序。
这样功耗就可以进一步降低。
除此之外,还有各种优化局部刷新,一点点抠功耗,直至榨干最大性能价值……
参考资料:
[1]开源资料https://oshwhub.com/yq-qvq/low-power-consumption-for-24-days-desktop-clock
— 完 —
嘉立创EDA·头条号
关注我,看一手优质开源项目
免责声明:文章内容来自互联网,本站仅提供信息存储空间服务,真实性请自行鉴别,本站不承担任何责任,如有侵权等情况,请与本站联系删除。
转载请注明出处:做了个多功能时钟,只因我解决了这4个问题,续航24天超轻松! https://www.bxbdf.com/a/180461.shtml