目次
前
次
信号機スケッチ
交通信号をエミュレートするスケッチを作成してみます。
3LEDをどこに接続するかを決めます。
ポートBに接続しておきます。
1ピンごとに処理するのではなく
DDRB
PORTB
を利用します。
点灯は、次のようにしてみます。
点灯パターンは、配列に入れて処理
すればよいでしょう。
時間間隔を生成するには、delayを利用
することで解決します。
状態変数を用意して、点灯処理を
制御します。
配線は、次のようにします。
スケッチの定義は以下。
#define INTERV 2000
#define LAST 5
// variables
byte bit_pat[LAST];
word xinterval ;
byte state ;
byte tmp ;
void setup()
{
// all bit output
DDRB = 0xff ;
// set interval
xinterval = INTERV ;
// set bit pattern
*(bit_pat+0) = ~0x01 ; // 000_001
*(bit_pat+1) = ~0x02 ; // 000_010
*(bit_pat+2) = ~0x04 ; // 000_100
*(bit_pat+3) = ~0x02 ; // 000_010
*(bit_pat+4) = ~0x01 ; // 000_001
// set state
state = 0 ;
}
// the loop() method runs over and over again,
// as long as the Arduino has power
void loop()
{
// impress
tmp = *(bit_pat+state) ;
PORTB = tmp ;
// increment
state++ ;
if ( state == LAST ) { state = 0 ; }
// delay
delay(xinterval);
}
1方向の交通信号ができたので、直交する
2方向に拡張してみます。
状態と配列値を増やせばよいので
スケッチの変更は簡単です。
#define INTERV 2000
#define LAST 8
// variables
byte bit_pat[LAST];
word xinterval ;
byte state ;
byte tmp ;
void setup() {
// all bit output
DDRB = 0xff ;
// set interval
xinterval = INTERV ;
// set bit pattern
*(bit_pat+0) = ~0x09 ; // 001_001
*(bit_pat+1) = ~0x0A ; // 001_010
*(bit_pat+2) = ~0x0C ; // 001_100
*(bit_pat+3) = ~0x0A ; // 001_010
*(bit_pat+4) = ~0x09 ; // 001_001
*(bit_pat+5) = ~0x11 ; // 010_001
*(bit_pat+6) = ~0x21 ; // 100_001
*(bit_pat+7) = ~0x11 ; // 010_001
// set state
state = 0 ;
}
// the loop() method runs over and over again,
// as long as the Arduino has power
void loop()
{
// impress
tmp = *(bit_pat+state) ;
PORTB = tmp ;
// increment
state++ ;
if ( state == LAST ) { state = 0 ; }
// delay
delay(xinterval);
}
ブレッドボード上に2方向の信号機に
相当するLEDを配置すると以下。
信号機には、歩行者用もあります。
歩行者用信号は、ひとつで、押しボタンスイッチは
対向で2個必要になります。
一方向だけの自動車と歩行者の信号を
考えてみれば、ブレッドボードにのる
部品は次のようになります。
自動車が停止したときに、歩行者は横断になるので
処理をステートマシンで記述して、スケッチに反映
させます。
押しボタンスイッチが押されたことを記憶しておき
自動車信号が赤のとき、歩行者がわたるとフラグが
セットされたなら、歩行者信号を「緑」にします。
ステートでは、次のようになります。
// set bit pattern
*(bit_pat+0) = ~0x09 ; // 001_001
if ( wflag == ON ) {
*(bit_pat+0) = ~0x11 ; // 010_001
}
*(bit_pat+1) = ~0x0a ; // 001_010
*(bit_pat+2) = ~0x0c ; // 001_100
*(bit_pat+3) = ~0x0a ; // 001_010
歩行者がボタンを押したことを記憶するために
フラグwflagを使います。
ステートが0のときに、ビットパターンを変えると
考えれば、自動車と歩行者の信号状態は、switch文
で簡単に記述できます。
switch ( state ) {
case 0 : tmp = ~0x09 ;
if ( wflag == ON ) { tmp = ~0x11 ; }
break ;
case 1 : tmp = ~0x0a ;
wflag = OFF ;
break ;
case 2 : tmp = ~0x0c ;
break ;
case 3 : tmp = ~0x0a ;
break ;
default : tmp = ~0x09 ;
break ;
}
PORTB = tmp ;
歩行者がボタンを押したか否かを記憶するには
シフトレジスタを利用します。シフトレジスタ
はタイマー割込みでボタンの状態を記憶して
2進数で01になったときに、フラグをセット
します。
タイマー割込みを使い、押しボタンの状態を
読み込みます。
void update_sw() {
// shift
bsft <<= 1 ;
// mask
bsft &= MASK03 ;
// get switch state
if ( digitalRead( BBUTTON ) == LOW ) { bsft |= ON ; }
// judge
if ( bsft == MASK01 ) { wflag = ON ; }
}
必要な情報が整ったので、スケッチを定義します。
#include <MsTimer2.h>
// pin assignment
#define BBUTTON 2
#define INTERV 200
#define OFF 0
#define ON OFF+1
#define MASK01 0x01
#define MASK03 0x03
int xinterval ;
byte state ;
byte tmp ;
byte bsft ;
byte tflag ;
// MtTimer2 interrupt handler
void update_sw() {
// shift
bsft <<= 1 ;
// mask
bsft &= MASK03 ;
// get switch state
if ( digitalRead( BBUTTON ) == LOW ) { bsft |= ON ; }
// judge
if ( bsft == MASK01 ) { wflag = ON ; }
}
void setup()
{
// LED
PORTB = 0xff ; // turn off all LEDs
DDRB = 0xff ; // all pin as outputs
// pin assignment
pinMode(BBUTTON,INPUT);
// delay counter
xinterval = INTERV ;
// clear shift registers
bsft = 0 ;
// clear flags
bflag = OFF ;
// initialize state
state = 0 ;
// 10ms period
MsTimer2::set(10,update_sw);
// enable
MsTimer2::start();
}
void loop()
{
// impress
switch ( state ) {
case 0 : tmp = ~0x09 ;
if ( wflag == ON ) { tmp = ~0x11 ; }
break ;
case 1 : tmp = ~0x0a ;
wflag = OFF ;
break ;
case 2 : tmp = ~0x0c ;
break ;
case 3 : tmp = ~0x0a ;
break ;
default : tmp = ~0x09 ;
break ;
}
PORTB = tmp ;
// increment
state++ ;
// judge
if ( state == 4 ) { state = 0 ; }
// delay
delay(xinterval);
}
目次
前
次