// RaceTimer // // 2017-03-29 時々、最初の5秒のカウントから抜け出ずマイナスまで行ってしまう問題を修正。 // setup()内のf=0をタイマー設定後に移動した。 // また不要なコメントを削除し、説明コメントを追加した。 // #include #include #define LCD_RS 5 #define LCD_RW 6 #define LCD_E 7 #define LCD_DB4 8 #define LCD_DB5 9 #define LCD_DB6 10 #define LCD_DB7 11 #define START 2 #define MODE 3 #define TONE 12 #define LED 13 LiquidCrystal lcd(LCD_RS,LCD_RW,LCD_E,LCD_DB4,LCD_DB5,LCD_DB6,LCD_DB7); volatile int f; // タイマー割り込み発生フラグ 割り込みがあると1がたつ。 int s; // 下記3種のテーブルのインデックス 0~69 int match; // 次にカウント値がこの値になった時にアクションを起こす。 volatile int t; // カウント値(1=100mS) int stat; // 現在の状態 0:カウント前 1:最初の5秒間 2:3,4,5分間のカウント int mode; // 3分,4分,5分モード 3:3分 4:4分 5:5分 // タイミングテーブル。単位:100mS int schedule[]={3000,2985,2980,2975,2970,2965, // 0..5 before 5m whistle 2900,2800,2700,2699,2600,2500,2400,2385,2380,2375,2370, // 6..16 before 5m 2300,2200,2100,2099,2000,1900,1800,1785,1780,1775, // 17..26 before 4m 1700,1600,1500,1499,1400,1300,1200,1185,1180, // 27..35 before 3m 1100,1000, 900,899, 800, 700, 600, 585, // 36..43 before 2m 500, 400, 300,299, 200, // 44..48 before 1m 100, 90, 80, 70, 60, // 49..53 before 10s 50,49,48,47,46, // 54..58 before 5s 40,39,38,37, // 59..62 before 4s 30,29,28, // 63..65 before 3s 20,19, // 66..67 before 2s 10, // 68 before 1s 0}; // 69 START // トーンテーブル。単位:Hz (今は全部同じだが変えても良し) int tonemap[]={ 1397,1397,1397,1397,1397,1397, 1397, 1397, 1397,1397, 1397, 1397, 1397,1397,1397,1397,1397, 1397, 1397, 1397,1397, 1397, 1397, 1397,1397,1397,1397, 1397, 1397, 1397,1397, 1397, 1397, 1397,1397,1397, 1397, 1397, 1397,1397, 1397, 1397, 1397,1397, 1397, 1397, 1397,1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397,1397,1397,1397,1397, 1397,1397,1397,1397, 1397,1397,1397, 1397,1397, 1397, 1397}; // デュレーションテーブル。単位:mS int duration[]={ 1000,150,150,150,150,150, 75, 75, 75,75, 75, 75, 1000,150,150,150,150, 75, 75, 75,75, 75, 75, 1000,150,150,150, 75, 75, 75,75, 75, 75, 1000,150,150, 75, 75, 75,75, 75, 75, 1000,150, 75, 75, 75,75, 75, 75, 75, 75, 75, 75, 75,75,75,75,75, 75,75,75,75, 75,75,75, 75,75, 75, 3000}; // 3分,4分,5分モード毎の初期値 int modetime[]= { 0,600,1200,1800,2400,3000}; int modeidx[] = { 0,47,41, 23, 12, 0}; // タイマー割り込みルーチン void timeup() { static boolean output = HIGH; digitalWrite(LED,output); f=1; output = !output; --t; } // セットアップ void setup() { // LCD lcd.begin(16,2); mode=5; modeout(mode); // TIMER pinMode(START,INPUT); pinMode(MODE,INPUT); pinMode(TONE,OUTPUT); Timer1.initialize(100000); Timer1.stop(); Timer1.attachInterrupt(timeup); f=0; // t=101;s=33; // 10s // match=schedule[s]; stat=0; } // 3分,4分,5分モード表示 void modeout( int m ) { lcd.clear(); switch (m) { case 3: lcd.print("MODE=3min"); break; case 4: lcd.print("MODE=4min"); break; case 5: lcd.print("MODE=5min"); break; default: lcd.print("MODE=UNKNOWN"); break; } } // LCDへの出力関数(スタート前の3,4,5分間) void lcdout( int time , int col) { int min=time/60; int sec=time%60; lcd.clear(); lcd.print("Before "); lcd.print(min); lcd.print(":"); lcd.print(sec); } // LCDへの出力関数(スタート前の前の5秒間) void readyout( int time) { lcd.clear(); lcd.print("READY "); lcd.print(time); } // メインループ void loop() { static int mt=0; switch (stat) { case 0: // 動作設定(カウント前) if (digitalRead(MODE) == 0 ) { // MODEボタン mt++; if (mt==100) { mode++; if (5 < mode ) { mode=3; } modeout(mode); } if (100 < mt ) { mt--;} } else { mt=0; } if(digitalRead(START) == 0) { // STARTボタン stat=1; t=51;s=54; // 5S match=schedule[s]; Timer1.start(); } break; case 1: // カウント開始前のカウント if (f==1 ) { if(t==match) { if (t<=0) { Timer1.stop(); t=modetime[mode]; s=modeidx[mode]; match=schedule[s]; stat=2; Timer1.start(); } tone (TONE,tonemap[s],duration[s]); match=schedule[++s]; } f=0; if (t % 10 == 0 ) { readyout(t/10);} } break; case 2: // 3,4,5分前のカウント if (f==1 ) { f=0; // タイマー処理 if(t==match) { tone (TONE,tonemap[s],duration[s]); match=schedule[++s]; if (t<=0) { Timer1.stop(); stat=0; } } // LCD処理 if (t<=0) { modeout(mode); lcd.setCursor(10,0); lcd.print("START!!"); } else { if (t % 10 == 0 ) { lcdout(t/10 , 8) ;} } // CANCEL処理 if(digitalRead(START) == 0) { mt++; if (mt==20) { Timer1.stop(); lcd.setCursor(1,1); lcd.print("CANCELED"); stat=0; mt=0; while (digitalRead(START)==0) {} modeout(mode); } } } break; default: break; } }