概要
前回はLEDを使ってLチカを行ってみました。今回はボタンを使ってLEDを制御してみたいと思おいます。
ボタン
ボタンはボードの左下にあります。D6に接続されているようですね。
スケッチ例
const int buttonPin = 6; // ボタン(D6) const int ledPin = 4; // LED(D4) void setup() { // ボタンを入力に設定 pinMode(buttonPin, INPUT); // LEDを出力に設定 pinMode(ledPin, OUTPUT); } void loop() { // ボタンの状態を取得 int buttonState = digitalRead(buttonPin); // ボタンの状態に応じてLEDを制御 if (buttonState == HIGH) { // ボタンがHIGHのときLEDを点灯 digitalWrite(ledPin, HIGH); } else { // ボタンがLOWのときLEDを点灯 digitalWrite(ledPin, LOW); } }
まずは動かしてみましょう。動きがないように思えますが、ボタンを押すとLEDが光るスケッチになります。
では、個別のプログラムを解析していきたいと思います。
void setup() { // ボタンを入力に設定 pinMode(buttonPin, INPUT); // LEDを出力に設定 pinMode(ledPin, OUTPUT); }
pinMode()関数で、ピンの状態を設定します。ボタンを入力、LEDを出力に設定しています。入力は設定し忘れても取得可能ですが、出力は設定を忘れるとdigitalWrite()関数が反映されませんので注意してください。
// ボタンの状態を取得 int buttonState = digitalRead(buttonPin);
digitalRead()でピンの状態を取得できます。取得できる値はLOWかHIGHになります。
// ボタンの状態に応じてLEDを制御 if (buttonState == HIGH) { // ボタンがHIGHのときLEDを点灯 digitalWrite(ledPin, HIGH); } else { // ボタンがLOWのときLEDを点灯 digitalWrite(ledPin, LOW); }
ボタンの状態がHIGHの場合、LEDを出力のHIGHに設定します。ボタンの状態がLOWの場合には逆に出力しないLOWに設定します。
単純なスケッチですが、基本的な構造になっています。動きから考えるとボタンを押すとLEDが点灯しているので、ボタンを押すと入力値はHIGHになっているはずです。
ボタンは押すとHIGHになるものと、LOWになるものの2種類あるので注意して利用してください。HIGHになるほうが直感的ですが、実際にはLOWになるボタンの方が種類は多いようです。
余談・pinMode()関数
pinMode()関数は非常に重要な関数です。プログラム的には問題がなさそうに見えますが実際に出力がされていない状態などになるので、必ず最初に初期化をする必要があります。
#define INPUT 0x0 #define OUTPUT 0x1 #define INPUT_PULLUP 0x2
上記が宣言なのですが、これまで紹介したINPUTとOUTPUT以外にINPUT_PULLUPがあります。このプルアップというのがかなり重要な役割になるのですが、なかなか理解しにくいのです。
上記はD6とGNDを接続している図です。この場合の入力値はLOWに固定されています。
こちらはD6と5Vを直結しています。この場合入力はHIGHに固定されます。
さて、これが問題なのですが、D6がどこにも接続されていない場合には? これはどんな結果になるのかわかりません。D6の端子に静電気のような電荷が溜まっており、その電圧で入力結果が決まってしまいます。
デジタル入力の場合には、0Vから5Vまでの入力をLOWとHIGHに判定しています。概ね2.5V未満がLOWになり、2.5V以上がHIGHになります。実際には2.5V前後だとどちらに判定されるか不安定になるのでLOWは0Vから1.25Vぐらいまで、HIGHは3.75Vから5Vぐらいまでの入力で使った方が安定すると思います。基本的には基準値とそれほど変わらない電圧を入力してあげてください。
このように、何も接続されていない端子はフローティングと呼ばれ、浮いている状態と表現されます。どこにも接続されていないので、入力値を信用することができません。
さて、D6にスイッチを接続して、押すと5Vが流れる回路にしてみます。
回路図のほうがわかりやすいですが、スイッチが押されると通電されてD6と5Vが接続されます。この場合ボタンを押すとHIGHになります。ただし、ボタンを押していない場合にはD6はどこにも接続されていない状態になります。この状態では入力値を信頼することができません。これでは入力には使えませんね。そこでプルアップとプルダウンという回路が必要になります。
上記がプルダウン回路です。ちょっと接続図だとわかりにくいですね。
回路図です。D6から10kΩの抵抗を経由してGNDに接続されています。これの意味としてはボタンを押していない場合にはD6は10kΩの抵抗を経由してGNDに接続されているので入力値はLOWになります。ボタンを押すと5VからD6と、10kΩの抵抗を経由してGNDに接続に接続されます。この場合はD6の入力値はHIGHになります。ポイントとなるのは抵抗の存在です。10kΩと大きめの抵抗がついているので少ない量ですが電流が流れますが、入力の邪魔にはなりません。この抵抗値が小さすぎるとたくさん電流が流れちゃうので入力電圧が下がったり、流れすぎてボードが壊れたりしてしまいます。
上記のようにプルダウン回路を組み込むことで、押していない場合には安定してLOWになり、押した場合には無駄な電流は流れますがHIGHになる回路となります。
上記は逆に抵抗を経由して5Vに接続されているプルアップ回路です。
回路図です。ボタンを押していない場合には、5Vから10kΩの抵抗を経由してD6に接続されています。つまり入力値はHIGHになります。ボタンを押した場合にはD6はGNDへと、5Vから10kΩの抵抗を経由した2本の線があります。この場合5Vからの電流はGNDに流れてしまいますのでD6には流れません。そのため入力はLOWになります。
プルアップ回路の場合には、ボタンを押していないと安定してHIGH、ボタンを押すと無駄な電流が5VからGNDに流れますがLOWになります。
このようにボタンはプルダウンかプルアップ回路がないと、正しく回路を組むことができません。話は戻りましてpinMode()でINPUT_PULLUPを指定した場合ですが、Arduino UNOの内部でプルアップ回路に接続されます。
上記のように内部で自動的にプルアップ回路に接続されますので、スイッチは単純にGNDに接続することで正常な回路として利用できます。配線がかなりシンプルになりますね。
さて、今回のボタンは押すとHIGHになるボタンですので、プルダウン回路のはずです。Arduino UNOの内部にプルダウン回路はありませんので、外部回路で実現しているはずです。
余談・ボタンの回路
上記のページに回路図があります。Grove-Button Eagle Filesという添付ファイルの中にPDFと実際の回路図などが入っています。
上記が回路図のようです。ボタンはVCC(5V)に接続されており、反対側は10kΩ経由でGNDに接続と、D1端子に接続されています。抵抗経由にGNDに接続されているのでプルダウン回路ですね。
Arduino UNO内蔵のプルアップ回路を使うことで、Groveボタンモジュール側ではシンプルな回路にすることができるはずですが、押したらHIGHになるわかりやすいボタンにするために内部でプルダウン回路を入れていると思われます。
また、ボードによってプルアップ回路を内蔵していない場合があるので、この手の汎用モジュールはプルアップかプルダウンされていることが多いです。ちなみにESP32だとプルダウン回路も内蔵しています。
まとめ
余談がどんどん長くなっていますが、本当に知ってほしいのは余談の部分になります。公式マニュアルなどではサラリとスケッチを動かして終わりなのですが、余談の部分を理解していないとなかなか理解が進まないと思います。
わかりにくいところがあったら、がんがんコメント欄で質問していただきたいと思います。
コメント