99秒までの秒読みに対応
開発が思うように進まず、前回(12/14のエントリー参照)からの進歩としては、2桁の秒読みに対応できただけ。
「デンシ電気店 ヤフーショップ」というところから、ダイナミックドライブ用配線済みの4桁7セグLED「LED/E3-4040CHR2」を入手した。
上記動画で数字がちかちか点滅して見えるのは、各桁を短い周期で交互に光らせる「ダイナミック点灯」を行なっているから。ただし人間の肉眼であれば、常に光っているように見える。
左側のボタンとLEDはまだ未使用。
今後の課題
7セグデコーダドライバ、または3to8デコーダ/デマルチプレクサ(Demultiplexer。コモン端子制御用に利用したい)が無い現状では、ポートが足りない(はず)。
- ブザー用・・・1Pin
- 7セグ用・・・7Pin(7セグデコーダがあれば4Pinで表現可能)
- ボタン用・・・1ボタンにつき1Pin
- コモン制御用・・・1桁につき1Pin(3to8デコーダ/デマルチプレクサがあれば、8桁までを3Pinで表現可能)
つまり、2ボタン+4桁を単純に表現すると、1+7+2+4=14Pinとなり、ArduinoのDigital In/Out Pin13個を超えてしまう。
ウケるのか?
明日から、1泊2日の某温泉将棋合宿に参加する。対局時計の数は足りているのだが、笑いをとるだけのために本対局時計を持っていく予定。というか実は、本開発の根本的な目的の1つは、この合宿に持っていく(そして笑いをとる)ことだった。もっと完成度を上げたかったのだが・・・無念。
スケッチ公開
参考までに、以下に現状のProcessingスケッチを載せておく。
主な変更点は、数字を表示するdispNum関数。その他、millis()で取得した時間データをうっかりInt型変数で受け取っていたバグ(前回は時間が短くバグが表面化していなかった)を修正したりしている。アノード→カソード変換など、どうもスマートじゃないところが散見かも。
#define TM_LIMIT 30 // 持ち時間 #define CATHODE // カソードコモンLED利用時。アノード時はコメントアウト // 状態 stateCC(CCはChessClockの略) // 1 (CNTDOWN): 秒読み状態 // 2 (CNTSTOP): 時間切れ状態 #define CNTDOWN 0 #define CNTSTOP 1 volatile int stateCC = CNTDOWN; unsigned long countBuf = 0; // 着手時のmillis時間保持用 int usingSec = 0; // 使用時間 // 各桁のコモン制御用ポート定義 int digitArray[2]={9,10}; // 各SegmentとPin対応。2,3Pinは割り込み用に空ける int SegArray[7] = {0,1,4,5,6,7,8}; // 0〜9の7セグ表示パターン アノードコモンLED用 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} }; // カソードコモンLEDに変換する際に用いる関数。各ビット反転 void changeCommonAtoC(void){ int i,j; for(i=0; i<10; i++){ for(j=0; j<7; j++){ LEDArray[i][j]= !LEDArray[i][j]; } } } // ブザーOn/Off用。13Pin利用 void buzzer( boolean soundOn ){ digitalWrite(13,soundOn); } // コモン端子制御用 void ctrlCommon( int port, boolean lightOn ){ digitalWrite(port, lightOn); } // 数字表示 void dispNum(int num){ static unsigned long millisBuf = 0; static int digit = 1; int num1; // 光らせる桁に表示させたい数字設定用 // 光らせる桁設定 現状2桁だけ。1→2→1→・・・ if( millis()-millisBuf >= 10 ){ // 10msおきにコモン切換 if(digit>=2){digit=1;} else {digit++;} millisBuf = millis(); } // 光らせる桁の数字取得 for(int n=digit; n!=1; n--){ num=num/10; } // 右へ桁シフトし下位桁削除 num1 = num%10; // 上位桁の数字クリア // コモン端子制御。光らせる桁のコモンのみHIGH for(int i=0; i<2; i++){ ctrlCommon( digitArray[i], digit==i+1 ); } // ↑digitとi+1が等しいときのみtrueとなる // 光らせる桁の数字の7セグ出力 for(int j=0; j<7; j++){ digitalWrite(SegArray[j], LEDArray[num1][j]); } } void setup(){ int i; //カソードコモンLED使用ならばカソード用に変換 #ifdef CATHODE changeCommonAtoC(); #endif // 7セグ用Pin初期化 for(i=0; i<=7; i++){ pinMode(SegArray[i], OUTPUT); } // ブザー用Pin初期化 pinMode(13,OUTPUT); // コモン制御用Pin初期化 pinMode(9,OUTPUT); pinMode(10,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; // 7セグ関連 dispNum(TM_LIMIT - usingSec/1000); // カウントダウン表示 // ブザー音関連 if(usingSec <= 50){ // ボタン押し直後は鳴らさない buzzer(false); } else if(TM_LIMIT - usingSec/1000 <= 5){ // ラスト5秒 buzzer(true); } else if(TM_LIMIT - usingSec/1000 <= 10){ // ラスト10秒 if(usingSec%1000 >= 0 && usingSec%1000 <= 50){ buzzer(true); } else{buzzer(false);} } else if( (TM_LIMIT*1000-usingSec)%10000 >= 9950 ){ // それ以前は10秒毎 buzzer(true); } else{buzzer(false);} // 時間使い切った場合 if(usingSec == TM_LIMIT*1000){ stateCC = CNTSTOP; } break; case CNTSTOP: dispNum(0); buzzer(false); break; default: break; } }
コメント