目次
前
次
Go/Stop装置
Go/Stop装置は、タイムトライアル競技の
スタートの合図を送ります。
装置の動作を、状態遷移図で示すと、以下。
ランプが4個必要なので、Arduinoのピン14、15、16、17に
接続しておきます。
スタートスイッチを押すと、順番にLEDを点灯していくので
次のコードで順番に点灯していけばよいはず。
/* LED_3 */
PORTC |= (1 << 3);
/* delay */
PORTC = 0;
/* LED_2 */
PORTC |= (1 << 2);
/* delay */
PORTC = 0;
/* LED_1 */
PORTC |= (1 << 1);
/* delay */
PORTC = 0;
/* LED_0 */
PORTC |= (1 << 0);
/* delay */
PORTC = 0;
音も必要なので、PWM波形を出力できる9ピンを使います。
音を簡単に出力するには、tone関数を使っていきます。
tone(SOUND_BIT,440,1000);
tone(SOUND_BIT,880,1000);
最後だけ高い周波数にし、持続時間を追加して
LEDの点灯とともに使えば、一関数だけで動作を
エミュレート可能。
void perform_state()
{
/* LED_3 */
PORTC |= (1 << 3);
tone(SOUND_BIT,440,1000);
PORTC = 0;
/* LED_2 */
PORTC |= (1 << 2);
tone(SOUND_BIT,440,1000);
PORTC = 0;
/* LED_1 */
PORTC |= (1 << 1);
tone(SOUND_BIT,440,1000);
PORTC = 0;
/* LED_0 */
PORTC |= (1 << 0);
tone(SOUND_BIT,880,1000);
PORTC = 0;
}
似たような処理をしているので、反復で対応します。
void perform_state()
{
word f;
int i;
/* default */
f = 440 ;
/* repeat */
for ( i = 3 ; i > -1 ; i-- ) {
/* turn on target LED */
PORTC |= (1 << i);
/* judge */
if ( i == 0 ) { f = 880 ; }
/* send sound */
tone(SOUND_BIT,f,1000);
/* turn off all LED */
PORTC = 0;
}
}
プッシュスイッチを押されたことは、シフトレジスタを
用意して、次のように判定。
/* shift */
sft <<= 1 ;
/* mask */
sft &= 3 ;
/* get switch state */
if ( PINB & ON ) { sft |= ON ; }
/* judge */
if ( sft == 1 ) { state = MODE_RUN ; }
シフトレジスタを使うときは、時間差が必要なので
タイマー割込みを利用して、フラグで時間経過通知
してもらいます。
if ( tflag == ON ) {
/* clear */
tflag = OFF ;
/* shift */
sft <<= 1 ;
/* mask */
sft &= 3 ;
/* get switch state */
if ( PINB & ON ) { sft |= ON ; }
/* judge */
if ( sft == 1 ) { state = MODE_RUN ; }
}
LEDと音でスタートまでの合図を送るために
状態変数stateを用意して、loopの中で処理
すればよいでしょう。
void loop(void)
{
/* shift register */
if ( tflag == ON ) {
/* clear */
tflag = OFF ;
/* shift */
sft <<= 1 ;
/* mask */
sft &= 3 ;
/* get switch state */
if ( PINB & ON ) { sft |= ON ; }
/* judge */
if ( sft == 1 ) { state = MODE_RUN ; }
}
/* execute */
if ( state == MODE_RUN ) {
/* perform */
perform_state();
/* return */
state = MODE_IDLE ;
}
}
イベント通知のフラグを扱う関数を初期化するには
次のコードを利用。
/* 500ms period */
MsTimer2::set(500,update_trigger);
/* enable */
MsTimer2::start();
イベント通知のハンドラに相当する関数を定義。
void update_trigger(void)
{
/* flash LED */
send_led( xcnt & ON );
/* update counter */
xcnt++ ;
/* set flag */
tflag = ON ;
}
Arduinoが動作していることがわかるように
13ピンに接続したLEDを点灯します。
これは、Arduino基板上にあるので、そのまま
トグルで論理値を出力するだけで対応できます。
void send_led(byte x)
{
if ( x ) { PORTD |= (1 << LED_BIT) ; }
else { PORTD &= ~(1 << LED_BIT) ; }
}
まとめると以下。
#include <MsTimer2.h>
#define OFF 0
#define ON OFF+1
#define MODE_IDLE 0
#define MODE_RUN 1
#define LED_BIT 7
#define SOUND_BIT 9
byte state;
byte sft;
byte xcnt;
boolean tflag;
void send_led(byte x)
{
if ( x ) { PORTD |= (1 << LED_BIT) ; }
else { PORTD &= ~(1 << LED_BIT) ; }
}
void update_trigger(void)
{
/* flash LED */
send_led( xcnt & ON );
/* update counter */
xcnt++ ;
/* set flag */
tflag = ON ;
}
void perform_state()
{
word f;
int i;
/* default */
f = 440 ;
/* repeat */
for ( i = 3 ; i > -1 ; i-- ) {
/* turn on target LED */
PORTC |= (1 << i);
/* judge */
if ( i == 0 ) { f = 880 ; }
/* send sound */
tone(SOUND_BIT,f,1000);
/* turn off all LED */
PORTC = 0;
}
}
void setup(void)
{
/* set I/O values */
PORTD = 0x01 ;
PORTB = 0x01 ;
PORTC = 0x00 ;
/* set port directions */
DDRD = 0xfe ;
DDRB = 0xfe ;
DDRC = 0xff ;
/* clear flag */
tflag = OFF ;
/* set others */
xcnt = 0 ;
sft = 0 ;
state = MODE_IDLE ;
/* 500ms period */
MsTimer2::set(500,update_trigger);
/* enable */
MsTimer2::start();
}
void loop(void)
{
/* shift register */
if ( tflag == ON ) {
/* clear */
tflag = OFF ;
/* shift */
sft <<= 1 ;
/* mask */
sft &= 3 ;
/* get switch state */
if ( PINB & ON ) { sft |= ON ; }
/* judge */
if ( sft == 1 ) { state = MODE_RUN ; }
}
/* execute */
if ( state == MODE_RUN ) {
/* perform */
perform_state();
/* return */
state = MODE_IDLE ;
}
}
LEDを4個使うので、デジタルピンの指定をして
処理することもできます。setupの内容は、次の
ように記述できるでしょう。
#define PSHB 8
#define LED_M 13
#define LED_0 14
#define LED_1 15
#define LED_2 16
#define LED_3 17
#define SOUND_BIT 9
void setup(void)
{
/* set I/O values */
digitalWrite(LED_0,LOW);
digitalWrite(LED_1,LOW);
digitalWrite(LED_2,LOW);
digitalWrite(LED_3,LOW);
digitalWrite(SOUND_BIT,LOW);
/* set port directions */
pinMode(PSHB ,INPUT);
pinMode(LED_0,OUTPUT);
pinMode(LED_1,OUTPUT);
pinMode(LED_2,OUTPUT);
pinMode(LED_3,OUTPUT);
pinMode(LED_M,OUTPUT);
pinMode(SOUND_BIT,OUTPUT);
/* clear flag */
tflag = OFF ;
/* set others */
xcnt = 0 ;
sft = 0 ;
state = MODE_IDLE ;
/* 500ms period */
MsTimer2::set(500,update_trigger);
/* enable */
MsTimer2::start();
}
ピンの入出力と論理値を決めてしまえば
LEDの点灯と音出力を担当する関数は次
のように記述できます。
void perform_state()
{
word xf ;
word xt ;
/* default */
xf = 440 ;
xt = 1000 ;
/* LED_3 */
digitalWrite(LED_3,HIGH);
tone(SOUND_BIT,xf,xt);
digitalWrite(LED_3,LOW);
/* LED_2 */
digitalWrite(LED_2,HIGH);
tone(SOUND_BIT,xf,xt);
digitalWrite(LED_2,LOW);
/* LED_1 */
digitalWrite(LED_1,HIGH);
tone(SOUND_BIT,xf,xt);
digitalWrite(LED_1,LOW);
/* LED_0 */
xf = 880 ;
digitalWrite(LED_0,HIGH);
tone(SOUND_BIT,xf,xt);
digitalWrite(LED_0,LOW);
}
こちらの方が状態遷移図を、そのまま
プログラムにしたように見えます。
全体は、以下。
#include <MsTimer2.h>
#define OFF 0
#define ON OFF+1
#define MODE_IDLE 0
#define MODE_RUN 1
#define PSHB 8
#define LED_M 13
#define LED_0 14
#define LED_1 15
#define LED_2 16
#define LED_3 17
#define SOUND_BIT 9
byte state;
byte sft;
byte xcnt;
boolean tflag;
void send_led(byte x)
{
if ( x ) { digitalWrite(LED_M,HIGH); }
else { digitalWrite(LED_M,LOW ); }
}
void update_trigger(void)
{
/* flash LED */
send_led( xcnt & ON );
/* update counter */
xcnt++ ;
/* set flag */
tflag = ON ;
}
void perform_state()
{
word xf ;
word xt ;
/* default */
xf = 440 ;
xt = 1000 ;
/* LED_3 */
digitalWrite(LED_3,HIGH);
tone(SOUND_BIT,xf,xt);
digitalWrite(LED_3,LOW);
/* LED_2 */
digitalWrite(LED_2,HIGH);
tone(SOUND_BIT,xf,xt);
digitalWrite(LED_2,LOW);
/* LED_1 */
digitalWrite(LED_1,HIGH);
tone(SOUND_BIT,xf,xt);
digitalWrite(LED_1,LOW);
/* LED_0 */
xf = 880 ;
digitalWrite(LED_0,HIGH);
tone(SOUND_BIT,xf,xt);
digitalWrite(LED_0,LOW);
}
void setup(void)
{
/* set I/O values */
digitalWrite(LED_0,LOW);
digitalWrite(LED_1,LOW);
digitalWrite(LED_2,LOW);
digitalWrite(LED_3,LOW);
digitalWrite(SOUND_BIT,LOW);
/* set port directions */
pinMode(PSHB ,INPUT);
pinMode(LED_0,OUTPUT);
pinMode(LED_1,OUTPUT);
pinMode(LED_2,OUTPUT);
pinMode(LED_3,OUTPUT);
pinMode(LED_M,OUTPUT);
pinMode(SOUND_BIT,OUTPUT);
/* clear flag */
tflag = OFF ;
/* set others */
xcnt = 0 ;
sft = 0 ;
state = MODE_IDLE ;
/* 500ms period */
MsTimer2::set(500,update_trigger);
/* enable */
MsTimer2::start();
}
void loop(void)
{
/* shift register */
if ( tflag == ON ) {
/* clear */
tflag = OFF ;
/* shift */
sft <<= 1 ;
/* mask */
sft &= 3 ;
/* get switch state */
if ( digitalRead(PSHB) == HIGH ) { sft |= ON ; }
/* judge */
if ( sft == 1 ) { state = MODE_RUN ; }
}
/* execute */
if ( state == MODE_RUN ) {
/* perform */
perform_state();
/* return */
state = MODE_IDLE ;
}
}
目次
前
次