文档章节

认识与实验Arduino的睡眠模式

simpower
 simpower
发布于 2014/11/02 13:42
字数 1737
阅读 2073
收藏 8

原文引自:http://swf.com.tw/?p=525

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

ARDUINO 代码复制打印

void setup () {}void loop () {}



所测量到的消耗电流量:

  • 採用9V电池,接电源插孔供电,约消耗55 mA

  • 用5V电源供电,约消耗46.6 mA



若用最精简的準系统(barebone)形式,例如,在麵包板上直接用ATmega828处理器和石英震盪器等少数零件组装的Arduino,仅消耗15.15 mA电流。

因為Arduino控制板上的USB序列埠转换晶片以及电压调节元件,都会消耗电力。

毕竟Arduino控制板是「原型开发板」,其用意是提供一个方便、好用的微电脑控制实验工具。实验成功之后,如果要长久保留作品或者需要节省电力,最好自製一个精简的Arduino板,或购买类似Arduino Pro Mini这种没有其他周边零件的板子。

Arduino的睡眠模式

Arduino像电脑和手机一样,也具备睡眠∕休眠∕待机功能。在睡眠状态下,系统几乎完全停止运作,只保留基本的侦测功能,因此只消耗少许电力。以电脑為例,在睡眠状态下,可被键盘按键或者网路讯息唤醒。

底下的程式一开始就让微控器进入睡眠状态,下文将採用名叫”Enerlib”的程式库,简化睡眠设定程式:

ARDUINO 代码复制打印

void setup () {  // 設定採用“Power-down”睡眠模式  set_sleep_mode (SLEEP_MODE_PWR_DOWN);  // 啟用睡眠模式  sleep_enable();  // 進入睡眠模式  sleep_cpu ();  } void loop () { }



这段程式在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资料夹:
Enerlib.png 

本实验程式的行为如下:

  • 启动时,每隔0.5秒点、灭三次位于第13脚的LED。

  •     LED闪烁完毕后,进入“Power-down(断电)”睡眠模式。

  •     当中断0(第2脚)的讯号改变时,唤醒Arduino,再次闪烁LED三次,接著再进入睡眠模式。



请先把Arduino的数位脚2接高电位(5V或3.3V插座):

sleep_hardware_setup.png 

反覆闪烁LED的基本程式码如下:

ARDUINO 代码复制打印

void setup() {  Serial.begin(9600);   pinMode(ledPin, OUTPUT);   Serial.println("Running...");} void loop() {  digitalWrite(ledPin, !digitalRead(ledPin));  delay(500);}



负责闪烁LED的关键叙述是这一行:

blink_statement.png 

设定唤醒Arduino的中断服务常式

修改上一节的程式,建立Energy程式物件,并加入中断服务常式叙述(广告一下,中断服务常式的说明,请参阅《超图解Arduino互动设计入门》的D-3页):
sleep_code_1.png 

若Arduino处于睡眠状态,只要中断0脚位的讯号改变,它就会被唤醒。然而,同一个程式其他叙述,也有可能需要接收中断0的讯息。为此,Energy提供一个用于判断Arduino是否处于睡眠状态的WasSleep()函数,若是,它将传回true。

底下是修改后的wakeISR中断处理常式,若Arduino之前处于睡眠状态,则state变数值将是1,若是在执行过程发生中断讯号,state值将是2:

wake_ISR.png 

透过state值,主程式将能得知中断的触发时机。补充说明,WasSleep()函数只能写在中断处理常式裡面。

让Arduino睡眠的主程式

主程式迴圈如下,它将在闪烁LED三次后进入最省电的「断电」睡眠模式:

sleep_code_2.png 

完整的范例程式码如下:

ARDUINO 代码复制打印

#include <Enerlib.h> Energy energy;             // 宣告"Energy"程式物件 const byte swPin = 2;      // 開關腳位const byte ledPin = 13;    // LED腳位byte times = 0;            // 記錄執行次數volatile byte state = 0;   // 暫存執行狀態 void wakeISR() {   if (energy.WasSleeping()) {    state = 1;  } else {    state = 2;  }} void setup() {  Serial.begin(9600);   pinMode(ledPin, OUTPUT);  pinMode(swPin, INPUT);  digitalWrite(swPin, HIGH);   attachInterrupt(0, wakeISR, CHANGE);  // 附加中斷服務常式   Serial.println("Running...");} void loop(){  if (state == 1) {    Serial.println("Was sleeping...");  } else if (state == 2) {    Serial.println("Was awake...");  }  state = 0;   digitalWrite(ledPin, !digitalRead(ledPin));  delay(500);  times ++;  Serial.println(times);   if (times > 5) {    times = 0;    Serial.println("Go to sleep...");    energy.PowerDown();  }}



编译并上传程式到Arduino板之后,开启「序列埠监控视窗」,它将显示:

run_sleep_1.png 

接著,把连接中断0的导线接到低电位(GND):

change_interrupt_state.png 

Arduino将被唤醒,并再次闪烁LED;笔者在LED闪烁的过程中,反覆将中断0接高、低电位,「序列埠监控视窗」因而呈现如下的内容:
run_sleep_2.png 

看门狗计时器简介

看门狗计时器(Watchdog Timer, 简称WDT)是微控器内部的「当机」监控器,若微控器当掉了,它会自动重新启动微控器。其运作原理是,看门狗内部有个计时器,微处理器必须每隔一段时间,向看门狗发出一个讯号,重设计时器值。

watchdog_timer.png 

若看门狗迟迟没有收到微处理器的讯号,计时器仍将继续倒数,直到计时值变成零,它就会认定微处理器已经当掉了,进而重新启动微处理器。

主程式可设定看门狗的计时器值,最短16ms,最长8s。Donal Morrissey写了一篇看门狗程式的介绍,以及沉睡8秒之后,切换LED状态的范例:Sleeping Arduino – Part 5 Wake Up Via The Watchdog Timer

本文转载自:http://www.geek-workshop.com/thread-8715-1-1.html

simpower
粉丝 28
博文 673
码字总数 50284
作品 0
海淀
程序员
私信 提问
加载中

评论(1)

s
smallfivecn
文中的说明图片是用什么软件做的?不错!
nrf2401 - 最廉价的2.4G无线通信方案

所有的使用Arduino 的朋友大多都会知道大名鼎鼎的XBee 这个土豪级的ZigBee 的通信模块。我们是做产品开发的,对于XBee这个产品可谓是又爱又恨,不得不承认他确实是一个好货,从做工到功能都无...

rayliang
2017/02/09
0
0
Arduino单片机使用和开发问题记录

Arduino单片机使用和开发问题记录 1、将程序上传到板子时Arduino IDE提示“avrdude: stk500_getsync(): not in sync: resp=0x00” 网上查遇到这个问题的人比较多,有说驱动问题的,有说IDE设...

青夜之衫
2017/12/05
0
0
如何用 JavaScript 控制 Arduino?

Arduino 运行 C 语言,而主控端运行 JavaScript,一次要编写和维护两种程序。既然浏览器和服务器都用 JavaScript,若 Arduino 也能用 JavaScript 控制,那岂不完美? 这就是 Rick Waldron 设...

tangxiaoyin
2017/09/30
0
0
Arduino教程汇总

原始链接:Arduino教程汇总贴 (有更新) 初识arduino http://www.arduino.cn/thread-1083-1-1.html 常见arduino版本比较 http://www.arduino.cn/thread-1192-1-1.html arduino驱动安装方法 ht......

小堤
2013/05/26
25.4K
15
呼吸灯的深入研究

http://sean.voisen.org/blog/2011/10/breathing-led-with-arduino/ Re-creating the "breathing" LED 呼吸灯的逆向工程 October 31, 2011 Perhaps it’s not surprising, but Apple has a p......

BetaYuan
2016/10/31
68
0

没有更多内容

加载失败,请刷新页面

加载更多

记一次项目启动报java.lang.StackOverflowError

项目是spring boot,之前没有问题,突然有一次debug方式启动的时候报这个错误。 因为其他同事没有问题,线上也没有问题,所以先排除了是代码问题。 开始以为电脑开的软件太多,然后给jvm的内存...

chro008
27分钟前
12
0
idea 2019.2免费激活码

亲测有效到2020.6 812LFWMRSH-eyJsaWNlbnNlSWQiOiI4MTJMRldNUlNIIiwibGljZW5zZWVOYW1lIjoi5q2j54mIIOaOiOadgyIsImFzc2lnbmVlTmFtZSI6IiIsImFzc2lnbmVlRW1haWwiOiIiLCJsaWNlbnNlUmVzdHJpY3Rpb......

Iverson58
35分钟前
9
0
移动APP开发中的重要注意事项

您的移动app在变化吗?如果没有,请确保遵循这些提示进行移动app开发。大多数行业的IT领导者都优先考虑劳动力和消费者的移动性。实现成功的移动app开发具有挑战性,涉及在app功能开发的基础上...

a429011717
42分钟前
6
0
Qt编写自定义控件69-代码行数统计

一、前言 代码行数统计主要用来统计项目中的所有文件的代码行数,其中包括空行、注释行、代码行,可以指定过滤拓展名,比如只想统计.cpp的文件,也可以指定文件或者指定目录进行统计。写完这...

飞扬青云
今天
12
0
驰骋工作流引擎-ccflow关于 “ 是否自动计算未来的处理人”的功能变更

关键字:流程未来节点处理人 工作流快速开发平台 工作流流设计 业务流程管理 asp.net 开源工作流 业务背景:一个流程在启动起来后,是可以对一些节点计算出来处理人是谁,流程的走向。对于另...

孟娟
今天
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部