目次
前
次
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の中のシーケンスは単純で、以下とします。
- 状態変数を利用し配列から値を取出す
- 値をLEDに出力
- 状態変数更新
- ディレイ
- 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を接続すると以下。
目次
前
次