Program Resource

開発者向け各種コード、アルゴリズム、リソース情報ライブラリ もしくはねふぁの覚え書き

以前の記事でRTCモジュールを使った基本的な時計の使い方を紹介したが、今回はアラーム機能を使った割り込みによる定期処理を行う方法について説明する。

DSC03441

Arduinoで例えば1分毎に何らかの処理を行いたい場合、loop処理内でdelay関数で60000ms程度待機させる方法もあるが、バッテリー駆動させる場合は電力の無駄だし、delayと処理を繰り返すたびに少しずつずれが生じてくる。

バッテリーを節約する方法としてWatchdogタイマーとSleepを使う方法もあるが、最長8秒のためインターバルが分や時間単位になるとやや処理が面倒になってくる。

そこでDS3231系のRTCモジュールのアラーム機能を使うと、毎秒、毎分、毎時間、毎日、毎週等の単位で簡単に割り込みを起こし定期処理を行う事が出来る。RTCモジュールなので、Arduinoの簡易時計機能よりも正確である。

配線は通信用のSCL/SDAと、割り込み用にSQWピンを使う。SQWピンは波形生成と共通のため、アラーム機能を使う場合は波形生成の機能はオフにしておく必要がある。下記配線例はArduino MEGA。Arudino UNOであればPin 2もしくは3をSQWと繋ぐ。

rtcmodule

ライブラリは下記ライブラリを使用。

https://github.com/JChristensen/DS3232RTC

秒単位で指定したい場合はAlarm 1を、分単位で指定する場合はAlarm 2を使う。RTCモジュールの時計はすでに合わせてあるものとする。

使い方は簡単で、attachInterruptで割り込みが変化した際に実行する関数を指定(RTCの割り込みはLOWになるので、FALLING指定)、setAlarmで割り込みのタイミングを指定、alarmInterrupt関数でアラームを有効化、alarm関数で割り込みフラグをリセットする。

下記サンプルコードは毎分00秒にRTCから割り込みを発生させ、シリアルポートに時刻を出力後電力セーブモードに入るコードである。

//Reference :
//https://github.com/JChristensen/DS3232RTC
//http://forum.arduino.cc/index.php?topic=109062.0
//http://donalmorrissey.blogspot.jp/2010/04/sleeping-arduino-part-5-wake-up-via.html
//http://easylabo.com/2015/04/arduino/8357/

#include <DS3232RTC.h>    //http://github.com/JChristensen/DS3232RTC
#include <Time.h>         //http://www.arduino.cc/playground/Code/Time
#include <Wire.h>         //http://arduino.cc/en/Reference/Wire (included with Arduino IDE)
#include <avr/sleep.h>
#include <avr/power.h>

bool rtcint = false;

void setup(void)
{
  //clear all
  RTC.alarmInterrupt(1, false);
  RTC.alarmInterrupt(2, false);
  RTC.oscStopped(true);

  //sync time with RTC module
  Serial.begin(9600);
  setSyncProvider(RTC.get);   // the function to get the time from the RTC
  if (timeStatus() != timeSet)
    Serial.println("Unable to sync with the RTC");
  else
    Serial.println("RTC has set the system time");
  Serial.flush();

  //show current time, sync with 0 second
  digitalClockDisplay();
  synctozero();

  //set alarm to fire every minute
  RTC.alarm(2);
  attachInterrupt(4, alcall, FALLING);
  RTC.setAlarm(ALM2_EVERY_MINUTE , 0, 0, 0);
  RTC.alarmInterrupt(2, true);
  digitalClockDisplay();
}

void loop(void)
{
  //process clock display and clear interrupt flag as needed
  if (rtcint) {
    rtcint = false;
    digitalClockDisplay();
    RTC.alarm(2);
  }

  //go to power save mode
  enterSleep();
}

void synctozero() {
  //wait until second reaches 0
  while (second() != 0) {
    delay(100);
  }
}

void alcall() {
  //per minute interrupt call
  rtcint = true;
}

void digitalClockDisplay(void)
{
  // digital clock display of the time
  setSyncProvider(RTC.get); //sync time with RTC
  Serial.print(hour());
  printDigits(minute());
  printDigits(second());
  Serial.print(' ');
  Serial.print(day());
  Serial.print(' ');
  Serial.print(month());
  Serial.print(' ');
  Serial.print(year());
  Serial.println();
  Serial.flush();
}

void printDigits(int digits)
{
  // utility function for digital clock display: prints preceding colon and leading 0
  Serial.print(':');
  if (digits < 10)
    Serial.print('0');
  Serial.print(digits);
}

void enterSleep(void)
{
  //enter sleep mode to save power
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  sleep_enable();
  sleep_mode();

  sleep_disable();
  power_all_enable();
}

電子ペーパーディスプレイと組み合わせた時計作成も参考に。
[GPG] Arduino用RTCモジュール DS3231 / AT24C32
[GPG] Arduino用RTCモジュール DS3231 / AT24C32


ArduinoでDS3231 RTCモジュールを使った定期処理」 に1件のコメント

  1. cordylus より:

    はじめまして

    当方、Arduino unoとDS3231を用いて、こちらの定期処理を行いたいと考えております。初歩的な質問なのですが、DS3231の時計合わせはどのようにするのでしょうか。お時間ありましたら、教えていただけると大変助かります。どうぞ宜しくお願い致します。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です


*