センサーがないのに手をかざすとLピカ!
不思議の回路を作ってみよう
ボタンを押してLEDを点灯させようとした次の回路で、ちょっと不思議な現象を見ることができます。
上の回路では、Arduinoを使って次のことをさせたいのですが、どうなると思いますか?
- 人間がボタンを押す
- Arduinoはボタンが押されたことを検知する
- ArduinoがLEDを点灯させる
準備する部品と接続方法は以下の通りです。
品名 | 備考 |
---|---|
Arduino | 本稿では以下2機種で確認 ①UNO R4 Minima(純正品) ②ELEGOO製 UNO R3互換品 |
LED | 砲弾型 直径5mm 赤色 |
ボタンスイッチ | 上図のボタンを押すと右と左が接続される |
抵抗 | 220Ω |
コードの色 /素子 | 接続先1 | 接続先2 |
---|---|---|
赤 | 5V端子 | ボタンスイッチ左 |
青 | ボタンスイッチ右 | 3番ピン |
緑 | 13番ピン | 抵抗(220Ω) 右 |
LED | アノード(長いほう)と抵抗(220Ω)の左側 | カソード(短いほう)とコードの黒 |
黒 | GND |
回路図は下の通りです。
回路が組めたら、Arduino IDEで次のスケッチを入力し、Arduinoに書き込みます。これは、ボタンが押されたらLEDを点灯し、ボタンを離したら消灯させるスケッチです。
#define SW 3 // ボタン #define LED 13 // LED void setup() { // put your setup code here, to run once: pinMode(SW,INPUT); // ボタンは入力 pinMode(LED,OUTPUT); // LEDは出力 } void loop() { // put your main code here, to run repeatedly: if( digitalRead(SW)==HIGH ) // ボタンが押されたら digitalWrite(LED,HIGH); // LEDを点灯する else // ボタンを離したら digitalWrite(LED,LOW); // LEDを消灯する }
Arduinoは3番ピンからの入力を口を開けて待っています。スケッチの12行目を見てください。SW(3番ピン)がHIGHか(あるいはLOWか)をチェックしています。これはブレッドボードの図で、青い線がつながったピンに電圧がかかっているかどうかで判定されます。
ハンドパワー?触れずにLEDが点灯!?
ボタンを押さないでください。
スケッチをArduinoに書き込んだあと、回路の近くに手をかざすように近づけると、ボタンを押していないにもかかわらず、LEDが点灯することがあります。手を引っ込めるとLEDは消灯します。
この現象は、必ず起きるとは限りませんが、かなり高確率で見ることができる現象です。
もしかすると、手を近づけなくても、身体と回路の距離が近いとLEDはぼんやり点いているかもしれません。
ボタンを押すと、LEDはより明るく点灯するでしょう。しかしボタンを押してはいけません(理由は後述)。
次にスイッチにつながっている青い線、赤い線をブレッドボードから外してみます。同様にLEDが点灯したのではないでしょうか?
どうでしょう?皆さんはLEDの不思議な点灯を見ることができましたか?
実はこの現象はある意味、回路が不完全なことによって起きています。
前掲の図で、本来はボタンが押されることにより、赤い線からボタンを経由して青い線を通って、3番ピンに電圧がかかり、HIGHになります。そして次にスケッチの処理に従って、13番ピンがHIGHになるのでLEDが点灯します。
注目すべきはボタンが押されていないときです。3番ピンにかかる電圧(正確には電位差)でボタンが押されたかどうかを判断するのですが、押されていないと3番ピンはどこにも つながっていない状態です。Arduinoは懸命に入力がHIGHかLOWかを検知しようとしているのですが、回路が宙に浮いて(フロート)しまっているので「不定」になるのです。このように宙に浮いたピンをdigitalRead()で読み取ると、HIGHとLOWがランダムに発生することがあります。手を近づけることでわずかな電位の変化が生じ、この現象が発生すると考えられます。LEDの明るさが少し鈍いことが多いのは、HIGHとLOWがランダムに発生しているからです。この時3番ピンの電圧をテスターで計測すると本来の電圧(4.5V程度)より低く、2V前後でした。これは非常に高速にHIGHとLOWの信号が出力されているため、疑似的なPWM出力が発生していると考えてよいのでしょうか?筆者の知識では断定できません。
超能力現象を回避するには
このハンドパワー現象を回避するには、3番ピンをGND(グランド)に接地します。回路は下の通りです。いわゆるプルダウンやプルアップと呼ばれるもので、この場合はプルダウンです。10KΩの抵抗を加えている理由は、スイッチを押した時に5Vが直接GNDにかかると、ショートによってArduinoを壊してしまう可能性があるためです。
追加した回路(上図赤枠)は次の通りです。
品名 | 備考 |
---|---|
抵抗 | 10KΩ |
コードの色 /素子 | 接続先1 | 接続先2 |
---|---|---|
抵抗 (10KΩ) | ボタンスイッチ右とコードの青 | コード黒 |
黒 | 抵抗(10KΩ) | GND |
これで手をかざしても、LEDは勝手につかなくなったでしょう。
今度はスイッチを押しても大丈夫です。
押したときだけ、LEDが点灯するようになりました。
Arduino UNO R4 Minimaでは
Arduino UNO R4 Minimaでも当然、同様の結果が得られることが確認できました。
Arduinoの隠し機能?
上記で述べた回路は「プルダウン」と呼ばれるセオリー通りの方法です。一方「プルアップ」も存在し、むしろこちらのほうが多く使用されているようです。そして実はArduino自体に「プルアップ」の機能が実装されています。これは、Arduino関連書籍ではあまり触れられていません。
まずはArduinoの機能を使用せず、普通にプルアップを組み込むと下の図になります。
Arduinoの5V電源から抵抗(10KΩ)を介してボタンとデジタル入力ピンを接続します。デジタル入力(3番)ピンは通常HIGHの状態です。ボタンを押すとGNDにつながるのでLOWになります。
これを動作させるスケッチは以下です。
#define SW 3 // ボタン #define LED 13 // LED void setup() { // put your setup code here, to run once: pinMode(SW,INPUT); // ボタンは入力 pinMode(LED,OUTPUT); // LEDは出力 } void loop() { // put your main code here, to run repeatedly: if( digitalRead(SW)==HIGH ) // ボタンを離したら digitalWrite(LED,LOW); // LEDを消灯する else // ボタンが押されたら digitalWrite(LED,HIGH); // LEDを点灯する }
前掲のプルダウンの時のスケッチとの違いは、loop()の中のdigitalWrite()の第2引数、HIGHとLOWが逆になっているだけです。
Arduinoのプルアップ機能とは
いよいよ、Arduinoのプルアップ機能です。回路は以下の通りで、5V電源と抵抗は使用しません。このシンプルな回路でプルアップが使えます。
スケッチは以下の通りです。このスケッチをArduinoに書き込むと、「ハンドパワー」現象は起きず、ボタンを押すとLEDが点灯します。
#define SW 3 // ボタン #define LED 13 // LED void setup() { // put your setup code here, to run once: pinMode(SW,INPUT_PULLUP); // ボタンは入力 pinMode(LED,OUTPUT); // LEDは出力 } void loop() { // put your main code here, to run repeatedly: if( digitalRead(SW)==HIGH ) // ボタンが押されたら digitalWrite(LED,LOW); // LEDを点灯する else // ボタンを離したら digitalWrite(LED,HIGH); // LEDを消灯する }
注目していただきたいのはスケッチの6行目です。pinMode()関数の引数に”INPUT_PULLUP”を指定しています。これにより、Arduinoの内蔵抵抗(と電源)でプルアップが行われます。
ちなみにプルダウン(”INPUT_PULLDOWN”)のオプション機能は無さそうです。プルアップのほうが多用されるからでしょうか?
さいごに
今回は、電子工作を始めると「アレ?」と思う不思議現象にスポットを当ててみました。回路のGNDへの結線を間違えたときなどにも、このようなことが発生することがあります。皆さんの参考になれば幸いです。