1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ArduinoのRTCとNTPを使って目覚まし時計を作る

Last updated at Posted at 2025-07-31

概要

Arduino Uno R4 WiFiでインターネットから現在時刻を取得して特定の時間にアラームが鳴るシステムをつくる

開発環境

  • Window11 Home 24H2(OSビルド 26100.4770)
  • エディタ:Arduino IDE 2.3.6

使用した機器

表1:使用した機器
機器名 型番 個数
Arduino Uno R4 WiFi AbX00087 1
ブレッドボード EIC-102J 1
ブレッドボード用ダイナミックスピーカー MSI28-12R 1
炭素被膜抵抗(1/2 W 22 Ω) CFS50J22RB 1
ジャンパーワイヤー(オス-オス) BBJ-65 1

使用したライブラリ

  • RTC.h
    Real Time Clock.時刻の設定や取得,アラームなどの割り込み処理を行う.
  • NTPClient.h
    Network Time Protocol.NTPサーバから現在時刻を取得する.
  • WiFiC3.h
  • WiFiS3.h
  • WiFiUdp.h
    WiFiC3.h,WiFiS3.h,WiFiUdp.hに関しては公式のドキュメントがなさそうだったが,ネット接続やUDPでの通信に必要なものらしい.

作っていて便利だったショートカット

今まではMacのトラックパッドでそこまで気にならなかったため使ってなかったが,いちいちキーボード→マウスを繰り返すのが面倒だったのでショートカットを使ってみた.わざわざここに書くようなものでもないが一応書いておく.ショートカットは使ったほうがいいなあ.

  • Ctrl + U:Arduinoにアップロード
  • Ctrl + Shift + M:シリアルモニタの開閉

回路図

arduino_speaker.png

スケッチ

基本的にはArduino Uno R4 WiFiのRTCドキュメントにあるものをそのまま利用している.時刻の取得や割込み処理の大体の説明はここを読めばなんとなくわかると思う.またコメントはできる限りサンプルコードのままにしてある.

ntp.ino
#include "RTC.h"

#include <NTPClient.h>

#if defined(ARDUINO_PORTENTA_C33)
#include <WiFiC3.h>
#elif defined(ARDUINO_UNOWIFIR4)
#include <WiFiS3.h>
#endif

#include <WiFiUdp.h>
#include "arduino_secrets.h" 

///// set parameters for the alarm /////
const int alarmpin = 3;
const int freq = 1800;
const int t = 50;
const int interval = 2000;
bool ledState = false;
bool alarmFrag = false;

///// set alarm time(HH/MM/SS) /////
const int matchhour = 15;
const int matchmin = 17;
const int matchsec = 0;


/////// please enter your sensitive data in the Secret tab/arduino_secrets.h
char ssid[] = SECRET_SSID;        // your network SSID (name)
char pass[] = SECRET_PASS;    // your network password (use for WPA, or use as key for WEP)

int wifiStatus = WL_IDLE_STATUS;
WiFiUDP Udp;
NTPClient timeClient(Udp);
RTCTime currentTime;

void printWifiStatus() {
  // print the SSID of the network you're attached to:
  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());

  // print your board's IP address:
  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");
  Serial.println(ip);

  // print the received signal strength:
  long rssi = WiFi.RSSI();
  Serial.print("signal strength (RSSI):");
  Serial.print(rssi);
  Serial.println(" dBm");
}

void connectToWiFi(){
  // check for the WiFi module:
  if (WiFi.status() == WL_NO_MODULE) {
    Serial.println("Communication with WiFi module failed!");
    // don't continue
    while (true);
  }

  String fv = WiFi.firmwareVersion();
  if (fv < WIFI_FIRMWARE_LATEST_VERSION) {
    Serial.println("Please upgrade the firmware");
  }

  // attempt to connect to WiFi network:
  while (wifiStatus != WL_CONNECTED) {
    Serial.print("Attempting to connect to SSID: ");
    Serial.println(ssid);
    // Connect to WPA/WPA2 network. Change this line if using open or WEP network:
    wifiStatus = WiFi.begin(ssid, pass);

    delay(10000);
  }

  Serial.println("Connected to WiFi");
  printWifiStatus();
}

void setup(){
  Serial.begin(9600);
  pinMode(alarmpin, OUTPUT);
  while (!Serial);

  connectToWiFi();
  RTC.begin();
  Serial.println("\nStarting connection to server...");
  timeClient.begin();
  timeClient.update();

  // Get the current date and time from an NTP server.
  // Change the time zone offset to your local one.
  auto timeZoneOffsetHours = 9;
  auto unixTime = timeClient.getEpochTime() + (timeZoneOffsetHours * 3600);
  Serial.print("Unix time = ");
  Serial.println(unixTime);
  RTCTime timeToSet = RTCTime(unixTime);
  RTC.setTime(timeToSet);

  RTCTime alarmTime;
  alarmTime.setHour(matchhour);
  alarmTime.setMinute(matchmin);
  alarmTime.setSecond(matchsec);

  AlarmMatch matchTime;
  matchTime.addMatchHour();
  matchTime.addMatchMinute();
  matchTime.addMatchSecond();

  RTC.setAlarmCallback(alarmCallback, alarmTime, matchTime);

  // Retrieve the date and time from the RTC and print them
  RTCTime currentTime;
  RTC.getTime(currentTime);
  Serial.println("The RTC was just set to: " + String(currentTime));
}


void loop(){
  // for debugging
  RTCTime currentTime;
  RTC.getTime(currentTime);
  Serial.println("current time in Japan: " + String(currentTime));
  // if the current time matches the set time, the alarm will sound
  if(alarmFrag){
    alarmFrag = false;
    sound();
  }
  delay(1000);
}

void alarmCallback(){
  if(!ledState){
    digitalWrite(LED_BUILTIN, HIGH);
  }else{
    digitalWrite(LED_BUILTIN, LOW);
  }
  ledState = !ledState;
  alarmFrag = true;
}

void sound(){
  for(int i=0; i<10; i++){
    for(int j=0; j<10; j++){
      tone(alarmpin, freq);
      delay(t);
      noTone(alarmpin);
      delay(t);
    }
    delay(interval);
  }
}

かいつまんで解説

///// set parameters for the alarm /////
const int alarmpin = 3;
const int freq = 1800;
const int t = 50;
const int interval = 2000;
bool ledState = false;
bool alarmFrag = false;

アラームを鳴らすときの各種パラメータを設定する.

  • alarmpin:スピーカーを接続するArduinoのPWDピン
  • freq:スピーカーから出す音の周波数
  • t:音の長さ.ピピピピッのピの部分.
  • interval:1アラームの間隔.ピピピピッとピピピピッの間の長さ.
  • ledState:設定時刻になったらArduinoのLEDが光るようにしたのでLEDの状態を宣言しておく
  • alarmFrag:設定時刻になったときにアラームを鳴らすためのフラグ
///// set alarm time(HH/MM/SS) /////
const int matchhour = 15;
const int matchmin = 17;
const int matchsec = 0;
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //
RTCTime alarmTime;
alarmTime.setHour(matchhour);
alarmTime.setMinute(matchmin);
alarmTime.setSecond(matchsec);

AlarmMatch matchTime;
matchTime.addMatchHour();
matchTime.addMatchMinute();
matchTime.addMatchSecond();

上部と中部で何時(matchhour)何分(matchmin)何秒(matchsec)にアラームを鳴らすか,下部でどこまで一致させるかを設定する.
この場合だと15時17分00秒に設定している.

alarmCallback関数
void alarmCallback(){
  if(!ledState){
    digitalWrite(LED_BUILTIN, HIGH);
  }else{
    digitalWrite(LED_BUILTIN, LOW);
  }
  ledState = !ledState;
  alarmFrag = true;
}

RTC.setAlarmCallback(alarmCallback, alarmTime, matchTime);でalarmTimeとmatchTimeの条件にしたがってalarmCallback関数を呼び出している.呼び出されたらLEDの状態を切り替え,アラームのフラグをtrueにする(loop関数につながる).

sound関数
void sound(){
  for(int i=0; i<10; i++){
    for(int j=0; j<10; j++){
      tone(alarmpin, freq);
      delay(t);
      noTone(alarmpin);
      delay(t);
    }
    delay(interval);
  }
}

アラームの音を決める.ピピピピピピピピピピッと鳴るようにしてみた.これはiPhoneの時計アプリで設定できるタイマー終了時の音であるクラシック-ヒルサイドを参考にした.

loop関数
void loop(){
  // for debugging
  RTCTime currentTime;
  RTC.getTime(currentTime);
  Serial.println("current time in Japan: " + String(currentTime));
  // if the current time matches the set time, the alarm will sound
  if(alarmFrag){
    alarmFrag = false;
    sound();
  }
  delay(1000);
}

デバッグ用に現在時刻をシリアル表示している.alarmCallback関数でアラームのフラグが立ったらアラームを鳴らし,フラグを初期化している.
はじめはalarmCallback関数の中でアラームを鳴らすようにしていたが,for文でアラームを回すと音が出なかった(tone関数だけだと音は鳴った).調べてみたら割り込み処理内ではdelay()をすぐに抜けてしまって無効になるらしい.

使い方

  1. Arduino IDEに上のスケッチntp.inoを書く
  2. 同じディレクトリにarduino_secrets.hを作り,接続するネットワークのSSIDとパスワードを記述する
  3. const int matchhour = 15; const int matchmin = 17; const int matchsec = 0;を好きな時刻に設定する
  4. Arduinoにアップロード!
arduino_secrets.h
#define SECRET_SSID "接続するSSID"
#define SECRET_PASS "そのパスワード"

動作(シリアルモニタと音)

下書きだと接続が拒否されましたと言われプレビューできない
少し汚めのモニターが映るので注意.

音が鳴っている間はシリアル表示が止まり,鳴り終わったらシリアル表示が再開する.

感想

もっと簡単なアラーム時刻の設定をできるようにしたり,アラーム音を単音ではなく和音とかきれいな音にできたらもっと楽しそう.今回はIDEでやったけど,CLIでできたらかっこいい.
初めてqiitaの記事書いたので感想や指摘など書いてくれると助かる.

1
1
1

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
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?