Skip to content

Instantly share code, notes, and snippets.

@deviceplususer
Created October 24, 2018 09:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save deviceplususer/4ddc365125e885fd5e91746f046c02a0 to your computer and use it in GitHub Desktop.
Save deviceplususer/4ddc365125e885fd5e91746f046c02a0 to your computer and use it in GitHub Desktop.
#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