最近在做一个低功耗的设备,发射红外来检测前面1米以内左右的地方是否有人,纽扣电池供电,需要持续工作至少两年,因此,要求设备工作电流在ua级别。
(1)红外发射接收
由于一般的红外发射接收(下图所示)都会比较耗电(几十ma),所以红外发射接收是不能一直打开的,需要每隔一段时间(30s)打开一次,检测是否有人,检测完毕后立即关闭红外发射接收。这样耗电的大户解决了,但是如果单片机一直处于工作状态,也就是循环程序里等待30s来进行红外发射检测的话,本身单片机也会耗电,达到ma的级别,这样的话,纽扣电池几百mah的电量也撑不了太久。
红外发射接收
(2)单片机休眠
考虑到单片机具有休眠功能,在不需要的时候可以MCU休眠,在唤醒的时候,打开红外并进行检测,检测完成后单片机继续休眠,这样就可以达到要求了,单片机休眠状态下,耗电很低,手册上一般都是几ua,完全符合要求,这里有一个问题就是,单片机的工期唤醒,一般情况下,单片机休眠后可以利用外部中断(电平、上升沿和下降沿)唤醒,但是设备中不存在这样的信号源能够定期(30s)唤醒单片机,因此这里需要单片机自己唤醒,也就是下面提到的看门狗唤醒。
(3)看门狗唤醒
AVR单片机的看门狗有三种模式,第一,系统复位,看门狗一般是用来监视程序是否正常运行的,当程序跑飞的时候,没有及时喂狗,看门狗就会强制单片机复位,达到重新运行程序的目的;第二,中断模式,在定时时间到的时候,会进入中断,这个中断会将掉电模式的单片机唤醒;第三,中断与系统复位(综合)。这里需要使用单片机的中断模式
(4)Arduino
Arduino本身是一个集成的开发平台,核心是一个avr单片机,优点在于平台集成了很多库函数,有很多外围器件,使用起来很方便,不需要使用者去了解单片机的寄存器,开发起来更快,但是做产品的话不一定能满足要求,最常用的就是Arduino
Uno了,核心是atmega328,单片机本身资源丰富,考虑到成本等因素,并不需要这么多资源,造成浪费,当然也有其他的型号的低成本的avr单片机,但本质上来说,自己做一块板子,再利用Arduino
IDE
编程,下来bootloader和程序,就不如直接进行单片机开发了。当然前期开发的话,还是适合的,之前的时候,学过一段时间51单片机,对avr还不是很熟悉,因此,这个低功耗设备,最开始还是使用Arduino
Uno
开发的,这个过程中遇到了各种问题,最后直接使用attiny13,进行单片机的开发,抛弃了Arduino。
(5)最终,休眠状态下设备耗电60多ua,达到了要求,后续将使用attiny13直接进行开发。
程序:(转自一个网友的文章,进行了一些注释)
#include
#include
volatile byte data=0;
int val;
void setup()
{
pinMode(2,OUTPUT);
pinMode(6,INPUT);
pinMode(7,OUTPUT);
pinMode(8,OUTPUT);
setup_watchdog(8);//设置看门狗超时时间
// 0=16ms, 1=32ms,2=64ms,3=128ms,4=250ms,5=500ms
// 6=1 sec,7=2 sec, 8=4 sec, 9= 8sec
ACSR=_BV(ACD);//关闭比较器ACD
ADCSRA=0;//关闭模数转换器ADC
Sleep_avr();//进入休眠模式
}
void loop()
{
if(data>=1){
data=0;
digitalWrite(7,HIGH);//红外
delay(50);
val = digitalRead(6);
if(val == LOW)//read led
{
digitalWrite(8,HIGH);//无线
digitalWrite(2,HIGH);//测试led
delay(2);
digitalWrite(2, LOW);//测试LED闪烁一次
delay(2850);
digitalWrite(8,LOW);//关闭无线
digitalWrite(7,LOW);//关闭红外发射器
}
digitalWrite(7,LOW);
Sleep_avr();
}
else
{
Sleep_avr(); //继续睡眠
}
}
//设置看门狗参数,输入参数为定时时间
void setup_watchdog(int ii){
byte bb;
if (ii > 9 ) ii=9;
bb=ii & 7;
if (ii > 7) bb
= (1<<5);
bb
= (1<
p="">
//开始设置看门狗中断
MCUSR &=
~(1<
p="">
WDTCSR
= (1<
p="">
(1<
p="">
//设置新的看门狗超时时间
WDTCSR = bb;
//设置为进入中断
WDTCSR= _BV(WDIE);
//看门狗唤醒后,从之前的程序继续执行
}
//超时后,只有在睡眠模式或空闲模式才会唤醒进入中断中断函数,除此之外,看门狗直接控制单片机复位
ISR(WDT_vect)
{
data++;
//继续执行睡眠之前的程序
}
//睡眠模式
void Sleep_avr()
{
set_sleep_mode(SLEEP_MODE_PWR_DOWN ); //设置睡眠模式
sleep_enable(); //使能睡眠模式
sleep_mode(); //进入睡眠模式,看门唤醒后在这里继续执行
}