Blinkから始まるArduino入門 その4 複数LED
●たくさんのLEDをBlinkするには
Arduinoのディジタル・ポート0番や13番のLEDの点滅ができました。ディジタル入出力は0~13番の14か所、アナログ入力のA0~A5の6か所、合計20か所にLEDがつなげられます。単純に1ポートに1 LEDをつながれば20個のLEDを制御できます。トライします。
●接続
LEDは緑色、電流制限抵抗は1.2kΩを使いました。
●スケッチ
/*const byte _LED0=19; // A5
const byte _LED1=18;
const byte _LED2=17;
const byte _LED3=16;
const byte _LED4=15;
const byte _LED5=14; // A0
const byte _LED6=0; // 0
const byte _LED7=1;
const byte _LED8=2;
const byte _LED9=3;
const byte _LED10=4;
const byte _LED11=5;
const byte _LED12=6;
const byte _LED13=7;
const byte _LED14=8;
const byte _LED15=9;
const byte _LED16=10;
const byte _LED17=11;
const byte _LED18=12;
const byte _LED19=13; // 13
*/
void setup() {
for (int i = 0 ; i < 20 ; i++) {
pinMode(i, OUTPUT);
}
}
void loop() {
for (int i = 0 ; i < 20 ; i++) {
digitalWrite(i,HIGH);
}
delay(5000);
for (int i = 0 ; i < 20 ; i++) {
digitalWrite(i,LOW);
}
delay(1000);
}
関数digitalWrite()を連続して実行すると、少しずつ処理時間がかかるので、20個のLEDはずれて光ります。オシロスコープで測ると約3.8usでした。もちろん、この差は小さすぎて人の目には判別つかないので、20個のLEDが同時にON/OFFしているように見えます。
●同時にON/OFFさせたい
コンパイルした結果得られる機械語は高速にプログラムが動きます。しかし、上述のように、1番ピンをONする関数の実行には複数の機械語がかかわり時間がかかるので、その次に2番ピンをONさせると時間にずれが生じます。この差を少なくすることはできるのでしょうか。
ATMega328にはPORTB、PORTC、PORTDの三つのポートのグループが存在します。すべてがArduinoでは使われていません。
PORTDとArduinoのディジタル入出力ピンの割り当ては次の関係です。
ピン | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
PD0 | PD1 | PD2 | PD3 | PD4 | PD5 | PD6 | PD7 |
PORTBとArduinoのディジタル入出力ピンの割り当ては次の関係です。
ピン | 8 | 9 | 10 | 11 | 12 | 13 |
PB0 | PB1 | PB2 | PB3 | PB4 | PB5 |
PORTCとArduinoのアナログ入力ピン(A0はディジタルでは14番ピン、A5は19番ピン)の割り当ては次の関係です。
ピン | 14 | 15 | 16 | 17 | 18 | 19 |
PC0 | PC1 | PC2 | PC3 | PC4 | PC5 |
ポート単位でON/OFFするように、アセンブラで記述します。
void setup() {
for (int i = 0 ; i < 20 ; i++) {
pinMode(i, OUTPUT);
}
}
void loop() {
PORTD = 0xff ; PORTB |= 0b00111111 ; PORTC |= 0b00111111 ;
delay(1000);
PORTD = 0 ; PORTB &= 0b11000000 ; PORTC &= 0b11000000 ;
delay(1000);
}
12番と13番ピンを観測しました。差はほとんどありません。
●スコープ
関数内に変数を宣言すると、それは、関数内のローカル変数になります。別の関数からは、知らない変数として扱われます。さらに、for文のカウンタなどに慣用的に使う i や j は、for ( int i=0; と宣言すると、このfor文の中だけで通用するローカル変数になります。
●スケッチの応用
最初に戻って、LEDを流れるように意識的に間隔を置いて表示するには、delay()をforループの中に入れます。
void setup() {
for (int i = 0 ; i < 20 ; i++) pinMode(i, OUTPUT);
}
void loop() {
for ( int i = 0 ; i < 20 ; i++) {
delay(10) ; digitalWrite(i,HIGH);
}
delay(100);
for ( int i = 0 ; i < 20 ; i++) {
delay(10) ; digitalWrite(i,LOW);
}
delay(100);
}