こんにちは、「メカのりまき」です。
この記事では、「変数宣言」、「条件分岐」について、説明した後、最後にシリアルモニタを利用して、13番ピンのLEDを制御する方法について説明したいと思います。
本記事は、前々回の記事と前回の記事をまとめたような記事となっています。
まだ、前々回の記事と前回の記事をご覧になっていないという方は、是非、以下のリンクから、記事をご覧になってください。
目次
本記事で使用するもの
本記事で私が使用した物は以下の通りです。
- 「Arduino IDE2.0.3」をインストールしたPC(Windows11)
- USBケーブル
- Arduino Uno R3(ELEGOO UNO R3でも可)
「Arduino IDEのバージョンやOSの違いによって、画面構成や手順が異なる部分が出てくると思われますので、ご注意ください。
また、「Arduino Uno R3」の互換ボードであれば、「ELEGOO UNO R3」以外のボードでも、本記事と同様な手順で動作可能だと思われますが、動作検証はしていないので、その点はご了承ください。
変数宣言について
前回の記事で、変数とは、後から自由に中身を書き換えたり、読み出したりできるようにするための箱のようなものという説明をしました。
そして、変数には型というものがあり、格納したいデータの種類によって、用意されたものを選ぶという説明もしました。
今回は型の種類と変数宣言のやり方について、もう少し詳しく説明したいと思います。
型の種類
変数の型にはいくつか種類があります。
この記事で全部の型は紹介しませんが、私がよく使う型を抜粋して紹介します。
int型
1 2 |
int data1=1000; int data2=-777; |
整数を入れることができる型です。
「1000」、「777」などの正の数や「-1000」、「-777」などの負の数(マイナスの付いた数字)、「0」といった数値を入れることができます。
しかし、「3.14」、「-9.8」などの小数を入れることはできません。
float型
1 2 3 4 |
float data1=3.14; float data2=-9.8; float data3=1000; float data4=-777; |
実数を入れることができる型です。
「int型」で入れることができる整数に加え、「3.14」、「-9.8」などの小数も入れることができます。
「int型」で入れることができる整数が入れられるなら、数値を入れるのは全部「float型」で良くないかと思うかもしれません。
しかし、「float型」は「int型」よりも、多くの情報を扱うため、多くのメモリを必要とします。
また、計算が「int型」より複雑であるため、処理の速さが遅くなったり、扱い方を間違うと思わぬ誤差が生じたりするなどの問題点があります。
よって、整数のみを扱うと決まっているのであれば、「float型」よりも「int型」を使うことをお勧めします。
char型
1 2 |
char data1='A'; char data2='1'; |
1文字分のデータを扱うことができる型です。
文字を入れるときは下記のように、シングルクォーテーション( ‘ )で文字を囲います。
bool型
1 2 |
bool data1=true; bool data2=false; |
「true」か「false」のみ入れることができる型です。
下記で説明する条件分岐などで使われます。
変数宣言の方法
1 2 3 4 |
int data1; float data2; char data3; bool data4; |
変数宣言を行う際は、上記のように、使用する型の名前を入力した後、スペースを空け、変数名を入力します。
変数名については、別種類の型であっても、同じ名前のものは2個以上宣言することはできないので注意してください。
また、最初に入れておきたいデータが決まっている場合は、以下のように変数名の後にイコール( = )を追加することで、データを入れておくことができます。
1 2 3 4 |
int data1=100; float data2=3.14; char data3='A'; bool data4=true; |
さらに、同じ型を利用する場合は、以下のようにカンマ( , )で区切ることによって、一行で複数の変数を宣言することができます。
1 2 3 |
int data1,data2; float data3=3.14,data4=-9.8; char data5='A',data6='1',data7; |
スケッチの使用例
前々回の記事で13番のLEDを点滅させるために、以下のようなスケッチを書き込みました。
1 2 3 4 5 6 7 8 9 10 |
void setup() { pinMode(13,OUTPUT); } void loop() { digitalWrite(13,HIGH); delay(100); digitalWrite(13,LOW); delay(100); } |
今度はこれを、変数を使った以下のようなスケッチに変えてみてください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
int led_pin=13; int blink_time; void setup() { pinMode(led_pin,OUTPUT); blink_time=100; } void loop() { digitalWrite(led_pin,HIGH); delay(blink_time); digitalWrite(led_pin,LOW); delay(blink_time); } |
実行される動作としては、両方とも同じですが、このように変数宣言をすることによって、後から、出力させたいピンの番号を変えたい場合や、点滅速度を変えたい場合、訂正する箇所が少なくなるため、スケッチを書き直す際の効率が良くなります。
また、変数の値は「void setup()」「void loop()」内で、変更が可能です。
よって、以下で説明する条件分岐と組みあわせることによって、「~をしたら~の速度を変更する」といった使い方をすることができます。
条件分岐(if文)について
前回の記事では、条件分岐(if文)を使うことにより、シリアルバッファに文字が格納されていたら、文字を読み込むといったスケッチを説明しました。
今回は条件分岐をさせる際に使用する「if文」について、さらに詳しく説明したいと思います。
if文の中身が実行される条件
if文の中身が実行される条件は次のようなときです。
ifの隣の( )内にあるbool型の変数が「true」のとき
1 2 3 4 5 6 7 8 9 10 |
bool data1=true; if(data1){ //処理1; } if(true){ //処理2; } if(1000){ //処理3; } |
上記のように、ifの隣の( )内にあるdata1が「true」である場合、if文内の処理が実行されます。
また、ifの隣の( )内にtrueと直接入力しても、if文内の処理は実行されます。
さらに、少し変わったやり方ではありますが、ifの隣の( )内に0以外の適当なデータを入れた場合にも、if文内の処理は実行されます。
適当なデータを入れても、内部の処理が実行される理由としては、ifの隣の( )内のデータが無理やりbool型に入れられ、0を「false」、それ以外を「true」にしてしまうからです。
このように、型にデータを入れたとき、その型に合わせてデータが変換されることを「型変換」と呼びます。
「型変換」についての詳しい説明は、記事が長くなってしまうので、後日、別の記事で行いたいと思います。
ifの隣の( )内にある条件式が正しいとき
1 2 3 |
if(条件式){ //処理1; } |
上記の場合、ifの後の( )内の条件式が正しければ、中身の処理が実行されます。
( )内の条件式を書く際には、以下で説明する比較演算子というものを使用します。
比較演算子
比較演算子は、「〇が△と等しかったら」、「〇が△より大きかったら」といった条件を書くための記号です。
以下に、比較演算子の使用パターンを書いていきます。
〇が△と等しい
1 2 3 |
if(data1==0){ //処理1; } |
上記の場合「data1」の値が0ときに、中身が実行されます。
〇が△と等しくない
1 2 3 |
if(data1!=0){ //処理1; } |
上記の場合「data1」の値が0以外のときに、中身が実行されます。
〇が△より大きい
1 2 3 |
if(data1>0){ //処理1; } |
上記の場合「data1」の値が0よりも大きいときに、中身が実行されます。
「data1」の値が0のときは、中身が実行されません。
〇が△以上
1 2 3 |
if(data1>=0){ //処理1; } |
上記の場合「data1」の値が0以上のときに、中身が実行されます。
「data1」の値が0のときも、中身が実行されます。
〇が△より小さい
1 2 3 |
if(data1<0){ //処理1; } |
上記の場合「data1」の値が0よりも小さいときに、中身が実行されます。
「data1」の値が0のときは、中身が実行されません。
〇が△以下
1 2 3 |
if(data1<=0){ //処理1; } |
上記の場合「data1」の値が0以下のときに、中身が実行されます。
「data1」の値が0のときも、中身が実行されます。
比較演算子の使用パターンは以上になります。
上記では、0との比較のみを記述しましたが、以下のように別の数値や変数同士を比較することもできます。
1 2 3 4 5 6 7 8 9 |
if(data1>=1000){ //処理1; } if(data2=='A'){ //処理2; } if(data3<=data4){ //処理3; } |
複合条件(AND/OR)
上記では、if文1個につき、1つの条件のみでしたが、以下で説明する「AND演算」、「OR演算」を使用することで、複合的な条件を指定することもできます。
AND演算
1 2 3 4 5 6 |
if(data1>=0&&data1<10){ //処理1; } if(data1==0&&data2==0&&data3==0){ //処理2; } |
上記の例では、「data1」の値が0以上かつ10よりも小さい場合、処理1が実行されます。
さらに、「data1」、「data2」、「data3」の値がすべて0の場合、処理2が実行されます。
このように、条件式がすべて正しい場合のみ処理を実行させるものを「AND演算」と呼び、条件式の間にアンドマーク( & )を二つ入れます。
OR演算
1 2 3 4 5 6 |
if(data1==0||data1==10){ //処理1; } if(data1==0||data2==0||data3==0){ //処理2; } |
上記の例では、「data1」の値が0か10の場合、処理1が実行されます。
さらに、「data1」、「data2」、「data3」の値のどれかが0の場合、処理2が実行されます。
このように、条件式のどれかが正しい場合に処理を実行させるものを「OR演算」と呼び、条件式の間にバーティカルバー( | )を二つ入れます。
if文が実行されなかった場合の処理
ifの隣の( )内にあるbool型の変数が「false」の場合や条件式が正しくない場合、中身の処理は行われず、次の別の処理に進みます。
しかし、下記で説明する「else if」や「else」を使うことで、条件を満たさなかったときの処理を追加することができます。
else if(条件式)
1 2 3 4 5 6 7 8 |
if(data1==0){ //処理1; }else if(data1==1){ //処理2; }else if(data2==0){ //処理3; } //次の別の処理 |
「else if(条件式)」は前のif文が条件を満たさなかった場合、さらに追加で条件を加えて、その条件を満たした場合、中身を実行させます。
図にまとめると以下のようになります。
else
1 2 3 4 5 6 7 8 |
if(data1==0){ //処理1; }else if(data1==1){ //処理2; }else{ //処理3; } //次の別の処理 |
「else 」は前のif文が条件を満たさなかった場合、中身を実行させます。
図にまとめると以下のようになります。
スケッチの使用例
以下のスケッチは、ボードに送信された文字に応じて、シリアルモニタに指定した文字列を出力させるスケッチです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
char input_char; void setup() { Serial.begin(9600); } void loop() { if(Serial.available() > 0){ input_char = Serial.read(); if(input_char=='a'||input_char=='A'){ Serial.println("Apple"); }else if(input_char=='b'||input_char=='B'){ Serial.println("Banana"); }else if(input_char=='c'||input_char=='C'){ Serial.println("Cherry"); }else{ Serial.println("Gorilla"); } } } |
シリアルモニタで「a」または「A」を送信したときは「Apple」、「b」または「B」を送信したときは「Banana」、「c」または「C」を送信したときは「Cherry」、その他の文字を送信したときは、「Gorilla」と表示されます。
ボードに書き込んだ後、シリアルモニタを使って確かめてみてください。
シリアルモニタを使った文字のやり取りについては前回の記事で説明しているので、分からない場合は前回の記事を確認してみてください。
しっかりと、指定通りの文字が出力されたでしょうか。
指定した文字の下に「Gorilla」が勝手に表示されてはいないでしょうか。
実はボードへ文字を送信する際、下の画像の赤枠部分が「改行なし」に選択されていない場合、指定した文字の下に「Gorilla」が表示されてしまいます。
「Gorilla」が表示される理由は、上記の赤枠部分が「RFのみ」の場合は、「\n」(これで1文字の特殊な文字)という改行コード、「CRのみ」の場合は、「\r」(これで1文字の特殊な文字)という改行コード、「CRおよびRF」の場合は、「\r」、「\n」の両方が、入力した文字の後に送信されており、その改行コードがif文の条件で指定した文字と異なるその他の文字として認識され、elseの中身が実行されるためです。
図で表すと以下のようになります。
シリアルモニタでLEDを制御する
上記で説明した知識を組み合わせれば、以下のように、シリアルモニタでLEDを制御するスケッチを書くことができます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
int led_pin=13; int blink_time; char input_char; bool blink_mode=false; void setup() { pinMode(led_pin,OUTPUT); Serial.begin(9600); } void loop() { if(Serial.available() > 0){ input_char = Serial.read(); if(input_char=='a'||input_char=='A'){ Serial.println("LED_ON"); digitalWrite(led_pin,HIGH); blink_mode=false; }else if(input_char=='b'||input_char=='B'){ Serial.println("LED_OFF"); digitalWrite(led_pin,LOW); blink_mode=false; }else if(input_char=='c'||input_char=='C'){ Serial.println("LED_blink_mode100"); blink_time=100; blink_mode=true; }else if(input_char=='d'||input_char=='D'){ Serial.println("LED_blink_mode1000"); blink_time=1000; blink_mode=true; } } if(blink_mode){ digitalWrite(led_pin,HIGH); delay(blink_time); digitalWrite(led_pin,LOW); delay(blink_time); } } |
今回は、シリアルモニタで「a」または「A」を送信したとき、13番のLEDを点灯、「b」または「B」を送信したとき、13番のLEDを消灯、「c」または「C」を送信したとき、13番のLEDを素早く点滅、「d」または「D」を送信したとき、13番のLEDをゆっくり点滅させるというスケッチを書きました。
「void loop()」の部分を図にまとめると以下のようになります。
if文を多く使用すると、スケッチが迷路のように複雑になり、今どのような状態であるかが分からなくなることがあります。
そういったときは、上記のスケッチのように、「Serial.println()」などでシリアルモニタに文字を出力させ、今どのような状態であるかを確認できるようにすると良いでしょう。
「変数宣言」、「条件分岐」の説明とシリアルモニタで13番ピンのLEDを制御する方法については以上となります。
「変数宣言」、「条件分岐」をマスターすれば、かなり作れるものの幅が広がります、今は完全に理解していなくても、これから色々なものを作るときに、「変数宣言」、「条件分岐」が良く出てくるので、分からない場合はこの記事と照らし合わせて、理解を深めていただければと思います。
次回は、ブレッドボードで回路を作成して、LEDを点灯させる方法について説明したいと思います。
本記事はここまでです。ご清覧ありがとうございました。
広告
楽天モーションウィジェットとGoogleアドセンス広告です。
気になる商品がございましたら、チェックをしてみてください。