目次

方向指示器スケッチ

 自動車の方向指示器と建物へ導く方向指示器の
 2つのスケッチを作成してみます。

 自動車の方向指示器は、2つのプッシュスイッチ
 と2つのLEDを利用してエミュレーションします。



 各デバイスとピン番号を指定します。



 ブレッドボード上にLEDとスイッチを実装
 すると、以下です。



 点滅周期は500msとして、左、右のどちらで
 点滅するかをmodeという変数でわかるとして
 みます。

 変数stateを利用して、このLSBが1か0かで
 LEDを点滅させる仕様としました。

  // none
  if ( mode == MODE_NONE ) {
    digitalWrite(LEFT_LED ,LED_LOW);
    digitalWrite(RIGHT_LED,LED_LOW);
  }
  // left direction
  if ( mode == MODE_LEFT ) {
    if ( state & 1 ) { digitalWrite(LEFT_LED,LED_HIGH); }
    else             { digitalWrite(LEFT_LED,LED_LOW) ; }
  }
  // right direction
  if ( mode == MODE_RIGHT ) {
    if ( state & 1 ) { digitalWrite(RIGHT_LED,LED_HIGH); }
    else             { digitalWrite(RIGHT_LED,LED_LOW) ; }
  }
  // increment
  state++ ;
  // delay
  delay(xinterval);

 変数modeの値を2スイッチの状態で
 決定することにします。
 それには、2スイッチの状態を入力
 する必要があるので、以下のように
 定義しました。

  tmp = (digitalRead(LEFT_SW) << 1) | digitalRead(RIGHT_SW) ;

 変数tmpの値で、mode値を決定します。

  switch ( tmp ) {
    case 1  : mode = MODE_LEFT  ; break ;
    case 2  : mode = MODE_RIGHT ; break ;
    default : mode = MODE_NONE  ; break ;
  }

 loopの内容が確定したので、setupを入れて
 スケッチを完成させます。

#define INTERV 500

#define LED_LOW  HIGH
#define LED_HIGH LOW

#define MODE_NONE  0
#define MODE_RIGHT 1
#define MODE_LEFT  2

// define data types
typedef unsigned char  UBYTE ;
typedef unsigned short UWORD ;

// pin assign
#define LEFT_LED  12
#define RIGHT_LED 11
#define LEFT_SW   9
#define RIGHT_SW  8

// variables
UWORD xinterval ;
UBYTE state ;
UBYTE mode ;
UBYTE tmp ;

void setup() {
  // PWM pin 
  pinMode(LEFT_LED ,OUTPUT);
  pinMode(RIGHT_LED,OUTPUT);
  pinMode(LEFT_SW  ,INPUT);
  pinMode(RIGHT_SW ,INPUT);
  // set interval
  xinterval = INTERV ;
  // set state
  state = 0 ;
  // set mode
  mode = MODE_NONE ;
}

// the loop() method runs over and over again,
// as long as the Arduino has power
void loop()
{
  // get mode
  tmp = (digitalRead(LEFT_SW) << 1) | digitalRead(RIGHT_SW) ;
  switch ( tmp ) {
    case 1  : mode = MODE_LEFT  ; break ;
    case 2  : mode = MODE_RIGHT ; break ;
    default : mode = MODE_NONE  ; break ;
  }
  // none
  if ( mode == MODE_NONE ) {
    digitalWrite(LEFT_LED ,LED_LOW);
    digitalWrite(RIGHT_LED,LED_LOW);
  }
  // left direction
  if ( mode == MODE_LEFT ) {
    if ( state & 1 ) { digitalWrite(LEFT_LED,LED_HIGH); }
    else             { digitalWrite(LEFT_LED,LED_LOW) ; }
  }
  // right direction
  if ( mode == MODE_RIGHT ) {
    if ( state & 1 ) { digitalWrite(RIGHT_LED,LED_HIGH); }
    else             { digitalWrite(RIGHT_LED,LED_LOW) ; }
  }
  // increment
  state++ ;
  // delay
  delay(xinterval);
}

 次に建物に導く方向指示器のスケッチを考えます。

 2つのプッシュスイッチと6つのLEDを利用して
 エミュレーションします。



 各デバイスとピン番号を指定します。



 ブレッドボード上に部品を実装すると以下。



 点滅周期は自動車と同じにして、スイッチを
 押している間、左から右あるいは右から左に
 LEDを点滅していくことに。

 6個のLEDの点滅パターンを配列に入れます。

  *(dirled+0) = ~0x01 ; // 1111 1110
  *(dirled+1) = ~0x02 ; // 1111 1101
  *(dirled+2) = ~0x04 ; // 1111 1011
  *(dirled+3) = ~0x08 ; // 1111 0111
  *(dirled+4) = ~0x10 ; // 1110 1111
  *(dirled+5) = ~0x20 ; // 1101 1111

 表示は、左から右、右から左の2通りに
 なりますが、パターンの引出し方を変え
 対応します。

  // left direction
  if ( mode == MODE_LEFT ) {
    PORTC = *(dirled+state) ;
  }
  // right direction
  if ( mode == MODE_RIGHT ) {
    i = LAST-state ;
    PORTC = *(dirled+i) ;
  }

 通常アナログで利用するピンは、デジタルに
 すると、14〜19になっています。14〜19ピン
 は、ポートCに接続されています。

 複数ピンを一度に扱うため、DDRC、PORTCを
 適用します。

 ここまで仕様を詰めたなら、自動車の方向指示器
 スケッチをコピーして、必要な部分を修正、追加
 します。出来上がったプログラムは、以下です。

#define INTERV 100
#define LAST   5
#define MAX    6

// define data types
typedef unsigned char  UBYTE ;
typedef unsigned short UWORD ;

// pin assign
#define LEFT_SW   9
#define RIGHT_SW  8

#define MODE_NONE  0
#define MODE_RIGHT 1
#define MODE_LEFT  2

// variables
UWORD xinterval ;
UBYTE state ;
UBYTE mode ;
UBYTE dirled[6] ;
UBYTE tmp ;
UBYTE i ;
UBYTE cport ;

void setup() {
  // PWM pin 
  pinMode(LEFT_SW  ,INPUT);
  pinMode(RIGHT_SW ,INPUT);
  DDRC = 0xff ;
  // set interval
  xinterval = INTERV ;
  // set state
  state = 0 ;
  // set mode
  mode = MODE_NONE ;
  // set values
  *(dirled+0) = ~0x01 ; // 1111 1110
  *(dirled+1) = ~0x02 ; // 1111 1101
  *(dirled+2) = ~0x04 ; // 1111 1011
  *(dirled+3) = ~0x08 ; // 1111 0111
  *(dirled+4) = ~0x10 ; // 1110 1111
  *(dirled+5) = ~0x20 ; // 1101 1111
}

// the loop() method runs over and over again,
// as long as the Arduino has power
void loop()
{
  // command interpreter
  {
    tmp = (digitalRead(LEFT_SW) << 1) | digitalRead(RIGHT_SW) ;
    // get mode
    switch ( tmp ) {
      case 1  : mode = MODE_LEFT  ; break ;
      case 2  : mode = MODE_RIGHT ; break ;
      default : mode = MODE_NONE  ; break ;
    }
  }
  // state machine
  {
    // none
    if ( mode == MODE_NONE  ) { cport = 0xff ; }
    // left direction
    if ( mode == MODE_LEFT  ) { cport = *(dirled+state) ; }
    // right direction
    if ( mode == MODE_RIGHT ) {
      i = LAST-state ;
      cport = *(dirled+i) ;
    }
    // impress
    PORTC = cport ;
    // increment
    state++ ;
    if ( state == MAX ) { state = 0 ; }
    // delay
    delay(xinterval);
  }
}

 loopの中は単純に、次のことを繰返しているだけです。
  1. 2つのスイッチの状態を取得
  2. 状態からモードを確定
  3. モードによりLEDへ出力するパターン生成
  4. LEDへパターン出力
  5. 状態値更新
  6. ディレイ
  7. 1にもどる
 PORTCは、ハードウエアピンなので、外部メモリ変数  cportに値を保存し、一度だけアクセスしています。  外部へのビットパターン出力は、一度きりにすると  バグが入る余地が少なくなります。

目次

inserted by FC2 system