1.Multi-function Shieldの取付け注意事項
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.ラップライマーのプログラム
ラップライマーとして動作するプログラムソースを下記に添付します。
/*
* 第一工業大学東京上野キャンパス
* 木下研究室 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単位戻す
}