見出し画像

タイムタイマー自作

LEDで残り時間を表示するタイムタイマーを作ってみた。 

100均のペンケースに格納

条件とその対策

ワンスイッチですべてを操作できること
諸般の事情によりスイッチは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に下がっていた。思ったより電池の消耗がはやい。一定時間後にスリープモードになるようにしたいが、今のわたしの実力で無理だ。今後の課題とする。

いいなと思ったら応援しよう!