Multi-function Shield をArduino UNOに装着する場合、4桁セグメントLEDの裏面ピンがArduino UNOのUSBコネクタに接触します。この表示動作時に誤動作を起こしたり、ボード故障の原因になりますので、セグメントLEDのピンは短くカットして、USBコネクタの上面には絶縁テープを貼ってください。
2.超音波距離センサーの取り付け
超音波距離センサー(HCSR04)をMulti function Shieldにスマートに固定するためにシールド左上の7ピンコネクタ(APC220 Bluetooth)を使用します。簡単なソケットボードを制作してシールドに固定してください。
コネクタのピン3-4は、Arduino UNOのシリアルピン0-1に使用されていますので使えません。なので、コネクタピン6-7を使用します。Arduno UNOのピン5-6がシールド右下のコネクタに引き出されていますので、これを使用します。下記のようにArduno UNOのピン5-6が、HC-SR04のEcho, Trigピンつながるように配線してください。
ラップライマーとして動作するプログラムソースを下記に添付します。
/* * 第一工業大学東京上野キャンパス * 木下研究室 3年生プレゼミ教材 * 2016年4月㏠ */ #define EchoPin 5 // 超音波距離センサ HC-SR0 ピン 入力 #define TrigPin 6 // 超音波距離センサ HC-SR0 ピン 出力 #define LATCH_DIO 4 // シフトレジスタ 74HC595 ピン OUTPUT #define CLK_DIO 7 // シフトレジスタ 74HC595 ピン OUTPUT #define DATA_DIO 8 // シフトレジスタ 74HC595 ピン OUTPUT #define SW1 A1 // スイッチSW1 A1ピン :モード切替SW #define SW2 A2 // スイッチSW1 A1ピン :ラップタイマーリセット #define SW3 A3 // スイッチSW1 A1ピン #define SW3 A3 // スイッチSW1 A1ピン #define Mode_0 0 // モード0: トラック位置設定 #define Mode_1 1 // モード1: ラップタイマーモード #define LED1 13 // LED1 ON:トラック位置設定、 #define LED2 12 // LED2 ON: ラップタイマーモード #define LED3 11 // LED3 #define LED4 10 // LED4 #define ON 0 // LED is on #define OFF 1 // LED is off #define SPEAKER 3 // int cm; // 超音波距離センサー計測値(センチメートル) int TrackCenter = 15; // トラック中央値 (デフォルト) bool DP_on = false; //2桁目LEDのDPのOn/Off byte OperationMode = Mode_0; // 動作モード bool Sw2IsOn = false; // スイッチ2が押された bool LapTimerStart = false; // ラップライマー制御 bool LapTimerRunning = false; unsigned long Last_100ms_Count = 0; //100ms カウント最終値 int Count_100ms = 0; // 100ms カウンタ bool SpeakerOn = false; //スピーカーをオン用フラグ(オンは0.1秒に固定 unsigned long SpeakerDuration = 0; void setup () { Serial.begin(9600); //シリアルを使用する // シフトレジスタ 74HC595初期化 pinMode(LATCH_DIO, OUTPUT); pinMode(CLK_DIO, OUTPUT); pinMode(DATA_DIO, OUTPUT); // 超音波距離センサピン初期化 pinMode(TrigPin, OUTPUT); pinMode(EchoPin, INPUT); digitalWrite(TrigPin, LOW); // Speaker 設定(オンオフは方向レジスタで制御) pinMode(SPEAKER, INPUT); // LED1-4の初期化 pinMode(LED1, OUTPUT); pinMode(LED2, OUTPUT); pinMode(LED3, OUTPUT); pinMode(LED4, OUTPUT); digitalWrite(LED1, ON); //ON digitalWrite(LED2, ON); digitalWrite(LED3, ON); digitalWrite(LED4, ON); delay(1000); digitalWrite(LED1, OFF); //OFF delay(100); digitalWrite(LED2, OFF); delay(100); digitalWrite(LED3, OFF); pinMode(SPEAKER, OUTPUT); delay(100); digitalWrite(LED4, OFF); pinMode(SPEAKER, INPUT); } /* Main program */ void loop() { ReadSwitch(); //SW1, SW2 の読み取り // キャリブレーションモード if (OperationMode == Mode_0) { digitalWrite(LED1, ON); digitalWrite(LED2, OFF); Display(cm); DP_on = false; Count_100ms = 0; TrackCenter = 2 * cm / 3; LapTimerStart = false; LapTimerRunning = false; } // ラップタイマーモード if (OperationMode == Mode_1) { digitalWrite(LED1, OFF); digitalWrite(LED2, ON); DP_on = true; Display(Count_100ms); // ラップタイマーストップ状態でマイコンカーが横切ったらカウントスタート if (LapTimerStart == false && cm < TrackCenter ) { LapTimerStart = true; TurnSpeakerOn(); } // ラップタイマーラン状態でマイコンカーが横切ったらカウントストップ if (LapTimerRunning == true && cm < TrackCenter ) { LapTimerStart = false; TurnSpeakerOn(); } // ラップタイマーストップ状態で、SW2を押した場合 if (Sw2IsOn == true && LapTimerStart == false) { Count_100ms = 0; // カウントを0.0秒にリセット LapTimerRunning = false; // ラップタイマー停止 Sw2IsOn = false; // SW2 ONクリア } } // 100ms インターバル処理 if (millis() - Last_100ms_Count > 100) { Last_100ms_Count = millis(); cm = readDistance(); // 距離計測は100msごと if (LapTimerStart == true) { if (Count_100ms < 9999) { Count_100ms++; if (Count_100ms > 10 ) LapTimerRunning = true; // ラップライマーがスタートして1秒間はラン状態にしない。 else LapTimerRunning = false; } else Count_100ms = 0; } } if (SpeakerOn == true) { // スピーカーを0.5秒オンする if (millis() - SpeakerDuration > 50) { SpeakerOn = false; pinMode(SPEAKER, INPUT); } } } // SW1, SW2の読み取り, スイッチはアナログ読み void ReadSwitch(void) { static byte Sw1Latch; static byte Sw2Latch; if ( analogRead(SW1) < 100) { if (Sw1Latch == 0) { Sw1Latch = 1; TurnSpeakerOn(); if (OperationMode == Mode_0) { OperationMode = Mode_1; } else { OperationMode = Mode_0; Sw2IsOn = false; LapTimerStart = false; } } } else Sw1Latch = 0; if ( analogRead(SW2) < 100) { if (Sw2Latch == 0) { Sw2Latch = 1; Sw2IsOn = true; TurnSpeakerOn(); } } else Sw2Latch = 0; } void TurnSpeakerOn(void) { SpeakerOn = true; pinMode(SPEAKER, OUTPUT); SpeakerDuration = millis(); } /*4SEG LEDにNumberを表示する loop()関数内に配置すれば、3ms毎にスキャン表示を行いう Number: 0-9999 の4桁の整数 表示間隔: 5ms */ void Display(int Number) { static unsigned long Last_ms_Count; static byte ScanSeg = 0; if (millis() - Last_ms_Count > 3) { Last_ms_Count = millis(); switch (ScanSeg++) { case 0: WriteNumberToSegment(0 , Number / 1000); break; case 1: WriteNumberToSegment(1 , (Number / 100) % 10); break; case 2: WriteNumberToSegment(2 , (Number / 10) % 10); break; case 3: WriteNumberToSegment(3 , Number % 10); break; default: ScanSeg = 0; } } } /* セグメント表示 Segment: セグメント位置:0 - 3 Value:表示する値 : 0 - 9 */ void WriteNumberToSegment(byte Segment, byte Value) { // セグメント表示パターン: 0 - 9 const byte SEGMENT_MAP[] = {0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0X80, 0X90}; const byte SEGMENT_SELECT[] = {0xF1, 0xF2, 0xF4, 0xF8}; // 4-seg LED 選択パターン: 1 to 4 byte SegPattern; if (DP_on == 1 && Segment == 2) // LED2のDP On/Off判定 SegPattern = SEGMENT_MAP[Value] & 0x7F; // DPパターンのマスク else SegPattern = SEGMENT_MAP[Value]; digitalWrite(LATCH_DIO, LOW); shiftOut(DATA_DIO, CLK_DIO, MSBFIRST, SegPattern); shiftOut(DATA_DIO, CLK_DIO, MSBFIRST, SEGMENT_SELECT[Segment] ); digitalWrite(LATCH_DIO, HIGH); } // 距離測定:センチメートル int readDistance(void) { long t ; int ans ; digitalWrite(TrigPin, HIGH) ; // 超音波センサーに5usのパルスを出力する delayMicroseconds(5) ; digitalWrite(TrigPin, LOW) ; t = pulseIn(EchoPin, HIGH, 5000) ; // パルス幅の時間を測る ans = (t / 29) / 2 ; // 往復なので2で割る return ans ; //cm単位戻す }