Created
October 24, 2018 09:29
-
-
Save deviceplususer/4ddc365125e885fd5e91746f046c02a0 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <SPI.h> | |
#include <Adafruit_GFX.h> | |
#include <Adafruit_ILI9341.h> | |
#include <Fonts/FreeSans12pt7b.h> | |
#include <Fonts/FreeSans18pt7b.h> | |
#include <Fonts/FreeSans40pt7b.h> | |
#include <Wire.h> | |
#include <RTClib.h> | |
#include "time.h" | |
#include <HardwareSerial.h> | |
#include <DFRobotDFPlayerMini.h> | |
#include <WiFi.h> | |
#include <WebServer.h> | |
#include <HTTPClient.h> | |
// 初期設定 | |
const char *ssid = "WiFiのSSID"; | |
const char *pass = "WiFiのパスワード"; | |
IPAddress ip(本体に割り当てるIPアドレス); | |
IPAddress gateway(デフォルトゲートウェイのIPアドレス); | |
const char* notify_url = "http://子機のIPアドレス/alarm"; | |
const char* adjust_time = "04:00:00"; | |
#define DF_VOLUME 30 | |
// 定数など | |
#define ALARM_SIG 25 | |
#define TFT_DC 2 | |
#define TFT_CS 5 | |
#define TFT_RST 4 | |
#define TFT_WIDTH 320 | |
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST); | |
RTC_DS3231 rtc; | |
HardwareSerial hs(1); | |
DFRobotDFPlayerMini myDFPlayer; | |
WebServer server(80); | |
char old_date[15]; | |
char old_time[9]; | |
char old_alarm[15]; | |
char alarm_time[9]; | |
char wdays[7][4] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; | |
bool alarm_checked = false; | |
bool alarm_on = false; | |
bool ntp_adjusted = false; | |
int alarm_ctr; | |
// NTPで日時を設定 | |
void setTimeByNTP() { | |
struct tm t; | |
configTime(9 * 3600L, 0, "ntp.nict.jp", "time.google.com", "ntp.jst.mfeed.ad.jp"); | |
if (!getLocalTime(&t)) { | |
Serial.println("getLocalTime Error"); | |
return; | |
} | |
rtc.adjust(DateTime(t.tm_year + 1900, t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec)); | |
} | |
// 液晶ディスプレイに文字列を表示 | |
void showMessage(char* s_new, char* s_old, int y0, int height) { | |
int16_t x1, y1; | |
uint16_t w, w2, h; | |
int x, y; | |
if (strcmp(s_new, s_old) != 0) { | |
tft.getTextBounds(s_old, 0, 0, &x1, &y1, &w, &h); | |
w2 = w * 11 / 10; | |
tft.fillRect((TFT_WIDTH - w2) / 2 , y0 - (height / 2) + 1, w2, height, ILI9341_BLACK), | |
tft.getTextBounds(s_new, 0, 0, &x1, &y1, &w, &h); | |
tft.setCursor((TFT_WIDTH - w) / 2, y0 + (h / 2) - 1); | |
tft.print(s_new); | |
strcpy(s_old, s_new); | |
} | |
} | |
// アラームの設定 | |
void handleSetAlarm() { | |
int i, hour, min, sec; | |
bool is_off = false; | |
String s_hour = "", s_min = "", s_sec = ""; | |
// URLからoff/hour/min/secのパラメータを得る | |
for (i = 0; i < server.args(); i++) { | |
if (server.argName(i).compareTo("off") == 0) { | |
is_off = true; | |
break; | |
} | |
else if (server.argName(i).compareTo("hour") == 0) { | |
s_hour = server.arg(i); | |
} | |
else if (server.argName(i).compareTo("min") == 0) { | |
s_min = server.arg(i); | |
} | |
else if (server.argName(i).compareTo("sec") == 0) { | |
s_sec = server.arg(i); | |
} | |
} | |
// offのパラメータが設定されていれば、アラームをオフにする | |
if (is_off) { | |
strcpy(alarm_time, "Off"); | |
server.send(200, "text/plain", "Alarm off."); | |
} | |
// アラームの時刻を設定する | |
else if (s_hour.length() > 0 && s_min.length() > 0) { | |
hour = s_hour.toInt(); | |
min = s_min.toInt(); | |
if (s_sec.length() > 0) { | |
sec = s_sec.toInt(); | |
} | |
else { | |
sec = 0; | |
} | |
if (hour >= 0 && hour <= 23 && min >= 0 && min <= 59 && sec >= 0 && sec <= 59) { | |
sprintf(alarm_time, "%02d:%02d:%02d", hour, min, sec); | |
String msg = "Alarm is set at "; | |
msg.concat(alarm_time); | |
server.send(200, "text/plain", msg); | |
} | |
else { | |
server.send(200, "text/plain", "Invalid hour / sec."); | |
} | |
} | |
else { | |
server.send(200, "text/plain", "Invalid parameter."); | |
} | |
} | |
// アラームを止める | |
void handleStopAlarm() { | |
myDFPlayer.pause(); | |
alarm_on = false; | |
tft.drawRect(30, 180, 260, 40, ILI9341_BLACK); | |
server.send(200, "text/plain", "Alarm stop"); | |
} | |
// 無効なURLが指定された場合 | |
void handleNotFound() { | |
String message = "Not Found : "; | |
message += server.uri(); | |
server.send(404, "text/plain", message); | |
} | |
// セットアップ | |
void setup() { | |
int16_t x1, y1; | |
uint16_t w, h; | |
Serial.begin(115200); | |
strcpy(old_date, "00000000000000"); | |
strcpy(old_time, "00000000"); | |
strcpy(old_alarm, "00000000000000"); | |
strcpy(alarm_time, "Off"); | |
// ディスプレイの初期化 | |
tft.begin(); | |
tft.setRotation(3); | |
tft.fillScreen(ILI9341_BLACK); | |
tft.setTextColor(ILI9341_WHITE); | |
tft.setFont(&FreeSans12pt7b); | |
String s = "Initializing..."; | |
tft.getTextBounds(s, 0, 0, &x1, &y1, &w, &h); | |
tft.setCursor(0, h); | |
tft.println(s); | |
// WiFi接続 | |
WiFi.begin(ssid, pass); | |
while (WiFi.status() != WL_CONNECTED) { | |
delay(500); | |
Serial.print("."); | |
} | |
WiFi.config(ip, gateway, WiFi.subnetMask(), IPAddress(8, 8, 8, 8), IPAddress(8, 8, 4, 4)); | |
Serial.println(""); | |
Serial.println("WiFi Connected."); | |
tft.println("WiFi Connected."); | |
// DFPlayer初期化 | |
hs.begin(9600, SERIAL_8N1, 16, 17); | |
int count = 0; | |
while (count < 10) { | |
if (!myDFPlayer.begin(hs)) { | |
count++; | |
Serial.print("DFPlayer initialize attempt "); | |
Serial.println(count); | |
} | |
else { | |
break; | |
} | |
} | |
if (count < 10) { | |
Serial.println("DFPlayer Initialized."); | |
tft.println("DFPlayer Initialized."); | |
myDFPlayer.pause(); | |
myDFPlayer.volume(DF_VOLUME); | |
} | |
else { | |
Serial.println("DFPlayer Error."); | |
tft.println("DFPlayer Error."); | |
while(1); | |
} | |
// RTC初期化 | |
if (!rtc.begin()) { | |
Serial.println("Couldn't find RTC"); | |
while (1); | |
} | |
Serial.println("RTC Initialized"); | |
tft.println("RTC Initialized."); | |
// NTPで現在時刻を取得してRTCに設定 | |
setTimeByNTP(); | |
// WebServerの初期化 | |
server.on("/set", handleSetAlarm); | |
server.on("/stop", handleStopAlarm); | |
server.onNotFound(handleNotFound); | |
server.begin(); | |
// ディスプレイを黒で塗りつぶす | |
tft.fillScreen(ILI9341_BLACK); | |
} | |
void loop() { | |
char new_time[9], new_date[15], new_alarm[15]; | |
// Webサーバーを動作させる | |
server.handleClient(); | |
// 現在の日時を液晶ディスプレイに表示 | |
DateTime now = rtc.now(); | |
sprintf(new_date, "%04d/%02d/%02d ", now.year(), now.month(), now.day()); | |
strcat(new_date, wdays[now.dayOfTheWeek()]); | |
sprintf(new_time, "%02d:%02d:%02d", now.hour(), now.minute(), now.second()); | |
strcpy(new_alarm, "Alarm "); | |
strcat(new_alarm, alarm_time); | |
tft.setFont(&FreeSans18pt7b); | |
tft.setTextColor(ILI9341_WHITE); | |
showMessage(new_date, old_date, 40, 28); | |
showMessage(new_alarm, old_alarm, 200, 28); | |
tft.setFont(&FreeSans40pt7b); | |
showMessage(new_time, old_time, 120, 64); | |
// 現在の時刻がアラームの時刻になっているかどうかを判断 | |
if (strstr(new_time, alarm_time) != NULL) { | |
if (!alarm_checked) { | |
// アラームの時刻なら、音を出して、子機にメッセージを送信 | |
myDFPlayer.loop(1); | |
alarm_checked = true; | |
alarm_on = true; | |
alarm_ctr = 0; | |
HTTPClient http; | |
http.begin(notify_url); | |
int httpCode = http.GET(); | |
} | |
} | |
else { | |
alarm_checked = false; | |
} | |
// アラームが鳴っている間は、液晶ディスプレイのアラーム時刻の周りに赤枠を点滅させる | |
if (alarm_on) { | |
if (alarm_ctr == 0) { | |
tft.drawRect(30, 180, 260, 40, ILI9341_RED); | |
} | |
else if (alarm_ctr == ALARM_SIG) { | |
tft.drawRect(30, 180, 260, 40, ILI9341_BLACK); | |
} | |
alarm_ctr++; | |
alarm_ctr %= ALARM_SIG * 2; | |
} | |
// 毎日一定の時刻にNTPで時刻合わせを行う | |
if (strstr(new_time, adjust_time) != NULL) { | |
if (!ntp_adjusted) { | |
setTimeByNTP(); | |
ntp_adjusted = true; | |
} | |
} | |
else { | |
ntp_adjusted = false; | |
} | |
delay(20); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment