タイムタイマー自作
LEDで残り時間を表示するタイムタイマーを作ってみた。
条件とその対策
ワンスイッチですべてを操作できること
諸般の事情によりスイッチは1つにした。(と背面に電源スイッチ)
スイッチの短押し、長押し、電源とスイッチの同時ON の3通りですべての操作を行う。短押しは50ミリ秒以上(チャタリング対策も兼ねている)のプレス、長押しは2秒以上のプレスである。
設定時間を変更出来ること
電源とスイッチの同時ONで時間設定モードに入れるようにした。10~120秒の間で10秒単位で設定できるようにした(短押しで+10秒、長押しで設定終了)。設定値はNANOのEEPROM(不揮発メモリ)に保存することにした。
仕様
タイマーモード
時間設定モード
構成
パーツ
Arduino NANO(AliExpressで購入。Amazon中華製は端子miniUSBで最近高いのに比べ、かなりの格安でしかもTypeCはうれしい)
LED、1Ω集合抵抗、0.1μFコンデンサ、スイッチ、直流ブザー、M3ネジ類、スペーサー、乾電池ボックス(シリコンハウス or デジット、ジャンク品あり)、DCDCコンバータ(秋月か)、ケース(100均)、ブレッドボード(Amazon中華製、安いが歪んでいる)
回路
写真の通り
NANOの各ポート → スイッチ
→ 直流ブザー
→ 12個のLED →1Ω →GND
電源は単3×2 → DCDCコンバータで5Vに昇圧
sketch
EEPROMへの仕込み用のsketch
本チャンの sketch の仕込み前にEEPROMへタイマー時間の設定値を書き込んでおく。
/*
Store value into the EEPROM address(0).
*/
#include <EEPROM.h>
long set_time = 60000; //
byte EEPROM_0_value; // address(0) value of EEPROM
void setup() {
Serial.begin(9600);
Serial.println(); Serial.println("EEPROM.write ---");
Serial.print("set_time: "); Serial.println(set_time);
EEPROM_0_value = byte(set_time / 10000);
Serial.print("byte(set_time / 10000): "); Serial.println(EEPROM_0_value, DEC);
EEPROM.write(0, EEPROM_0_value); // (address, byte value)
}
void loop() {}
本チャンの sketch
上の仕込みのあとこのsketchを書き込む
/*
=========================
timetimer_for_NANO_03.ino
=========================
Arduino NANO
1・ ・VIN serial port is COM3 for hp_PC.
0・ ・GND
Reset・ ・Reset 3,11 is interfered by tone().
GND・ ・5V A6,A7 is analog only.
BUZ <-- 2・ ・A7 0,1 is not for use.
LED_4 <-- 3・ ・A6
LED_5 <-- 4・ ・19/A5 <-- LED_10
LED_6 <-- 5・ ・18/A4 --> LED_1
LED_7 <-- 6・ ・17/A3 --> LED_2
LED_8 <-- 7・ ・16/A2 --> LED_3
LED_9 <-- 8・ ・15/A1
SW <-- 9・ ・14/A0
LED_11 <--10・ ・AREF
LED_12 <--11・ ・3.3V
12・ USB ・13
*/
#include <EEPROM.h>
#define LED_1 18
#define LED_2 17
#define LED_3 16
#define LED_4 3
#define LED_5 4
#define LED_6 5
#define LED_7 6
#define LED_8 7
#define LED_9 8
#define LED_10 19
#define LED_11 10
#define LED_12 11
#define BUZ 2
#define SW 9
#define Long_push_time 1000 // long push time(msec)
#define Short_push_time 50 // short push time(msec)
unsigned long on_time = 0; // moment when switch is pressed
unsigned long off_time = 0; // moment when switch is pressed off
unsigned long press_time = 0; // time from on to off
byte EEPROM_0_value; // address(0) value of EEPROM
long set_time = 60000;
int blink_interval = 500; // = set_time / 120
void time_set() { // set time
while (true) { // when switch on, time_set() start.
Serial.println(" waiting switch on ");
if (is_SW_short_or_long() == 0) {
Serial.println("time_set() start");
break;
}
}
blink_interval = set_time / 120;
Serial.println("set time -----");
Serial.print(" time = "); Serial.println(set_time);
Serial.print(" blink_interval = "); Serial.println(blink_interval);
indicate_time_LED(set_time / 10000);
int short_or_long;
while (true) {
short_or_long = is_SW_short_or_long();
if (short_or_long == 0) {
set_time = set_time + 10000; // add 10sec
if (set_time > 120000) {
set_time = 10000;
}
blink_interval = set_time / 120;
Serial.print(" time = "); Serial.println(set_time);
Serial.print(" blink_interval = "); Serial.println(blink_interval);
indicate_time_LED(set_time / 10000);
} else if (short_or_long == 1) {
EEPROM_0_value = byte(set_time / 10000);
Serial.print("byte(set_time / 10000): "); Serial.println(EEPROM_0_value, DEC);
EEPROM.write(0, EEPROM_0_value); // (address, byte value) write EEROM
Serial.println(" time_set() is end");
digitalWrite(BUZ, HIGH); delay(50); // message "set time is end"
digitalWrite(BUZ, LOW); delay(100);
digitalWrite(BUZ, HIGH); delay(300);
digitalWrite(BUZ, LOW);
break; // return to setup()
}
}
}
void timer() { // timer
start_position:
Serial.println("Timer ---");
int sw_state = -1; // 0:short press, 1:long press
for (int i = 1; i <= 12; i++) { // all LED on
LED_on(i); delay(0);
};
Serial.println(" all LED on");
while (true) { // when switch on, timer start
Serial.println(" waiting switch on ");
Serial.println(" call is_SW_short_or_long()");
sw_state = is_SW_short_or_long();
Serial.print(" sw_state = ");Serial.println(sw_state);
if (sw_state == 0) {
digitalWrite(BUZ, HIGH);
delay(50);
digitalWrite(BUZ, LOW);
Serial.println("timer start");
break;
}
}
for (int i = 1; i <= 12; i++) { // count down, LED blink
// for (int i = 8; i <= 12; i++) { // count down, LED blink
if (digitalRead(SW) == LOW) {
delay(50);
if (digitalRead(SW) == LOW) { // if switch pressd, reset
Serial.println(" timer is reset");
digitalWrite(BUZ, HIGH); delay(50); digitalWrite(BUZ, LOW); delay(100);
digitalWrite(BUZ, HIGH); delay(300); digitalWrite(BUZ, LOW); delay(500);
goto start_position; // restart
}
} else { // if not pressed, run
Serial.print(" LED_");
Serial.print(i);
Serial.println(" is blinking");
LED_blink(i, 5);
LED_off(i);
}
};
Serial.println("count down ends");
while (true) { // end message
Serial.println(" end message");
LED_on(10); LED_off(11); LED_on(12); digitalWrite(BUZ, HIGH); delay(100);
LED_off(10);LED_on(11); LED_off(12);digitalWrite(BUZ, LOW); delay(100);
if (digitalRead(SW) == LOW) { // when switch on, out of loop
delay(1000);
Serial.println("goto start_position");
goto start_position;
}
}
}
int is_SW_short_or_long() { // If short press, return 0. long press, return 1.
while (digitalRead(SW) == HIGH); // wait for pressed
on_time = millis(); // note pressed time
digitalWrite(13, HIGH); // light on monitor LED
delay(20); // for chattering (wait for 20ms)
while (digitalRead(SW) == LOW); // wait for press-off
off_time = millis(); // note press-off time
digitalWrite(13, LOW); // light off monitor LED
press_time = off_time - on_time; // calculate pressed time
if (press_time > Long_push_time) { // judge of long press ( > 3000ms )
Serial.print(" long press ");
Serial.println(press_time);
return 1; // return judgment (1)
} else if (press_time > Short_push_time) { // judge of short press ( > 50ms )
Serial.print(" short press ");
Serial.println(press_time);
return 0;
}
}
void LED_on(int LED_num) {
switch (LED_num) {
case 1: digitalWrite(LED_1, HIGH); break; case 2: digitalWrite(LED_2, HIGH); break;
case 3: digitalWrite(LED_3, HIGH); break; case 4: digitalWrite(LED_4, HIGH); break;
case 5: digitalWrite(LED_5, HIGH); break; case 6: digitalWrite(LED_6, HIGH); break;
case 7: digitalWrite(LED_7, HIGH); break; case 8: digitalWrite(LED_8, HIGH); break;
case 9: digitalWrite(LED_9, HIGH); break; case 10: digitalWrite(LED_10, HIGH); break;
case 11: digitalWrite(LED_11, HIGH); break; case 12: digitalWrite(LED_12, HIGH); break;
}
}
void LED_off(int LED_num) {
switch (LED_num) {
case 1: digitalWrite(LED_1, LOW); break; case 2: digitalWrite(LED_2, LOW); break;
case 3: digitalWrite(LED_3, LOW); break; case 4: digitalWrite(LED_4, LOW); break;
case 5: digitalWrite(LED_5, LOW); break; case 6: digitalWrite(LED_6, LOW); break;
case 7: digitalWrite(LED_7, LOW); break; case 8: digitalWrite(LED_8, LOW); break;
case 9: digitalWrite(LED_9, LOW); break; case 10: digitalWrite(LED_10, LOW); break;
case 11: digitalWrite(LED_11, LOW); break; case 12: digitalWrite(LED_12, LOW); break;
}
}
void LED_blink(int LED_num, int num_of_cycle) {
int LED;
switch (LED_num) {
case 1: LED = LED_1; break; case 2: LED = LED_2; break;
case 3: LED = LED_3; break; case 4: LED = LED_4; break;
case 5: LED = LED_5; break; case 6: LED = LED_6; break;
case 7: LED = LED_7; break; case 8: LED = LED_8; break;
case 9: LED = LED_9; break; case 10: LED = LED_10; break;
case 11: LED = LED_11; break; case 12: LED = LED_12; break;
}
for (int i = 0; i < num_of_cycle; i++) {
delay(blink_interval); digitalWrite(LED, LOW); // on
delay(blink_interval); digitalWrite(LED, HIGH); // off
}
}
void indicate_time_LED(int t) { // light LED of set time
int how_many_LED = t;
digitalWrite(BUZ, HIGH); delay(30); digitalWrite(BUZ, LOW);
for (int i = 1; i < 12; i++) { // all LED off
LED_off(i);
}
for (int i = 13 - how_many_LED; i <= 12; i++) {
LED_on(i); // seleced LED on
}
}
void setup() {
pinMode(LED_1, OUTPUT); pinMode(LED_2, OUTPUT); pinMode(LED_3, OUTPUT); pinMode(LED_4, OUTPUT);
pinMode(LED_5, OUTPUT); pinMode(LED_6, OUTPUT); pinMode(LED_7, OUTPUT); pinMode(LED_8, OUTPUT);
pinMode(LED_9, OUTPUT); pinMode(LED_10, OUTPUT);pinMode(LED_11, OUTPUT);pinMode(LED_12, OUTPUT);
pinMode(BUZ, OUTPUT); // buzzer
pinMode(SW, INPUT_PULLUP); // switch
Serial.begin(9600); // open port by 9600bps
Serial.println("");
Serial.println("Hello Timetimer");
EEPROM_0_value = EEPROM.read(0); // read address(0) as set_time/10000
Serial.print("value of address(0): "); Serial.println(EEPROM_0_value, DEC);
set_time = long(EEPROM_0_value) * 10000;
blink_interval = set_time / 120;
Serial.print("set_time: "); Serial.println(set_time);
if (digitalRead(SW) == LOW) { // if switch on, call time_set()
time_set();
}
}
void loop() {
timer();
}
課題
実は市販のタイマーにあるカウントダウンの一時停止と完全停止のメニューがない。カウントダウン中にスイッチを押すと一時停止、もう一度押すと再開、長押しするとカウントダウンを中止する(リセット)ことが出来ない。今後の宿題とする。
追記
上の課題のうち、カウントダウン中のリセットは出来るようになったのでsketchを書き直した。(正確にはそれぞれのLEDのブリンクとブリントの間にスイッチを押したかどうかの判定を行い、押していればリセットを行う)
追記その2
その後ネットで見つけたタイムエイド関連の記事をあげておく(アプリを除く。下線部リンク)
自作:タイムエイド ポケット(小山智史・梅村博之)
自作:宮崎県立延岡工業高校情報技術科(https://cms.miyazaki-c.ed.jp/6029/)
市販:タイムログ(五大エンボディ㈱)
市販(KIT):電子工作キット(キッチンタイマー)MK128
資料:支援の七つ道具(楽暮(らぼ)プロジェクト)
資料:コミュニケーション支援機器一覧(北九州市立八幡西特別支援学校)
資料:支援技術を用いた知的障害当事者による時間管理支援マニュアル作成(岡 耕平)
追記その3
約20分/日×23日で動作しなくなった。VCC-GND間の電圧が約3.5Vに下がっていた。思ったより電池の消耗がはやい。一定時間後にスリープモードになるようにしたいが、今のわたしの実力で無理だ。今後の課題とする。