将棋の神様〜0と1の世界〜

「三間飛車のひとくちメモ」管理人、兼「フラ盤」&「チェスクロイド」作者がおくる、将棋コラム

//移転しました。

対局時計を自作(1)「10秒将棋対応」

//移転しました。


最近、「Arduino」を使って対局時計を自作して遊んでいる。実は電子工作に取り組むこと自体初めてだ。先月8日、id:takkawid:oshix「Make: Tokyo Meeting 02」というイベントに誘われて行ってみて、電子工作に開眼した。で、何を作ってみようかと考えてみたとき、まずは対局時計辺りがちょうどいいな、と。

とりあえず1桁のカウントダウン表示が可能になったので覚書きしておく。また、初めてYoutubeに動画をアップロードしてみた。今後も区切りのいいところでアップしていきたい。

下記のようにまだまだ機能は貧弱だ。

  • 1人分の持ち時間表示しかできない。
    • 秒読みの対局ならば、これで問題無い。分単位の持ち時間がある対局では2人分表示されるべき。
  • ボタンが1つしかない。
    • 実はボタンは1つでも対局可能。とはいえ正規品に則りいずれ2つにしてみる。
  • 1桁しか表示できない。
    • ダイナミックドライブ用に配線された7セグLEDが欲しい。そうでないと配線が非常に増える。
  • 時間設定機能が無い。
    • 「ボタン長押しで時間設定モードに入る」とするか、1つボタンを追加するか、検討中。
  • 音声・ブザー音が無い。
    • 近日追加予定。
  • リセットボタンが無い。
    • Arduinoボード上のリセットボタンを押す必要がある。

今後徐々にパワーアップしていく予定。
モノづくりには電子部品やらの入手作業が必要なので、ソフトウェアだけで作れるものと違い、開発がストップしてしまい非常に歯がゆい。が、その分作り甲斐があるともいえる。
以下に、お恥ずかしながらProcessingのスケッチプログラム内容を載せておく。疑問・質問やアドバイスがあればコメント等下さい。

状態遷移図

  • 状態
    1. 秒読み中(デクリメント中)
    2. 停止中
  • 遷移
    1. 時間切れ
    2. Arduinoボード上のリセットボタン押し
    3. チェスクロックボタン押し
スケッチ内容
#define TM_LIMIT 10  // 持ち時間

// 状態 stateCC(CCはChessClockの略)
// 1 (CNTDOWN): 秒読み状態
// 2 (CNTSTOP): 時間切れ状態
#define CNTDOWN 0
#define CNTSTOP 1
volatile int stateCC = CNTDOWN;

int countBuf = 0;  // 着手時のmillis時間保持用
int usingSec = 0;  // 使用時間

// 0〜9の7セグ表示パターン
boolean LEDArray[10][7]={ {0,0,0,0,0,0,1},
                          {1,0,0,1,1,1,1},
                          {0,0,1,0,0,1,0},
                          {0,0,0,0,1,1,0},
                          {1,0,0,1,1,0,0},
                          {0,1,0,0,1,0,0},
                          {0,1,0,0,0,0,0},
                          {0,0,0,1,1,0,1},
                          {0,0,0,0,0,0,0},
                          {0,0,0,0,1,0,0} };
// 数字表示
void dispNum(int num){
  int j;
  for(int i=0; i<7; i++){
    // pin2は割り込み処理用に空ける
    if(i>=2){ j=i+1; }
    else    { j=i; }
    digitalWrite(j,LEDArray[num%10][i]);
    // ↑現状一桁対応で、10を0にするためnum%10としている
  }
}
void setup(){
  int j;
  for(int i=0; i<=7; i++){
    // pin2は割り込み処理用に空ける
    if(i>=2){ j=i+1; }
    else    { j=i; }
    pinMode(j,OUTPUT);
  }
  // チェスクロボタン押しで割り込み発生
  attachInterrupt(0, pushButton, RISING);
}
void pushButton(){
  switch(stateCC){
  case CNTDOWN:
    usingSec = 0;
    countBuf = millis();  // チェスクロボタン押した時の時刻保持
    break;
  case CNTSTOP:
  default:
    break;
  }
}
void loop(){
  switch(stateCC){
  case CNTDOWN:
    usingSec = millis() - countBuf;
    dispNum(TM_LIMIT - usingSec/1000);  // カウントダウン表示
    if(usingSec == TM_LIMIT*1000){  // 時間使い切った場合
      stateCC = CNTSTOP;
    }
    break;
  case CNTSTOP:
    dispNum(0);
    break;
  default:
    break;
  }
}