LoginSignup
1
0

ATtiny202のスリープ機能を試す

Last updated at Posted at 2024-02-16

はじめに

本記事ではATtiny202のスリープ機能について、自分なりに使い方をまとめてみました。タクトスイッチ1個を使い、スリープ状態への移行と復帰を制御するような具体例で試してみます。以前の記事に引き続き、少しでも参考になりましたら幸いです。
picture.jpg

開発環境

  • Windows 11 Home 22H2
  • Arduino IDE 1.8.19
  • megaTinyCore 2.6.10

回路構成

PA6にLED、PA7にタクトスイッチを接続しました。書き込み方法などは以前の記事でも解説しているため、今回は割愛します。
breadboard.png

クロック周波数

クロック周波数はデフォルトだと20MHzに設定されているため、低電圧検出機能が4.2V付近で作動します。今回は乾電池2本で駆動することを想定しているため、このままだと正しく動作しません。そこで、閾値を最小値の1.8Vにまで下げてみたところ、クロック周波数も5MHz以下にまで落とす必要がありました。なお、設定した項目を適用するためにはヒューズビットを書き換える必要があります。Arduino開発環境を利用している場合はブートローダの書き込みを実行するだけなので簡単です。
screenshot.png
クロック周波数は動作時の消費電流に影響します。しかし、スリープ時はCPUも停止するため、スリープ時の消費電流とは無関係です。

スリープ機能

以下の表で示すようにモードとしては3種類が用意されているみたいです。今回は最も消費電流が小さくなるモードを選択しました。RTCなど、ほとんどの機能は停止します。また、スリープ状態から復帰する手段としては3種類の中から選べます。今回は外部割り込みを選択しました。ピン状態の立ち下がり、立ち上がり、その両方を含む変化、あるいはローレベルのいずれかを検出できます。ATtiny202では全ての入出力ピンが外部割り込みに使用できますが、注意としては非同期で検出できる入出力ピンがPA2とPA6に限られている点です。つまり、その他はピン状態の変化、あるいはローレベルしか検出できません。
table.png
復帰に要する時間はオシレータの起動に要する時間とペリフェラルへ供給されるクロック信号6回に要する時間との合計です。
start-up_time.png

プログラム

タクトスイッチを1秒くらい押し続けるとスリープ状態に移行します。そして、タクトスイッチを再び押すとPA7がローレベルとなり、外部割り込みが発生してスリープ状態から復帰します。押し続ける時間により判定しているため、条件分岐を増やせば複数の機能を割り当てることも可能です。

sleep.ino
#include <avr/sleep.h>

#define PIN_LED PIN_PA6
#define PIN_BUTTON PIN_PA7


//the interrupt is handled after waking up here
ISR(PORTA_PORT_vect) {
  PORTA.INTFLAGS = PORT_INT7_bm; //clear the interrupt flag on PA7
}

void sleep() {
  set_sleep_mode(SLEEP_MODE_PWR_DOWN); //select the power down sleep mode

  noInterrupts(); //disable all interrupts
  sleep_enable();
  interrupts(); //enable all interrupts

  PORTA.PIN7CTRL = PORT_PULLUPEN_bm | PORT_ISC_LEVEL_gc; //pull up PA7, trigger on low level
  sleep_cpu(); //actually go to sleep here
  
  //the program will continue after waking up from here
  sleep_disable();
  PORTA.PIN7CTRL = PORT_PULLUPEN_bm; //pull up PA7, turn off the pin change interrupt
}

void setup() {
  pinMode(PIN_LED, OUTPUT);
  pinMode(PIN_BUTTON, INPUT_PULLUP); //pull up PA7

  //pull up unused pins to minimize current consumption
  pinMode(PIN_PA1, INPUT_PULLUP);
  pinMode(PIN_PA2, INPUT_PULLUP);
  pinMode(PIN_PA0, INPUT_PULLUP);
  pinMode(PIN_PA3, INPUT_PULLUP);

  digitalWrite(PIN_LED, HIGH); //turn on the LED
}

void loop() {
  static unsigned long lastTime;
  static int lastState = HIGH;
  
  int state = digitalRead(PIN_PA7); //read the state of the button

  //detect the state change
  if (state != lastState) {
    if (state == LOW) { //the button is pressed
      lastTime = millis();
    } else { //the button is released
      unsigned long interval = millis() - lastTime;

      //the button is pressed for more than 1 second
      if (interval > 1000) {
        digitalWrite(PIN_LED, LOW); //turn off the LED
        sleep(); //go to sleep
        digitalWrite(PIN_LED, HIGH); //turn on the LED
      }
    }
  }
  lastState = state;
  delay(10);
}

未使用ピンは内部プルアップを有効化し、電位を固定することで意図しない発振を防ぎ、より消費電流を抑えることができます。

検証

まずは動作時の消費電流を測定してみたところ、約2.735mAとなりました。LEDには約1.630mAの電流が流れていたのでATtiny202には差し引き約1.105mAの電流が流れていた計算となります。クロック周波数は5MHzです。また、検証時は単3形の乾電池2本を電源として使用し、電圧は約2.478Vでした。
active_mode.jpg
次にスリープ時の消費電流を測定してみたところ、なんと約0.1uAとなりました。
sleep_mode.jpg
このように消費電流を大幅に抑えることができました。起動時間も短く、非常に優秀だと思います。

おわりに

例えばLR44など、容量が100mAhくらいの小型なボタン電池2個で駆動することを仮定した場合、理論上は約114年も持つ計算となります。もちろん、動作時の消費電流を減らしていく工夫は必要ですが、スリープ時の消費電流は無視できるくらい小さいことが検証できました。活用の幅も広がりそうです。

参考文献

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0