前回の記事では、スイッチが押されたことを検知するアルゴリズムを考えました。これから、そのアルゴリズムをもとにスケッチを作成していきます。
第10回から第12回までの内容は、少し難しくなっています。
すべて理解できなくても、第13回以降の記事がわからなくなる、ということはありません。理解できるところまでチャレンジしてみましょう!
もし難しく感じたら、とりあえず第12回の記事まではスキップして、第13回の記事からお読みいただければと思います。
日本語でスケッチを考える
これからスケッチを作成していきますが、最初は日本語まじりのスケッチで検討します。
それでは、前回考えたアルゴリズムを図でもう一度確認してみましょう。

スイッチが押されたタイミングを検知するには、この図の赤い矢印のタイミングの
「前回のスイッチ状態がOFF」かつ「今回のスイッチ状態がON」
の確認すればよかったんですよね。
ということは、loop
関数ではまずは次のように書くことができます。
void loop() {
if( 「前回のスイッチ状態がOFF」かつ「今回のスイッチ状態がON」 ) {
// スイッチが押されたことを検知したので、LEDを50ms点灯する
digitalWrite(12, HIGH);
delay(50);
digitalWrite(12, LOW);
}
ポイントとしては、3行目のようにif
の条件を書ければ、最初の図の赤い矢印のタイミングだけ条件が成立します。
つまり、スイッチが押されたことを検知してLEDをピカッと50ms、1回だけ光らせることができるはずです。
それでは次に、 if( 「前回のスイッチ状態がOFF」かつ「今回のスイッチ状態がON」 )
の部分をどうすればよいか、考えていきまょう。
スイッチ状態の記録
先ほど作成したプログラムでちょっと気になるところがあります。
それは「前回のスイッチ状態」です。
loop
関数の中で「今回のスイッチ状態」はすぐにわかりますよね。digitalRead(A5)
で現在のスイッチ状態を読み取ればOKです。
でも「前回のスイッチ状態」とは、前回loop
関数を処理した時のスイッチ状態のことです。今回のloop
関数の処理では、すでに前回のloop()関数の処理は終わっています。
そこで、「前回のスイッチ状態」は前回のloop
関数を処理したときに記録しておく必要があります。
前回のスイッチ状態を記録しておきたいのですが、どうしたらよいか、詳しく検討してみましょう。
digitalRead(A5)
で読み取ったスイッチ状態は、1
(OFF)か0
(ON)のどちらかです。
この1
か0
を記録、つまり数値をメモしておく機能って、今まで何度も出てきましたよね。
そうです!「変数」(メモ帳)を使ってdigitalRead(A5)
で読み取った値を記録すればよさそうです。
digitalRead(A5)
の戻り値は0
か1
ですので、uint8_t
型(0〜255)の変数に代入することにします。
また、if
で前回と今回の値を扱いますので、両方とも以下のように変数宣言することにします。
記録する内容 | 変数名 |
前回のスイッチ状態 | zenkai(uint8_t型) |
今回のスイッチ状態 | konkai(uint8_t型) |
ということで、スケッチは以下のように書いてみました。
void loop() {
// 前回と今回のスイッチ状態を記録する変数
uint8_t zenkai, konkai;
if( zenkai == 1 かつ konkai == 0 ) {
// スイッチが押されたことを検知したので、LEDを50ms点灯する
digitalWrite(12, HIGH);
delay(50);
digitalWrite(12, LOW);
}
}
4行目で変数の宣言をして、6行目のif
の条件部分を変数名に書き換えました。
ところで、if
の条件を変数に置き換えてみたのはいいですが、この変数に実際のスイッチ状態を代入する必要があります。
これから今回のスイッチ状態konkai
、前回のスイッチ状態zenkai
の変数に何をどのように代入すればよいか検討しましょう!
今回のスイッチ状態
最初に、今回のスイッチ状態の変数konkai
について考えます。
この変数には、今回のスイッチ状態を代入すればよいわけですから、
konkai = digitalRead(A5);
と書いて、単に現在のスイッチ状態を変数konkai
に代入すれば実現できます。
この変数はif
の条件部分で使いますので、if
より前に変数に代入しておくことが必要です。
void loop() {
// 前回と今回のスイッチ状態を記録する変数
uint8_t zenkai, konkai;
// 今回のスイッチ状態を調べて、変数「konkai」に代入する
konkai = digitalRead(A5);
if( zenkai == 1 かつ konkai == 0 ) {
// スイッチが押されたことを検知したので、LEDを50ms点灯する
digitalWrite(12, HIGH);
delay(50);
digitalWrite(12, LOW);
}
}
これで今回のスイッチ状態の処理はできました!
前回のスイッチ状態
では前回のスイッチ状態の変数zenkai
はどうしたらよいでしょうか?
もう一度、スイッチ状態の図を確認してみましょう。

この図で、❶の緑色の点線枠の部分のタイミングで条件を判断するケースを考えてみます。
このタイミングの条件判断を行う場合、先程説明したように「今回のスイッチ状態」はdigitalRead(A5)
で調べればOKです。(さらに調べた結果はkonkai
変数に代入しています)
上の図では「今回の状態」はONになります。
次に、❷の赤色の点線枠の「今回の状態」というのは、❸のオレンジ色の点線枠にあるように、次回の条件判断を行う時の「前回の状態」になっています。
かなりややこしい話になってきましたね…泣
ここで、他のどのタイミングを見ても、今回の条件判断時の「今回の状態」は、次回の条件判断時の「前回の状態」になっていますよね。
ということはですよ、今回のif
の判定が終わった後、次回loop
関数を処理するときのために「今回の状態」を「前回の状態に保存しておく」ことが必要になります。
この処理は次のように17行目に追加しました。
void loop() {
// 前回と今回のスイッチ状態を記録する変数
uint8_t zenkai, konkai;
// 今回のスイッチ状態を調べて、変数「konkai」に代入する
konkai = digitalRead(A5);
if( zenkai == 1 かつ konkai == 0 ) {
// スイッチが押されたことを検知したので、LEDを50ms点灯する
digitalWrite(12, HIGH);
delay(50);
digitalWrite(12, LOW);
}
// 今回のスイッチ状態を、次回の判断のとき用に、前回のスイッチ状態に保存しておく
zenkai = konkai;
}
さて、、、
かなりややこしくなってきました。
考えているとややこしくて「キーッ」ってなりそうですが、スケッチ完成までもう少しです!
もう一踏ん張りして先に進めましょう!
論理演算子
さて、スケッチはかなりの部分が出来上がりましたが、まだ一つ残っていますよね。
それは、zenkai == 1 かつ konkai == 0
の「かつ」の部分です。
電子工作では複数の条件を判断することが多くあります。例えば「気温が25度以上かつ湿度が75%以上のときは熱中症警戒と判定する」などです。
そこで、if
の条件部分で複数の条件を組み合わせて判断する方法を習得しましょう。
複数の条件を組み合わせる場合、次のように「かつ」「または」「ではない」の条件を組み合わせるための書き方が用意されています。
意味 | C++言語 | 呼び方 | 書き方の例 |
---|---|---|---|
かつ | && | 「論理積」 または「AND」 | zenkai == 1 && konkai == 0 (意味は「zenkaiが1」かつ「konkaiが0」) |
または | || | 「論理和」 または「OR」 | zenkai == 1 || konkai == 0 (意味は「zenkaiが1」または「konkaiが0」) |
ではない | ! | 「論理否定」 または「NOT」 | !(zenkai == 1) (意味は「zenkaiが1ではない」) |
またいろいろと新しい言葉が出てきましたね… 少しずつ読み解いていきましょう。
日本語の「かつ」「または」「ではない」は、C++言語では&
や|
、!
の記号を使って上のように表記します。
&
ではなく&&
としているのは、&
という別の意味を持つ記号があるためです。それと区別するために、条件を組み合わせるときの記号は&&
というように&
を2個続けて書くようになっています。(|
も同様です)
また、プログラミングの世界では、例えば「かつ」は「論理積」または「AND」と呼んでいます。
このような条件を組み合わせる記号のことを「論理演算子」と呼んでいます。
なんだか難しい呼び方でいろいろ出てきましたが、頭の中では「スケッチで条件の組み合わせ書く場合、『かつ』は&&
」などと覚えておけば十分です。
今回のスケッチではzenkai == 1 かつ konkai == 0
という条件を書きたいので、「かつ」の記号&&
を使用して次のように書けばOKです。(9行目)
void loop() {
// 前回と今回のスイッチ状態を記録する変数
uint8_t zenkai, konkai;
// 今回のスイッチ状態を調べて、変数「konkai」に代入する
konkai = digitalRead(A5);
if( zenkai == 1 && konkai == 0 ) {
// スイッチが押されたことを検知したので、LEDを50ms点灯する
digitalWrite(12, HIGH);
delay(50);
digitalWrite(12, LOW);
}
// 今回のスイッチ状態を、次回の判断のとき用に、前回のスイッチ状態に保存しておく
zenkai = konkai;
}
これでスケッチが完成しました!
動作確認
今回作成したプログラムをまとめます。#defineを使用してなるべくわかりやすく書き直してみました。
/*
* スイッチ制御プログラム改良版
* スイッチを押すとピカッとLEDを光らせる
*/
// 青色LEDのピン接続番号
#define LED_BLUE 12
// 左側スイッチのピン接続番号
#define SWITCH_HIDARI A5
// スイッチの状態
#define OFF 1
#define ON 0
// 点灯時間(単位:ms)
#define TENTOU_JIKAN 50
void setup() {
pinMode(LED_BLUE, OUTPUT); // LEDのピンを出力に設定
pinMode(SWITCH_HIDARI, INPUT_PULLUP); // スイッチのピンを入力(プルアップ)に設定
digitalWrite(LED_BLUE, LOW); // 最初はLEDをOFFに設定しておく
}
void loop() {
uint8_t zenkai, konkai; // スイッチ状態を記録する変数
// 今回のスイッチ状態を読み取る
konkai = digitalRead(SWITCH_HIDARI);
// スイッチ状態が、前回OFF、今回ONの時、スイッチが押されたと判断する
if( (zenkai == OFF) && (konkai == ON) ) {
digitalWrite(LED_BLUE, HIGH); // LEDを点灯
delay(TENTOU_JIKAN); // 一定時間待つ
digitalWrite(LED_BLUE, LOW); // LEDを消す
}
// 今回の値を前回の値として保存
zenkai = konkai;
}
実際にスケッチを動作させてみると、、、なんだかうまく動きません!!
ここまで一生懸命考えて作ったのに!!キーッ!!ってなって、落ち込んでしまいますね…
スケッチを作ってもうまく動かないことはよくあります。
このようなときは「なんでうまく動かないんだろう…」と落ち込んで後ろ向きに考えるより、「新しいことにチャレンジする機会ができた!」と思って前向きに明るく行きましょう!
ということで、次回の記事ではうまく動かない原因を見つけて、新しいことを習得します。
ミニチャレンジ課題
課題
条件の組み合わせは電子工作のプログラミングでもよく使います。
例えば室内の照明を自動制御するシステムを作るときに「外の明るさが〇〇ルクス以下、かつ人感センサで人がいることを検知した場合に照明をつける」など、「かつ」や「または」という条件はよく使います。
そこで、論理演算子の使い方に慣れるため、ミニチャレンジ課題に挑戦してみましょう。
「屋外の明るさが500ルクス以下、かつ人感センサが人を検知したときに条件が成立する」ようにif
の条件を作成してみてください。この条件が成立したときに室内の照明を点灯するようにリモコンを操作しようと思います。
屋外の明るさはuint16_t akarusa;
で変数宣言してあります。この変数には明るさセンサで測定した明るさの数値がルクスで代入されています。
人感センサの状態はuint8_t jinkan;
で変数宣言してあります。この変数には、人を検知した場合に1、人を検知していない場合に0が代入されます。
屋外の気温を測定して、「気温が23度〜27度以外のときに条件が成立する」ようにif
をの条件を作成してみてください。外気温が23度〜27度以外の場合、寒いか暑いかのどちらかなので、この条件が成立するときは窓を自動的に閉めるシステムを作ろうと思います。
外気温はint8_t kion;
で変数宣言してあり、現在の気温はこの変数に代入されます。
解答例
いくつか書き方がありますので、次の例を参考にしてみてください。
ミニチャレンジ課題1
変数akarusa
の値が500以下、かつ変数jinkan
の値が1であれば条件整理です。
「変数akarusa
の値が500以下」はスケッチでは次のように書けます。
akarusa <= 500
「変数jinkan
の値が1」は次のように書けます。
jinkan == 1
これらの条件を「かつ」の記号で組み合わせれば良いので、ifは次のように書けばOKです。
if( akarusa <= 500 && jinkan == 1 )
ただ、このように書くと条件の区切りがわかりづらいので、次のように条件を括弧で囲むとわかりやすくなるかな、と思います。
if( (akarusa <= 500) && (jinkan == 1) )
ところで、数値の1
は「真」(成立)を意味しますので、次のように簡略化して書くこともできます。
if( akarusa <= 500 && jinkan )
ただ、これはちょっと読みづらい気もしますね。
ミニチャレンジ課題2
条件の「『23度〜27度』ではない」というのは、「かつ」や「または」を使って書き直すと、「『23度以上、かつ27度以下』ではない」と意味になります。
また、「〜ではない」は!
です。
「23度以上、かつ27度以下」という条件を!
を使って「ではない」にします。
この考え方で次のように作成してみました。
if( !( kion <= 23 && kion >= 27 ) )
また、条件を「23度未満、または27度より高い」と考えることもできます。
この場合は以下のような書き方ができます。
if( kion <23 || kion > 27 )
複数の条件の「かつ」「または」の書き方はかなりややこしいですよね。
でも、電子工作でセンサを組み合わせて特定の条件で何かを制御する、ということは多いので、ぜひ今回の記事内容や課題を通して慣れてみてください。
更新履歴
日付 | 内容 |
---|---|
2021.8.29 | 新規投稿 |
2025.2.7 | 説明内容一部削除(簡略化のため) |