オンボードの水晶発振子で動く
時計のスケッチを考えました。
茂吉の処女作です。
/*
millis()? 関数で刻む時計
[dClock100.ino]
2014/04/29 daikunomokichi
millis()? 関数は、
Arduinoボードがプログラムの実行を開始した時から現在までの時間をミリ秒単位で返します。
戻り値=符号なしlong整数型
約50日間でオーバーフローし、ゼロに戻ります。
開始数分前に設定し、コンピュータから離脱後、[RESET]し、時刻合わせをする。
*/
long dTimer0 = 0; //起動後経過時間
long dTimer1 = 0; //開始時日時
long dTimer2 = 0; //日時刻=起動後経過時間+開始時刻
long dTimer_y0 = 2010; //設定した開始年
long dTimer_y1 = 0; //2010より経過年
long dTimer_yy = 2014; //開始時刻 年
long dTimer_mm = 4; //開始時刻 月
long dTimer_dd = 29; //開始時刻 日
long dTimer_hh = 20; //開始時刻 時
long dTimer_nn = 00; //開始時刻 分
long dTimer_ss = 0; //開始時刻 秒
long dTimer_d0 = 0; //年頭からの総日数
long dTimer_d1 = 0; //曜日 日1 月2 火3 水4 木5 金6 土7
long dTimer_d2 = 0; //2月29日の補正
long dTimer_d3 = 0; //月の末日
long dTimer_hh_mod = 0;
long dTimer_nn_mod = 0;
long dTimer_ss_mod = 0;
//曜日 日1 月2 火3 水4 木5 金6 土7
char dStr1[ ] = {
'_', 'S', 'M', 'T', 'W', 'T', 'F', 'S'
}; //1文字目
char dStr2[ ] = {
'_', 'u', 'o', 'u', 'e', 'h', 'r', 't'
}; //2文字目
char dStr3[ ] = {
'_', 'n', 'n', 'e', 'd', 'u', 'i', 'u'
}; //3文字目
long dYear1[ ] = {
5, 6, 0, 2, 3, 4, 5, 1, 2, 3, 4, 6, 0, 1, 2
}; //2010からの元日の曜日
long dYear2[ ] = {
0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1
}; //2010からの閏年の補正テーブル
long dMoth1[ ] = {
31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
}; //1月~12月の各月の日数
long dMoth2[ ] = {
0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
}; //1月~12月の各月の1日の年頭からの日数
long dSpeed = 100; //100が標準。10は10倍速
// include the library code:
#include <LiquidCrystal.h>
// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(8, 13, 9, 4, 5, 6, 7);
void setup()
{
lcd.begin(16, 2); //LCDの大きさ
lcd.clear(); //クリア
//開始日時を秒(10=1秒)に変換
dTimer1 = (dTimer_dd * 864000) + (dTimer_hh * 36000) + (dTimer_nn * 600) + (dTimer_ss * 10);
dTimer_y1 = dTimer_yy - dTimer_y0; //2010より経過年
}
void loop()
{
dTimer0 = millis() / dSpeed; //起動後経過時間=>秒(10=1秒)
dTimer2 = dTimer0 + dTimer1; //日時刻=>秒(10=1秒)
dTimer_hh_mod = (dTimer2 % 864000); //(日時刻÷1日)の余り=>時分秒
dTimer_dd = (dTimer2 - dTimer_hh_mod) / 864000; //(日時刻-時分秒)÷1日=>日
dTimer_d0 = dMoth2[dTimer_mm - 1] + dTimer_dd; //各月の1日の年頭からの日数+日=>年頭からの総日数
//曜日表示のための閏年の2月29日の補正
dTimer_d2 = 0; //2月29日の補正なし
if (dTimer_d0 > 59) { //2月29日または3月1日
dTimer_d2 = dYear2[dTimer_y1]; //補正テーブルを参照
}
dTimer_d1 = ((dTimer_d0 + dTimer_d2 + dYear1[dTimer_y1]) % 7); //曜日 日1 月2 火3 水4 木5 金6 土7
//月の末日
dTimer_d3 = dMoth1[dTimer_mm - 1]; //月の末日
if (dTimer_mm == 2) { //2月の場合
dTimer_d3 = dMoth1[dTimer_mm - 1] + dYear2[dTimer_y1]; //閏年の補正
}
if (dTimer_d3 < dTimer_dd) {
dTimer1 = dTimer1 - ((dTimer_dd - 1) * 864000);
dTimer_mm = dTimer_mm++;
//12月(大晦日)
if (dTimer_mm > 12) { //12月の場合
dTimer_mm = 1; //1月に戻す
dTimer_yy = dTimer_yy++; //年を+1
dTimer_y1 = dTimer_yy - dTimer_y0; //2010より経過年
}
}
dTimer_nn_mod = (dTimer2 % 36000);
dTimer_hh = (dTimer_hh_mod - dTimer_nn_mod) / 36000; //時
dTimer_ss_mod = (dTimer2 % 600);
dTimer_nn = (dTimer_nn_mod - dTimer_ss_mod) / 600; //分
dTimer_ss = (dTimer2 / 10) % 60; //秒
lcd.setCursor(0, 0);
lcd.print(dTimer_yy);
lcd.print("/");
lcd.print(dTimer_mm / 10);
lcd.print(dTimer_mm % 10);
lcd.print("/");
lcd.print(dTimer_dd / 10);
lcd.print(dTimer_dd % 10);
lcd.print(" (");
lcd.print(dStr1[dTimer_d1]);
lcd.print(dStr2[dTimer_d1]);
lcd.print(dStr3[dTimer_d1]);
lcd.print(")");
lcd.setCursor(0, 1);
lcd.print(dTimer_hh / 10);
lcd.print(dTimer_hh % 10);
lcd.print(":");
lcd.print(dTimer_nn / 10);
lcd.print(dTimer_nn % 10);
lcd.print(":");
lcd.print(dTimer_ss / 10);
lcd.print(dTimer_ss % 10);
lcd.print(" ");
lcd.print(" [");
lcd.print((millis() / 1000) / 60); //経過分の表示
}