目次

信号機スケッチ

 交通信号をエミュレートするスケッチを作成してみます。



 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);
}


目次

inserted by FC2 system