Advertisement
Guest User

Untitled

a guest
Feb 21st, 2020
128
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.68 KB | None | 0 0
  1. /*
  2.  * スリープへの移行とボタン押下による復帰
  3.  * https://www.hiramine.com/physicalcomputing/atmega328/sleepbuttonwakeup.html
  4.  */
  5.  
  6. #include <avr/sleep.h>
  7.  
  8. #define LEDPIN    (13)
  9. unsigned long bootTime;
  10.  
  11. void setup() {
  12.   Serial.begin(115200);
  13.   Serial.println("-- Sleep Test Start --");
  14.   // スリープ中の消費電力を最小限に抑えるために、
  15.   //  i) 出力ピンは電流を供給なし
  16.   // ii) 入力ピンは一定
  17.   // にする。
  18.   // i) ii) を実現する簡単な方法は、内部プルアップ抵抗を有効にすること。
  19.   for ( int i = 0; i < 20; i++ )
  20.   {
  21.     pinMode(i, INPUT_PULLUP);
  22.   }
  23.  
  24.   // LEDピンのセットアップ
  25.   pinMode( LEDPIN, OUTPUT );
  26.   digitalWrite( LEDPIN, LOW );
  27.   bootTime = millis();
  28.   Serial.println("Wake Up!");
  29.   Serial.print("Boot Time: ");
  30.   Serial.println(bootTime);
  31. }
  32.  
  33. void loop() {
  34.   Serial.print("Now Time  : ");
  35.   Serial.println(millis());
  36.  
  37.   // リセットかスリープモードへ移行
  38.   if ((millis() - bootTime) > 300000) { // 5分経ったらリセット
  39.     Serial.println("Reboot!");
  40.     delay(100);
  41.     software_reset();
  42.   } else if ((millis() - bootTime) > 60000) { // 1分経ったらスリープ
  43.     Serial.println("Good Night!");
  44.     delay(100); // println が終わるまでの時間調整
  45.     Sleep();
  46.   } else {
  47.     blink();
  48.   }
  49. }
  50.  
  51. void blink() {
  52.   for (int i = 0; i < 2; i ++) {
  53.     digitalWrite(LEDPIN, HIGH);
  54.     delay(100);
  55.     digitalWrite(LEDPIN, LOW);
  56.     delay(400);
  57.   }
  58.   delay(1000);
  59. }
  60.  
  61. void software_reset() {
  62.   asm volatile ("jmp 0");
  63. }
  64.  
  65. // 外部割り込みの結果呼び出される関数
  66. void wakeUpNow() {
  67.   bootTime = millis();
  68.   Serial.println("Good Morning!");
  69.   Serial.print("Wake Time : ");
  70.   Serial.println(bootTime);
  71.   delay(30000); // 時間調整。30秒ととても大きな数字だけどこれだとバグらなかった。
  72. }
  73.  
  74. void Sleep() {
  75.   // ① アナログ・デジタル・コンバータ機能を無効にする(少しでも電力消費を抑えるため)
  76.   byte adcsra_old = ADCSRA;   // ADC Control と Register Aの設定値の以前の値を保持。
  77.   ADCSRA = 0;     // アナログ・デジタル・コンバータ機能の無効にする。
  78.  
  79.   // ② スリープモードを設定する(②⑤⑧でセット)
  80.   set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  81.  
  82.   // ③ 割り込み機能を無効にする(④⑤の処理を確実に実行するため)
  83.   noInterrupts(); // cli()でも同じ
  84.  
  85.   // ④ 電圧降下検出機能を無効にする(少しでも電力消費を抑えるため)
  86.   sleep_bod_disable();
  87.  
  88.   // ⑤ スリープ機能を有効にする(②⑤⑧でセット)
  89.   sleep_enable();
  90.  
  91.   // ⑥ 割り込み機能を有効にする(④⑤の処理を実行したので元に戻す)
  92.   interrupts();   // sei()でも同じ
  93.  
  94.   // ⑦ 外部割り込み条件を設定する(Wakeするための外部割り込み条件の割込設定)
  95.   attachInterrupt(0, wakeUpNow, LOW); // INT0端子(2番ピン)の立ち下がりで割り込み発生。wakeUpNow関数が呼ばれる。
  96.  
  97.   // ⑧ スリープ実行(②⑤⑧でセット)
  98.   sleep_cpu();
  99.  
  100.   // (⑧によってスリープに移行する。⑦で設定した外部割り込みでWakeし、⑨の処理が実施される)
  101.  
  102.   // ⑨ スリープ機能を無効にする(⑦で設定した外部割り込みでWakeしたので、スリープを無効にする)
  103.   sleep_disable();
  104.  
  105.   // ⑩ 外部割り込み条件の設定を解除する(Wakeしたので)
  106.   detachInterrupt(0);
  107.  
  108.   // ⑪ アナログ・デジタル・コンバータ機能を有効にする(Wakeしたので)
  109.   ADCSRA = adcsra_old;
  110. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement