亚博智能论坛  
  
查看: 892|回复: 3

认识与实验Arduino的睡眠模式

[复制链接]

该用户从未签到

23

主题

54

帖子

149

积分

菜鸟程序猿

Rank: 2

积分
149
发表于 2017-7-14 15:33:19 | 显示全部楼层 |阅读模式
本帖最后由 灰原哀 于 2017-7-14 15:34 编辑


根据Nick Gammon这位澳大利亚老兄,在 Power saving techniques for microprocessors(微处理器省电技术)文章,
于 Arduino UNO Rev 3 控制板执行底下的代码:

  1. voidsetup(){}
  2. voidloop(){}
复制代码

所测量到的消耗电流量:
  • 采用9V电池,接电源插孔供电,约消耗55 mA
  • 用5V电源供电,约消耗46.6 mA
若用最精简的准系统(barebone)形式,例如,在面包板上直接用ATmega828处理器和石英震荡器等少数零件组装的Arduino,仅消耗15.15 mA电流
因为Arduino控制板上的USB序列端口转换芯片以及电压调节元件,都会消耗电力。
毕竟Arduino控制板是「原型开发板」,其用意是提供一个方便、好用的微电脑控制实验工具。
实验成功之后,如果要长久保留作品或者需要节省电力,最好自制一个精简的Arduino板,或购买类似Arduino Pro Mini这种没有其他周边零件的板子。
Arduino的睡眠模式
Arduino像电脑和手机一样,也具备睡眠∕休眠∕待机功能。在睡眠状态下,系统几乎完全停止运作,只保留基本的侦测功能,因此只消耗少许电力。以电脑为例,在睡眠状态下,可被键盘按键或者网络信息唤醒。
底下的程序一开始就让微控器进入睡眠状态,下文将采用名叫”Enerlib”的程序库,简化睡眠设定程序:
  1. #include <avr/sleep.h>
  2. voidsetup()
  3. {
  4. // 設定採用“Power-down”睡眠模式
  5. set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  6. // 啟用睡眠模式
  7. sleep_enable();
  8. // 進入睡眠模式
  9. sleep_cpu();
  10. }
  11. voidloop(){}
复制代码
这段程序在UNO R3控制板上,约消耗32.9 mA电流;但是在精简的「准系统」Arduino板,仅仅消耗0.36mA(360μA)
ATMega328微控器具有六种睡眠模式,底下是依照「省电情况」排列的睡眠模式名称,以及Enerlib(注:Energy和Library,即:「能源」和「程序库」的缩写)程式库的五道函数指令对照表,排越后面越省电。
「消耗电流」字段指的是ATmega328处理器本身,而非整个控制板。
睡眠模式
Energy指令
中文直译
消耗电流
Idle
Idle()
闲置
15mA
ADC Noise Reduction
SleepADC()
模拟数位转换器降低噪声
6.5mA
Power-save
PowerSave()
省电
1.62mA
Standby
Standby()
待机
1.62mA
Extended Standby

延长待机
0.84mA
Power-down
PowerDown()
断电
0.36mA


微控器内部除了中央处理器(CPU),还有內存、模拟数位转换器、序列通信…等模块。越省电的模式,仍在运作中的模块就越少。
例如,在”Power-Down”(电源关闭)睡眠模式之下,微控器仅剩下外部中断看门狗定时器Watchdog Timer,参阅下文说明)仍持续运作。而在Idle睡眠模式底下,SPI,UART(也就是序列端口)、定时器、模拟数位转换器等,仍持续运作,只有中央处理器和闪存(Flash)时脉信号被停止。
时脉信号就像心跳一样,一旦停止时脉信号,相关的元件也随之暂停。各种睡眠模式的详细说明,请参阅ATmega328微控器的数据手册,第39页,「Power Management and Sleep Modes(电源管理与睡眠模式)」单元
采用Enerlib程序库设定睡眠模式
Enerlib程序库可简化Arduino睡眠模式的程序设定,请先下载Enerlib程序库并解压缩到Arduino的libraries文件夹
本实验程序的行为如下:
  • 启动时,每隔0.5秒点、灭三次位于第13脚的LED。
  • LED闪烁完毕后,进入“Power-down(断电)”睡眠模式
  • 当中断0(第2脚)的信号改变时,唤醒Arduino,再次闪烁LED三次,接着再进入睡眠模式。
请先把Arduino的数位脚2接高电位(5V或3.3V插座):
反复闪烁LED的基本代码如下:
  1. voidsetup(){
  2. Serial.begin(9600);
  3. pinMode(ledPin,OUTPUT);
  4. Serial.println("Running...");
  5. }
  6. voidloop(){
  7. digitalWrite(ledPin,!digitalRead(ledPin));
  8. delay(500);
  9. }
复制代码
负责闪烁LED的关键叙述是这一行:
设定唤醒Arduino的中断服务例程
修改上一节的程序,建立Energy程序物件,并加入中断服务例程叙述:
若Arduino处于睡眠状态,只要中断0脚位的信号改变,它就会被唤醒。然而,同一个程序其他叙述,也有可能需要接收中断0的信息。为此,Energy提供一个用于判断Arduino是否处于睡眠状态的WasSleep()函数,若是,它将传回true。
底下是修改后的wakeISR中断处理例程,若Arduino之前处于睡眠状态,则state变数值将是1,若是在执行过程发生中断信号,state值将是2:
透过state值,主程式将能得知中断的触发时机。补充说明,WasSleep()函数只能写在中断处理例程里面。
让Arduino睡眠的主程式
主程式循环如下,它将在闪烁LED三次后进入最省电的「断电」睡眠模式:
完整的示例代码如下:
  1. #include <Enerlib.h>
  2. Energyenergy;// 宣告"Energy"程式物件
  3. constbyteswPin=2;// 開關腳位
  4. constbyteledPin=13;// LED腳位
  5. bytetimes=0;// 記錄執行次數
  6. volatilebytestate=0;// 暫存執行狀態
  7. voidwakeISR(){
  8. if(energy.WasSleeping()){
  9. state=1;
  10. }else{
  11. state=2;
  12. }
  13. }
  14. voidsetup(){
  15. Serial.begin(9600);
  16. pinMode(ledPin,OUTPUT);
  17. pinMode(swPin,INPUT);
  18. digitalWrite(swPin,HIGH);
  19. attachInterrupt(0,wakeISR,CHANGE);// 附加中斷服務常式
  20. Serial.println("Running...");
  21. }
  22. voidloop()
  23. {
  24. if(state==1){
  25. Serial.println("Was sleeping...");
  26. }elseif(state==2){
  27. Serial.println("Was awake...");
  28. }
  29. state=0;
  30. digitalWrite(ledPin,!digitalRead(ledPin));
  31. delay(500);
  32. times++;
  33. Serial.println(times);
  34. if(times>5){
  35. times=0;
  36. Serial.println("Go to sleep...");
  37. energy.PowerDown();
  38. }
  39. }
复制代码
编译并上传程序到Arduino板之后,开启「序列端口监控视窗」,它将显示:
接着,把连接中断0的导线接到低电位(GND)
Arduino将被唤醒,并再次闪烁LED;笔者在LED闪烁的过程中,反复将中断0接高、低电位,「序列端口监控视窗」因而呈现如下的内容:
看门狗定时器简介
看门狗定时器(Watchdog Timer,简称WDT)是微控器内部的「当机」监控器,若微控器当掉了,它会自动重新启动微控器。其运作原理是,看门狗内部有个定时器,微处理器必须每隔一段时间,向看门狗发出一个信号,重设定时器值。
若看门狗迟迟没有收到微处理器的信号,定时器仍将继续倒数,直到计时值变成零,它就会认定微处理器已经当掉了,进而重新启动微处理器。
主程式可设定看门狗的定时器值,最短16ms,最长8s。



回复

使用道具 举报

  • TA的每日心情
    萌哒
    2018-5-17 16:00
  • 176

    主题

    275

    帖子

    1106

    积分

    超级版主

    Rank: 9Rank: 9Rank: 9

    积分
    1106
    发表于 2017-7-14 15:58:11 | 显示全部楼层
    看门狗~
    回复

    使用道具 举报

    该用户从未签到

    0

    主题

    43

    帖子

    46

    积分

    新手上路

    Rank: 1

    积分
    46
    发表于 2018-3-19 10:05:01 | 显示全部楼层
    分行了,谢谢。。。。。。。。
    回复

    使用道具 举报

    该用户从未签到

    0

    主题

    43

    帖子

    46

    积分

    新手上路

    Rank: 1

    积分
    46
    发表于 2018-3-19 10:10:11 | 显示全部楼层
    分享了,好的,谢谢
    回复

    使用道具 举报

    *滑动验证:
    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    快速回复 返回顶部 返回列表