目次

Knight Riderスケッチ

 マイコンでLEDを利用するとき、「Hello World!」に
 相当する定番テストプログラムを、自分の中では
 Knight Riderにしています。

 LEDを横一列に並べて(LED列)、左右に
 光の位置を変化させるのが、Knight2000
 (車に搭載されたAI)の特徴です。



 間隔をおいて、LED列にビットパターンを送ってやれば
 車のフロントグリルに並べたランプと同じ動作を実現
 できます。

 配列を用意して、その配列に値を格納しておきます。
 配列から値を取り出し、LED列に出力してみれば
 Knight Riderを実現できます。

 Arduinoに使われているAVRは、ATmega168なので
 ポートB、C、DのどれかをすべてLEDに接続して
 次のようにビットパターンを送ってやれば
 Knight2000のフロントグリルのランプのように
 光らせることが可能です。

  000000
  ↓
  100001
  ↓
  010010
  ↓
  001100
  ↓
  010010
  ↓
  100001



 loopの中のシーケンスは単純で、以下とします。
  1. 状態変数を利用し配列から値を取出す
  2. 値をLEDに出力
  3. 状態変数更新
  4. ディレイ
  5. 1に戻る
 これらの内容を踏まえて、スケッチを作成します。 #define INTERV 200 #define LAST 6 /* 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) = ~0x00 ; /* 000_000 */ *(bit_pat+1) = ~0x21 ; /* 100_001 */ *(bit_pat+2) = ~0x12 ; /* 010_010 */ *(bit_pat+3) = ~0x0c ; /* 001_100 */ *(bit_pat+4) = ~0x12 ; /* 010_010 */ *(bit_pat+5) = ~0x21 ; /* 100_001 */ /* set state */ state = 0 ; } void loop() { /* impress */ tmp = *(bit_pat+state) ; PORTB = tmp ; /* increment */ state++ ; if ( state == LAST ) { state = 0 ; } /* delay */ delay(xinterval); }  ポートBの6ビットをまとめて利用するため  用意されているDDRB、PORTBを使いました。  ブレッドボードにLEDを接続するとすれば  以下のようになります。  配列を利用せずに、ステートマシンで扱う場合は  次のように、出力メモリに状態に対応した値を  格納して対応します。 switch ( state ) { case 0 : dport = ~0x84 ; break ; case 1 : dport = ~0x28 ; break ; case 2 : dport = ~0x30 ; break ; case 3 : dport = ~0x28 ; break ; default : dport = 0xff ; break ; }  チルダー(~)は、論理値反転で利用します。  負論理でLEDの点灯を扱います。  シリアルで点滅処理を制御できるように  しておくと、ミスが減るので、コマンド  インタプリタを用意します。  コマンドインタプリタは、コマンドを英小文字  1文字に対応させて、次のように定義します。 if ( Serial.available() > 0 ) { /* get command */ cmd = Serial.read() ; /* judge */ if ( cmd == '?' ) { show_help() ; } if ( cmd == 'e' ) { flag = ON ; } if ( cmd == 'd' ) { flag = OFF ; } }  フラグを使い、ONで点滅させ、OFFで全LEDを  消灯とすれば、出力メモリの値をフラグ値で  変更すればよいでしょう。 if ( flag == OFF ) { dport = MASKFF ; }  まとめると、次のスケッチになります。 #define OFF 0 #define ON OFF+1 #define INTERV 200 #define MASKFF 0xff #define LAST 4 /* variables */ word xinterval ; byte state ; byte dport ; byte cmd ; byte flag ; void show_help() { Serial.println("? help"); Serial.println("e enable blink"); Serial.println("d disable blink"); } void setup() { /* start */ Serial.begin(9600); /* initialize port direction */ DDRD = 0xfe ; /* set interval */ xinterval = INTERV ; /* set state */ state = 0 ; /* clear flag */ flag = OFF ; } void loop() { /* command interpreter */ if ( Serial.available() > 0 ) { /* get command */ cmd = Serial.read() ; /* judge */ if ( cmd == '?' ) { show_help() ; } if ( cmd == 'e' ) { flag = ON ; } if ( cmd == 'd' ) { flag = OFF ; } } /* state machine */ { switch ( state ) { case 0 : dport = ~0x84 ; break ; case 1 : dport = ~0x28 ; break ; case 2 : dport = ~0x30 ; break ; case 3 : dport = ~0x28 ; break ; default : dport = 0xff ; break ; } /* judge */ if ( flag == OFF ) { dport = MASKFF ; } /* impress */ PORTD = dport ; /* update state */ state++ ; if ( state == LAST ) { state = 0 ; } } /* delay */ delay(xinterval); }  ブレッドボードにLEDを接続すると以下。

目次

inserted by FC2 system