パワーセービングスリープモードでArduinoメガを起こす方法は?

私は、ルーチンが実行を終了した後にスリープモードを使用してデバイスをオフにしています。割り込みを使用して33ミリ秒ごとにスリープモードを起動します。基本的には、ルーチンが33ミリ秒未満で完了すると、残りの時間にプロセッサがシャットダウンして電力を節約できるため、消費電力の削減につながります。私はcurrenltyが下記の sleepNow()関数でデバイスをオフにすることができましたが、私がプログラムした割り込みは機能していないようです。プログラムは単に眠りにつき、決して目が覚めることはありません。私は間違って何をしていますか?

#include 
#include 
#include 

const uint16_t PERIOD = 2150;

void setup()
{
  noInterrupts();
  TCCR1A = 0;           //undo the timer config done...
  TCCR1B = 0;           //...by the Arduino core library
  TCNT1 = 0;            //reset the timer
  OCR1A = PERIOD - 1;   //set the period
  TIMSK1 = _BV(OCIE1A); //enable TIMERx_COMPA interrupt
  TCCR1B |= (1 << CS12);//...and set the prescaler
  interrupts();

  Serial.begin(9600);
}

ISR(TIMER1_COMPA_vect)
{
  Serial.println(millis());  
}

void loop()
{
  Serial.println("Program is on");
  Serial.flush();
  sleepNow();
}

void sleepNow()
{

   //Choose our preferred sleep mode:
    set_sleep_mode(SLEEP_MODE_PWR_SAVE);

   //Set sleep enable (SE) bit:
    sleep_enable();

   //Put the device to sleep:
    sleep_mode();

   //Upon waking up, sketch continues from this point.
    sleep_disable();

}
1
タイマー1はあなたを目覚めさせません。なぜなら、それは眠っているからです!タイマー2だけが SLEEP_MODE_PWR_SAVE で起きています。
追加された 著者 Sprogz,
シリアルポートは割り込みを使用してデータを送信し、ISR内部でブロックされるため、ISRからの印刷は避けてください。
追加された 著者 Sprogz,
いいえ、どこでも割り込みを設定できます。あなたはおそらくそれをしながら無関係のバグを導入しました。
追加された 著者 Sprogz,
問題は、私がそれを行うときに ISR を残さずにループを再入力することです。それは時間を無限に印刷するだけです。以前はIDLEとTimer 1を使っていましたが、以前はこれを使用していませんでした。
追加された 著者 Cicely Mason,
変わった点は、printステートメントを ISR 関数の外に移動すると、プログラムが正常に動作することです。
追加された 著者 Cicely Mason,
さて、それは理にかなっていますが、ちょっとしたハウスキーピングに関する質問があります。私は、割り込み設定を別の方法に移動しようとした後、セットアップ方法から呼び出すと、割り込みが機能しなくなりました。あなたはセットアップ方法であなたの割り込みをセットアップする必要があるのでそれですか?
追加された 著者 Cicely Mason,

1 答え

それは確かに非常に深い眠りに入ることを救うために魅力的です 電源は、しかし、あなたはまだ目を覚ます必要がありますどのような周辺機器 ウェイクアップソースとして使用します。 16ビットタイマを使用する場合は、 SLEEP_MODE_IDLE 以外の選択肢。

しかしそれはそれほど悪くないかもしれません。 IDLEモードでは、 あなたが使用していない周辺機器をクロックする(したがってスリープさせる)。または多分 すべてを寝てから、必要なものを少しだけ目を覚ましてください。この は、 power _ * _ disable()および power _ * _ enable() の機能の。

以下の編集コードでは、Timer 1を除くすべての周辺機器は無効になっています CPUはスリープします。 USARTは、必要な時間だけ有効になります そのメッセージを送る:

#include 
#include 
#include 
#include 

const uint16_t PERIOD = 2150; //34.4 ms

void setup()
{
 //Disable all but the needed peripherals.
  power_all_disable();
  power_timer1_enable();

 //This is for debug pulses.
  pinMode(22, OUTPUT);

 //Configure Timer 1 to wake us up every 34.4 ms.
  TCCR1A = 0;           //undo the timer config done...
  TCCR1B = 0;           //...by the Arduino core library
  TCNT1 = 0;            //reset the timer
  OCR1A = PERIOD - 1;   //set the period
  TIMSK1 = _BV(OCIE1A); //enable TIMERx_COMPA interrupt
  TCCR1B = _BV(WGM12)   //CTC mode, TOP = OCR1A
         | _BV(CS12);   //...and set the prescaler /256

  Serial.begin(9600);
}

ISR(TIMER1_COMPA_vect)
{
 //Send a debug pulse.
  digitalWrite(22, HIGH);
  _delay_ms(2);
  digitalWrite(22, LOW);
}

void loop()
{
 //Enable the USART only while needed.
  power_usart0_enable();
  Serial.println("Program is on");
  Serial.flush();
  power_usart0_disable();

 //And go to sleep in IDLE mode.
  sleep_mode();
}

ISRはシリアルポートには印刷されません。 スコープで監視するデバッグパルスを送信します。これはから削除する必要があります 生産コード。この遅延はavr-libc関数を使って達成されます 標準のArduino delay()が機能しないため、 _delay_ms() 無効になっているタイマ0に依存します。

2
追加された
@AngelLockhart:安全な場所にいたい場合は、使用しない周辺機器だけを無効にすることができます。 IDLEモードの良い点は、目を覚ますことができることです。 ;-) データシートには、セクション11.1に、各スリープモードで使用可能なウェークアップソースを持つテーブルがあります。すべての16ビットタイマを含むほとんどのペリフェラル(「その他のI/O」)は、IDLEモードでのみ使用可能であることがわかります。
追加された 著者 Sprogz,
しかし、Arduinoの専門家ではないので、プログラムの開始時に power_all_disable(); で周辺機器を無効にしているので、これはプログラムの機能には影響しません。新しいバグの一束?最後に、私が非常に深い睡眠を使用して、上記のコードで起きたら、 IDLE モードの省電力オプションを切り替えることのメリットは何ですか?
追加された 著者 Cicely Mason,
また、なぜ16ビットタイマーを使用して IDLE を使用するのでしょうか?
追加された 著者 Cicely Mason,