2015年2月28日土曜日

AVRと赤外線センサを使った回路の省電力化

赤外線受信モジュールを使った AVR の回路を、コイン電池 CR2032 でどれくらいの時間駆動できるかを測定した。

赤外線センサー GP1UXC41QS は 0.3~0.6[mA] の電流を消費する。コイン電池 CR2032 の容量が 225[mAh] とすると、センサーの消費電力だけで 375時間=15日 くらいで電池がなくなってしまう。これに AVR マイコンの消費も加わるので、実際はもっと短くなる。

そこで、省電力化のために、通常は AVR マイコンをスリープ状態にして、ウォッチドッグタイマ割り込みで定期的に起動し、赤外線センサーの入力を見て、赤外線を受信していなければまたスリープすることにした。 赤外線センサーの電源は、AVR マイコンの出力ピンから取り、スリープ中は OFF にする。

この方法はウォッチドッグタイマ割り込みのある AVR でしかできない。今回は Tiny10 でテストした。メインクロックは内蔵 CR で 1[MHz] とする。

スリープ後 125[ms] にウォッチドッグ割り込みが発生するように指定して、割り込みが発生したら IR センサの電源を入れて 1[ms] 待つ (センサの出力の安定を待つため)。その後 IR センサの出力を読んで、L (赤外線信号あり) ならコードを実行、H (赤外線信号なし) ならスリープする。これの繰り返しを行う。

10Ωの抵抗は電流測定用。この両端の電圧をオシロで測定して、消費電流を測定した。

結果は、1秒間に約7回、1.06[ms] の間、最大約 6[mA] のパルス状の電源電流が流れた(オシロのピーク値測定モードで測定したので、実際の消費電流はこれより小さいと思う)。それ以外 (スリープ中) の消費電流はノイズに埋もれて測定できなかったが、アナログテスターでの測定とデータシートによると、約 4[μA] くらいと思われる。

平均すると、常時 50[μA] 程度の電流が流れているのと等価になる。容量 225[mAh] の CR2032 なら 4500時間=187日間動作するはず。あくまで理想上の計算なので、実験してみないとわからないが。

割り込み周期を変更したり、待ち時間を短縮すれば、さらに消費電力化も可能と思われる。

ちなみに家電用の赤外線リモコンの場合、1ビットを表すパルス1個は 1~4[ms] 程度の長さ。信号全体でも 100~200 [ms] 程度のことが多いので、今回の方法の速度では、信号全体を取り込むことはできない (割り込みで赤外線信号に気付いた時は、すでに信号の前半を取りこぼしてしまっている)。信号が繰り返し送られることを前提として受信するか、リーダーが長い特殊な赤外線フォーマットで通信する必要がある。

ウォッチドッグタイマ割り込みで定期的にIRセンサを起動 (Tiny10, 1MHz)。
PB0 から IR センサの電源を出力する。10Ωの抵抗は電流測定用。




// 消費電力測定: Tiny10 用
#include <avr/io.h>
#define F_CPU 1000000UL
#include <util/delay.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <avr/wdt.h>

// 起動前にウォッチドッグを禁止
uint8_t mcusr_mirror __attribute__ ((section (".noinit")));
void get_mcusr(void) __attribute__((naked)) __attribute__((section(".init3")));
void get_mcusr(void) {
  mcusr_mirror = RSTFLR;
  RSTFLR = 0;
  wdt_disable();
}

// ウォッチドッグ割り込みハンドラ
EMPTY_INTERRUPT(WDT_vect)

int main(void) {
  DDRB = 0b11111011; // PORTB 0,1,3 を出力に
  PUEB = 0b00000000; // プルアップしない

  // ウォッチドッグタイマ割り込みを有効にして(WDIE=1)
  // ウォッチドッグリセットは発生しないようにする(WDE=0)(125ms)
  RSTFLR = 0;
  WDTCSR = _BV(WDIE) | _BV(WDP1) | _BV(WDP0) ;
  
  sei();
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);

  while(1) {
    PORTB |= _BV(PB0); // IR 電源 ON
    _delay_ms(1);      // 1[ms] 待つ
    if ((PINB & _BV(PB2)) == 0) {
      PORTB &= ~_BV(PB0);  // IR 電源 OFF
      // ここに赤外線を受信したときに実行したい処理を書く
    }
    PORTB &= ~_BV(PB0);  // IR 電源 OFF
    wdt_reset();
    WDTCSR |= _BV(WDIF);
    sleep_mode();
  }
}


パルス状に見えるのは1秒間に約7回(144[ms]間隔)の電源 ON。
それ以外の期間はスリープ。スリープ中の測定ノイズが激しい。
オシロはピーク検出モードにしている。

1回のパルスを拡大すると、長さは1.06[ms]。
この期間、最大約 6[mA] の電流が流れている。