2015年1月6日 星期二

Arduino power consumption reduction

要試著將我手上的Arduino Pro Mini功耗降到最低,我上網查了一些文章,
也做了一些實驗。結果就是讓板子在進到power down mode時,功耗為
18.7uA/3.3V。如果有那位大大知道如何讓功耗再往下降,請不吝指教。


在一開始我參考下面reference列的那個網址,在進到power down mode
的功耗是112uA,後來去修改register MCUCR去關掉BOD,功耗降到
106uA。後來再去修改register PRR,將Timer0~2,TWI,SPI,USART0,
ADC關掉,才讓功耗降到18uA。此外原本reference code是用函式
sleep_mode()來進到sleep mode,但這個函式會去打開一些前面關掉的
設定,所以要改用函式sleep_cpu()來進sleep mode。

為了去降低功耗,也需要硬體去配合,我將Arduino Pro Mini上的U2
LDO拆掉,還有紅色的LED1也拿掉。另外將INT0 pin接到一個button
,當系統開機後3秒,會自動進到sleep mode,這時再按下button,
就可以觸發 attachInterrupt事件,來喚醒MCU。
#include <avr/sleep.h>
#include <avr/power.h>       
void setup(void)
{
    // the GPIO comprise 3 part, B,C,D.
    DDRD &= B00000011;       // set Arduino pins 2 to 7 as inputs, leaves 0 & 1
    DDRB = B00000000;        // (RX & TX) as is set pins 8 to 13 as inputs
    PORTD = B00000100;      // disable pullups on pins 3 to 7
    PORTB = B00000000;      // disable pullups on pins 8 to 13
    pinMode(13,OUTPUT);      // set pin 13 as an output so we can use LED to monitor
    digitalWrite(13,HIGH);   // turn pin 13 LED on
    Serial.begin(9600); 
}
                //
void loop(void)
{
    // Stay awake for 1 second, then sleep.
    // LED turns off when sleeping, then back on upon wake.
    delay(3000);
    sleepNow();
}
                //
void sleepNow(void)
{
   Serial.println("Go to sleep");
    
    // Set pin 2 as interrupt and attach handler:
    attachInterrupt(0, pinInterrupt, LOW);
    delay(100);
    //
    // Choose our preferred sleep mode:
    set_sleep_mode(SLEEP_MODE_PWR_DOWN);
    //
    // Set sleep enable (SE) bit:
    sleep_enable();
    digitalWrite(13,LOW);   // turn LED off to indicate sleep
    // Put the device to sleep:
     MCUCR |= bit(BODSE) | bit(BODS); // timed sequence
     MCUCR = (MCUCR & ~bit(BODSE)) | bit(BODS);
  
     ADCSRA &= ~(1 << ADEN);
     PRR = 0xFF;
     sleep_cpu();
    //sleep_mode();

    // Upon waking up, sketch continues from this point.
    sleep_disable();
    Serial.println("sleep disable");
    digitalWrite(13,HIGH);   // turn LED on to indicate awake
    PRR = 0x00;
   //  delay(10000);
}
                //
void pinInterrupt(void)
{
    Serial.println("Interrupt");
    detachInterrupt(0);
}

下表為各個power mode,它有那些block是開著或關掉。


我們利用下面的函式就可以改變sleep mode,在各個sleep mode可以得到不同的功耗。
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
VCC=3.3V
ACTIVE_MODE                         8.0mA
SLEEP_MODE_IDLE                1.56mA
SLEEP_MODE_ADC                1,.02mA
SLEEP_MODE_PWR_SAVE    0.65mA
SLEEP_MODE_STANDBY       0.65mA
SLEEP_MODE_PWR_DOWN  18.7uA.





Reference.
http://www.engblaze.com/hush-little-microprocessor-avr-and-arduino-sleep-mode-basics/