5-4 組み合わせてみよう

折角なので、本章で覚えた関数を組み合わせて楽しむ応用編をやってみましょう!
もちろん配線図もサンプルコードも用意してありますのでご安心ください。
   

まずはデジタル入力と出力の組み合わせです。
タクトスイッチを押すことで、LEDのON/OFFを切り替える装置を作ります。

  


  
本回路ではタクトスイッチの方は、プルダウンを使って値を安定させる仕様になっています。
抵抗はデジタル入力の項と同じものでOKです。
LEDの抵抗も、デジタル出力の項と同じ仕様でOKです。
既にお気付きの方もいるかもしれません。実はこの回路、講師が「きぐるみギミック制作講座」で、実際に作成を実演した回路と全く同じものになります。
つまりこの単元を通して、みなさんはあの日の講師と同じものを作っていることになります。

使う部品リスト

部品 個数
砲弾型LED球 1個
LEDのための抵抗器
(抵抗値は使うLEDのデータシートをもとに各自計算してください)
1個
タクトスイッチ 1個
タクトスイッチのための抵抗器(10kΩ) 1個


  (めちゃくちゃテンパっているあの日の講師)

  

サンプルコード5-4-1_switch_with_LED.inoを開いてください。

int LEDpin = 10; //LEDはD10
int SWpin = 2; //タクトスイッチはD2
bool value = false; //LEDの点灯状態を記憶する変数(falseはOFF、trueはONとします)

void setup() {
  pinMode(LEDpin, OUTPUT); //D10を出力モードにする
  pinMode(SWpin, INPUT); //D2を入力モードにする
}

void loop() {
  if (digitalRead(SWpin) == HIGH) { //D2が5Vを観測したら=スイッチが押されたら
    if (value == false) { //かつ、現在のLEDの点灯状態がfalse=OFFなら
      digitalWrite(LEDpin, HIGH); //D10の電圧を5Vにして電気を出力する
      value = true; //今のLEDの点灯状態はtrue=ONであるとvalueに記憶させる
    } else { //現在のLEDの点灯状態がtrue=ONなら
      digitalWrite(LEDpin, LOW); //D10の電圧を0Vにして電気を止める
      value = false; //今のLEDの点灯状態はfalse=OFFであるとvalueに記憶させる
    }
    while (digitalRead(SWpin) == HIGH) { 
      delay(100); 
    }
  }
}
1~2行目
int LEDpin = 10; //LEDはD10
int SWpin = 2; //タクトスイッチはD2

なんてことはないピン番号の設定です。
ちなみにアナログピンを「A(番号)」と呼ぶように、プログラムの解説ではデジタルピンは一般的に「D(番号)」と呼ばれることが多いです。
慣れるためにも今後は略称で行きます。

3行目
bool value = false; //LEDの点灯状態を記憶する変数(falseはOFF、trueはONとします)

LEDの点灯状態を記憶する変数valueを用意します。
プログラムの構造上、入れる値はfalseかtrueの二択しかないのでbool型を選択しました。

7行目
pinMode(SWpin, INPUT); //D2を入力モードにする

今回はプルダウン回路です。INPUT_PULLUP(=内部プルアップ有効)しないようご注意を。

11行目
if (digitalRead(SWpin) == HIGH) { //D2が5Vを観測したら=スイッチが押されたら

スイッチの値がHIGHであれば、スイッチが押されたとみなしてif文内部に突入します。

12行目
if (value == false) { //かつ、現在のLEDの点灯状態がfalse=OFFなら

またしてもif文です。if文の中にif文が入れ子になっている状態ですね。
今度のif文の条件はif (value == false) なので、変数valueの中身がfalseならTrueです。

このif文が存在する理由ですが、今回のプログラムではLEDがONならOFF、OFFならONにするという処理をしなければならないのですが、そのためには「今LEDはONかOFFどちらの状態か」を常に把握していなければなりません。
(ONの時にONの命令、OFFの時にOFFの命令をしたら…それは外からは動作不良に見えます)
しかしArduinoはLEDが点灯しているかどうかを自動で判別してくれません。
なので、変数を使って今のLEDの状態を記憶させたり、判定に使用したりします。
今回はvalueという変数の中身がfalseならOFF、trueならONという状態で取り扱うこととします。
(講師は後で見返した時の為にfalse=OFF/true=ONと扱うことを変数宣言の時にコメントで書き残すようにしてます)

13行目
digitalWrite(LEDpin, HIGH); //D10の電圧を5Vにして電気を出力する

valueの中身がfalseなのでLEDが現状OFFの場合の処理です。すなわちLEDをONにします。

14行目
value = true; //今のLEDの点灯状態はtrue=ONであるとvalueに記憶させる

LEDがONの状態になったので、valueの中身もそれに準じたtrueに変えておきます。

15行目
} else { //現在のLEDの点灯状態がtrue=ONなら

elseです。このelseは12行目のif文に対応しています。
12行目の判定でvalueがfalseではなかった場合(今回は消去法でtrue)はこちらの処理を行います。

16行目
digitalWrite(LEDpin, LOW); //D10の電圧を0Vにして電気を止める

今回はLEDの点灯状態がONの場合なので、LEDをOFFに切り替えます。

17行目
value = false; //今のLEDの点灯状態はfalse=OFFであるとvalueに記憶させる

そしてvalueの中身もfalseにしておきます。 if (value == false) {} はここで終了です。

19~21行目
while (digitalRead(SWpin) == HIGH) { 
  delay(100); 
}

if (value == false) {}を抜けましたが、その外側にあるif (digitalRead(SWpin) == HIGH) {}からはまだ抜けていません。
このif文にはまだ残された処理があります。それがこの行です。
タクトスイッチが押され続けた場合に処理を進めないためのwhile文です。
ボタンから指が離れた時点でこのwhile文を抜け、if文からも抜け、loop部の先頭に戻ります。
  
  

もういっちょいきましょう!今度はアナログ入力とデジタル出力の組み合わせです。
CdSセルで周囲の明るさを観測し、暗ければLEDをON、明るければOFFにする装置を作ります。

  


  
CdSの抵抗もLEDの抵抗も、以前使ったものと同じ仕様でOKです。

使う部品リスト

部品 個数
砲弾型LED球 1個
LEDのための抵抗器
(抵抗値は使うLEDのデータシートをもとに各自計算してください)
1個
CdSセル 1個
CdSセルのための抵抗器(10kΩ) 1個

  

サンプルコード5-4-2_CdS_with_LED.inoを開いてください。

int LEDpin = 4;  //LEDはD4
int CDSpin = A0;  //CdSはA0
int brightnessThreshold = 600; //LEDの状態を切り替えるかどうかの閾値

void setup() {
  pinMode(LEDpin, OUTPUT);  //D4を出力モードにする
}

void loop() {
  int value = 0; //CdSで読み取った値を入れる変数valueを用意
  value = analogRead(CDSpin); //valueにCdSで読んだ値を入れる

  if (value >= brightnessThreshold) {  //もしCdSで読んだ値がbrightnessThresholdの値以上(=周囲が暗い)なら
    digitalWrite(LEDpin, HIGH); //LEDを点灯する
  } else { //CdSの値がbrightnessThresholdの値未満(=周囲が明るい)なら
    digitalWrite(LEDpin, LOW); //LEDを消灯する
  }
  delay(500);
}
1行目
int LEDpin = 4;  //LEDはD4

今回LEDはD4に挿していますが、特に深い意味はないです。
(単にD4に挿せば配線図が見やすかったからというだけです…)

デジタル入出力はスケッチで正しく指定できていればどのソケットを使ってもOKです。
但し、以下のDピンはデジタル入出力には使わない方が無難です。

  • D0とD1:UARTと兼用のピン。UART用として使った方が無難です(特にR3の場合、絶対にデジタル入出力には使わないほうがいいです!)
  • D13:Lチカで使った、基板上のLEDと繋がっているピン
3行目
int brightnessThreshold = 600; //LEDの状態を切り替えるかどうかの閾値

変数brightnessThresholdを宣言して、600の数値をを入れます。
この変数を明るさの基準値として、LEDのON/OFFを切り替えるための判定に使います。

brightnessThresholdに入れる600という数値は、5-3_analogReadの項で得られたCdSの読み取り値をもとに決めています。
講師の環境では、CdSは平常時で200前後、CdSを手で覆って暗くすると500~980くらい、ケータイのライトを当てると100未満の数値を示しました。
なので、“CdSを軽く手で覆ったくらいの暗さ”で示される600以上の数値を“LEDを点灯すべき暗い状態”という基準にしています。

なおこの数値は環境によってブレがあります。
もしみなさんが5-3のコードを実行した際に、講師の環境とはだいぶ異なる数値を計測する場合は、みなさんの環境に合わせた“暗い”状態を示す数値に適宜書き換えてください。

10行目
int value = 0; //CdSで読み取った値を入れる変数valueを用意

CdSで読み取った値を格納する変数valueを宣言します。

11行目
value = analogRead(CDSpin); //valueにCdSで読んだ値を入れる

valueの中にA0で読み取った値を入れておきます。

13行目
if (value >= brightnessThreshold) {  //もしCdSで読んだ値がbrightnessThresholdの値以上(=周囲が暗い)なら

valueの数値をbrightnessThresholdと比較して、LEDをONにするかOFFにするかを判定します。
今回、brightnessThresholdの値は600に設定しました。
なので、このif文の動作は「valueの数値が600以上であればON」となります。

14行目
digitalWrite(LEDpin, HIGH); //LEDを点灯する

if文がtrueであれば、LEDをONにします。
5-4-1は“スイッチを押したら必ずLEDの状態を反転”させる装置でしたので、LEDの状態を常に記憶しておく必要がありました。
一方今回は、“周囲の状態が変わらなければLEDの状態は継続、基準値を超える変化があれば反転”という動作をする装置です。
ONの状態で引き続きONの命令を実行する(逆も然り)ことになっても動作として問題はないというかむしろ正しいので、LEDの状態を記憶しておく必要もありません。

15行目
} else { //CdSの値がbrightnessThresholdの値未満(=周囲が明るい)なら

else文です。valueが600未満(=周囲はある程度明るい)なら、こちらの処理に入ります。

16行目
digitalWrite(LEDpin, LOW); //LEDを消灯する

LEDを消灯します。先述の通り周囲がずっと明るければOFFの状態を継続します