目次
前
次
乱数でイルミネーション
ArduinoのAPIには、乱数を発生するrandomが
あります。
このAPIで、イルミネーションを実現。
LEDは11個を、電流制限抵抗といっしょに
ブレッドボードに差し込み。
回路は、単純。
電流制限抵抗の値は、VFを2Vとし、Arduinoの
GPIOピンから5V出力するとして、次のように
計算し、問題がないことを確認。
i = (5V-2V)/470(Ω)
= 3V / 470(Ω)
= 3V / 500(Ω)
= 3000mV / 500(Ω)
= 6mA
LEDに流れる電流は、7mAまではないので、破損は
ないでしょう。
許容電力250mWのカーボン抵抗で、耐えられるかを
計算してみると、50mAくらいで1/5くらいでOK。
W = V x i
= 3V x 6mA
= 48mA
LEDを11個使うので、どのピンに接続するのかを
マクロ定義。
#define LED00 3
#define LED01 4
#define LED02 5
#define LED03 6
#define LED04 7
#define LED05 8
#define LED06 9
#define LED07 10
#define LED08 11
#define LED09 12
#define LED10 14
Arduino基板には、D13にLEDが接続されている
ので、そのピンをスキップ。
回路図から、LEDを接続するピンを初期化する
関数を定義して、関数setup()内で使えるよう
にしておきます。
#define OFF 0
#define ON OFF+1
void init_led_pins()
{
byte ii ;
for ( ii = 0 ; ii < 10 ; ii++ ) {
digitalWrite( LED00 + ii , OFF );
pinMode( LED00 + ii , OUTPUT );
}
digitalWrite( LED10 , OFF );
pinMode( LED10 , OUTPUT );
}
ピン番号が連番であれば、for文を利用して
全部のピンの論理値と入出力を指定できます
が、LED10だけ番号が飛んでいるので、for文
の外でコンフィグレーション。
乱数を生成して、1個のLEDだけ点灯する
ステートマシンを定義。
#define LCNTMAX 3000
byte lstate ;
byte rd ;
unsigned long lcnt ;
void led_handling()
{
switch ( lstate ) {
/* generate random number */
case 0 :
rd = random(11);
lstate = 1 ;
break ;
/* turn on target LED and duration */
case 1 :
led_on( rd );
lcnt = millis() + LCNTMAX ;
lstate = 2 ;
break ;
/* delay */
case 2 :
lstate = 2 ;
if ( millis() > lcnt ) { state = 3 ; }
break ;
/* return first state */
case 3 :
lstate = 0 ;
break ;
/* others */
default :
break ;
}
}
ステートマシンの中で使っているLEDを1個だけ
点灯する処理関数を定義します。
void led_on(byte x)
{
byte ii ;
/* turn off all LEDs */
for ( ii = 0 ; ii < 10 ; ii++ ) {
digitalWrite( LED00 + ii , OFF );
}
digitalWrite( LED10 , OFF );
/* turn of target LED */
if ( x > 9 ) {
digitalWrite( LED10 , ON ) ;
} else {
digitalWrite( LED00 + x , ON ) ;
}
}
ステートマシンを動かすためには、状態変数lstateの
初期化が必要なので、関数init_led_pinsに入れて対応。
void init_led_pins()
{
byte ii ;
for ( ii = 0 ; ii < 10 ; ii++ ) {
digitalWrite( LED00 + ii , OFF );
pinMode( LED00 + ii , OUTPUT );
}
digitalWrite( LED10 , OFF );
pinMode( LED10 , OUTPUT );
/* initialize state value */
lstate = 0 ;
}
スケッチ作成の部品が揃ったのでまとめ。
#define LED00 3
#define LED01 4
#define LED02 5
#define LED03 6
#define LED04 7
#define LED05 8
#define LED06 9
#define LED07 10
#define LED08 11
#define LED09 12
#define LED10 14
#define OFF 0
#define ON OFF+1
#define LCNTMAX 3000
byte lstate ;
byte rd ;
unsigned long lcnt ;
void init_led_pins()
{
byte ii ;
for ( ii = 0 ; ii < 10 ; ii++ ) {
digitalWrite( LED00 + ii , OFF );
pinMode( LED00 + ii , OUTPUT );
}
digitalWrite( LED10 , OFF );
pinMode( LED10 , OUTPUT );
/* initialize state value */
lstate = 0 ;
}
void led_on(byte x)
{
byte ii ;
/* turn off all LEDs */
for ( ii = 0 ; ii < 10 ; ii++ ) {
digitalWrite( LED00 + ii , OFF );
}
digitalWrite( LED10 , OFF );
/* turn of target LED */
if ( x > 9 ) {
digitalWrite( LED10 , ON ) ;
} else {
digitalWrite( LED00 + x , ON ) ;
}
}
void led_handling()
{
switch ( lstate ) {
/* generate random number */
case 0 :
rd = random(11);
lstate = 1 ;
break ;
/* turn on target LED and duration */
case 1 :
led_on( rd );
lcnt = millis() + LCNTMAX ;
lstate = 2 ;
break ;
/* delay */
case 2 :
lstate = 2 ;
if ( millis() > lcnt ) { state = 3 ; }
break ;
/* return first state */
case 3 :
lstate = 0 ;
break ;
/* others */
default :
break ;
}
}
void setup()
{
init_led_pins();
}
void loop()
{
led_handling();
}
イルミネーションごときに、ステートマシンを
使うことはないだろうと言われましたが、複数
のLED基板があったなら、ステートマシンを使う
ことなしに実現したら、バグの嵐で完成しない
でしょう。
ArduinoMega2560のように、多数のI/Oピンを
持つマイコン基板では、次のようにLEDを接続
すると、初期化と点灯するLEDを指定する関数
が単純になります。
初期化は、次のように単純に。
#define OFF 0
#define ON OFF+1
#define PS0 24
void init_led_pins()
{
byte ii ;
for ( ii = 0 ; ii < 11 ; ii++ ) {
digitalWrite( PS0 + ii , OFF );
pinMode( PS0 + ii , OUTPUT );
}
/* initialize state value */
lstate = 0 ;
}
ターゲットとするLEDの点灯は、for文と
switchを利用して記述。
void led_on(byte x)
{
byte ii ;
/* judge */
if ( x > 10 ) return ;
/* turn off all LEDs */
for ( ii = 0 ; ii < 11 ; ii++ ) {
digitalWrite( PS0 + ii , OFF );
}
/* turn of target LED */
digitalWrite( PS0 + x , ON ) ;
}
下位の関数を書き換えたので、全体は
次のソースコードに。
#define OFF 0
#define ON OFF+1
#define PS0 24
#define LCNTMAX 3000
byte lstate ;
byte rd ;
unsigned long lcnt ;
void init_led_pins()
{
byte ii ;
for ( ii = 0 ; ii < 11 ; ii++ ) {
digitalWrite( PS0 + ii , OFF );
pinMode( PS0 + ii , OUTPUT );
}
/* initialize state value */
lstate = 0 ;
}
void led_on(byte x)
{
byte ii ;
/* judge */
if ( x > 10 ) return ;
/* turn off all LEDs */
for ( ii = 0 ; ii < 11 ; ii++ ) {
digitalWrite( PS0 + ii , OFF );
}
/* turn of target LED */
digitalWrite( PS0 + x , ON ) ;
}
void led_handling()
{
switch ( lstate ) {
/* generate random number */
case 0 :
rd = random(11);
lstate = 1 ;
break ;
/* turn on target LED and duration */
case 1 :
led_on( rd );
lcnt = millis() + LCNTMAX ;
lstate = 2 ;
break ;
/* delay */
case 2 :
lstate = 2 ;
if ( millis() > lcnt ) { state = 3 ; }
break ;
/* return first state */
case 3 :
lstate = 0 ;
break ;
/* others */
default :
break ;
}
}
void setup()
{
init_led_pins();
}
void loop()
{
led_handling();
}
下位の関数を書き換えるだけで、上位の
関数、手続きをかえないで済ませられる
のが、ポイント。
目次
前
次