先日は、基本的な半導体の構造が同じなことを利用して、LEDを太陽電池として利用する実験をしてみました。
今回は、LEDを、光センサとしても、LEDとして光らせることもできる「光る光センサ」の実験をしてみたいと思います。
発電を利用した光センサ
LEDに光を当てると、発電することがわかったので、上記のような光センサとしての回路を試してみました。
回路図左側のLEDに光を当てると、LEDが発電して電圧が上がり、その電圧がNOTゲートのスレッショルド電圧を超えると、NOTゲートが反転します。もう一つNOTゲートがあるのでさらに反転します。そのため結果的には、左側のLEDに光が当たると、右側のLEDが光るという回路になっています。
今回は、光源のLEDは白色LEDとして、受光側のLEDには白色LEDに反応しやすかった黄色のLEDにしました。NOTゲートには74HC04を使っています。
実験した結果、受光側のLEDの発電電圧が低く、なかなかNOTゲートのスレッショルドを超える電圧になりません。光源のLEDと受光のLEDをピッタリとくっつけてやっと反応する程度です。
光センサとして利用するには、かなり感度が低い結果となりました。
LEDを逆バイアスにしてみる
今度はLEDを逆バイアスにして、センサとして利用できるか実験してみます。逆バイアスとは、上記の回路の左側のLEDのように、LEDのマイナス極(カソード)を電源に接続して、プラス極(アノード)から信号を得ます。
通常ですと、LEDのマイナス極(カソード)の電圧が高く、プラス極(アノード)の電圧が低いため、ダイオードの特性によって電流は流れず、アノードには電気が流れてきません。この状態ではもちろん右側のLEDは光りません。
この回路で、左側の受光側のLEDに光を当てると...
青いLEDが光りました。受光側のLEDが光センサとして機能しています。発電の回路よりも、逆バイアスの回路の方が、光に対して感度が良い感じです。
LEDに光が当たることで、ダイオードとして特性が弱まることで、逆バイアスの電流が若干流れ出してくるようです。
NOTゲートの入力には、10MΩの抵抗でプルダウンしました。かなりの高抵抗ですが、ないと安定して動作しません。というのも、光に反応した後、光源を離しても反応した状態が続いてしまいます。電気がたまってしまうようなので、その電気を逃す抵抗が必要でした。ただし、抵抗値が2MΩより低いと光センサとして動作しなくなってしまいます。そこで、10MΩとしました。
LEDを「光る光センサ」にするには
LEDに逆バイアスをかけることで、光センサとして利用できることがわかりました。続いて、光ることもできるし、光センサとしても利用できる回路を考えます。
上記がその回路になります。ロジックICが3Vなので、マイコンにはarduinoではなく、3V程度で動作するLPC1114を利用しました。LPC1114はmbedを利用して簡単にプログラミングができます。
光センサとして利用する時
光センサとして利用する場合、マイコンのledKのピンをHに、ledAのピンをLにします。こうすることでLEDが逆バイアスの状態になり、LEDが光センサとして機能します。
NOTゲートの結果をマイコンのledSensorピンに入力して、Lだったら光に反応していると判断し、Hだったら光に反応していないと判断します。(NOTゲートが1つだけなので、先ほどの実験と結果が反転しています)
LEDを光らせる時
LEDを光らせる場合は、ledAのピンをHの状態にします。この状態で、ledKのピンをLにするとLEDに電流が流れLEDが点灯します。ledKピンをHにすると電流が流れないのでLEDが消灯します。
プログラムを作って実験してみる
仕組みが決まったので、プログラムにしてみます。0.5秒ごとにONとOFFを繰り返すLED(黄色)を、0.1秒ごとに一瞬だけ光センサとして動作させて、測定した結果を別のLED(青)へ出力してみます。
#include "mbed.h" DigitalOut ledK(dp13); DigitalOut ledA(dp14); DigitalIn ledSensor(dp1); DigitalOut led(dp15); bool lightDetect(); int main() { while(1) { for( int i=0 ; i<5 ; i ++ ) { ledA = 1; //光センサ点灯 ledK = 0; wait(0.1); led = lightDetect(); //センサ状態をLEDへ出力 } for( int i=0 ; i<5 ; i ++ ) { ledA = 1; //光センサ消灯 ledK = 1; wait(0.1); led = lightDetect(); //センサ状態をLEDへ出力 } } } //光センサとして光を検知する bool lightDetect() { ledA = 0; //光センサのモードにする ledK = 1; wait(0.001); //1ms光センサのモード bool sense = ledSensor; //センサの状態を読み込む ledA = 1; //発光モードにする return sense; }
こちらが、プログラムです。dp13,dp14につながったLEDが光センサとしても利用するLED。dp15につながったLEDが出力のLEDです。
実際に動作させてみましょう。
左側の黄色の点滅しているLEDが、光センサにもなるLEDです。光源の白色LEDを近づけると、反応して右側の青いLEDが点灯していますね。
LEDが、光センサとしても、発光デバイスとしても利用できるようになりました。「光る光センサ」ができました。
ちなみに、NOTゲートを省略してLPC1114の入力ピンに光センサのLEDを直接つないだところ、LPC1114の入力インピーダンスが低いため、光センサとして動作しませんでした。
たくさんのLEDを「光る光センサ」にする
完成した「光る光センサ」にはLED1つあたり3つのポートが必要です。たくさんの「光る光センサ」をマイコンで利用しようとすると、ポートがすぐに不足してしまいます。
そこで、なるべく少ないポート数で、「光る光センサ」をたくさん利用するための回路を考えました。
光センサとして利用する時
光センサとして利用する場合には、これまで同様ledAのピンをLにします。そして調べたいLEDのledKのピンだけをHにします。これで特定のLEDだけ逆バイアスになり、光センサになります。
例えば、上記の図のようにledK1だけをHにすると、D1のLEDが光センサとして機能するので、ledSensorの出力を読み取ってD1のLEDが光に反応しているかを判断します。
次にledK2だけをHにして、ledSensorの出力を読み取ります。次にledK3だけHにして...と、LEDの数だけスキャンしていきます。
上記の図では、これまで10MΩだった抵抗のところがトランジスタに変更になり、そのトランジスタを制御する「flash」という新しいピンが増えています。これは、スキャンの方式に変更したところ、10MΩの抵抗では光に反応した時の電気の放電が間に合わず、1カ所のLEDが反応すると電気が抜けるのが遅いために、他のLEDも反応したかのような現象が起きてしまいました。そこで、強制放電させる回路にしました。
具体的には、
- ledK1をH
- ledSensorの結果を読み込み
- ledK1をL
- flashを一瞬H
とします。これを全てのLED ledK1〜ledKnまでスキャンしていきます。
LEDを光らせる場合
LEDを光らせる場合には、ledAをHにします。そして、光らせたいLEDのみLにして、光らせたくないLEDはHにします。こうすることで、LにしたLEDにのみ電流が流れLEDが光ります。上記の例の場合、ledK1のみLなので、D1のLEDだけが光ります。
実際にやってみた
「光る光センサ」8個にしてみました。ledK1からledK8までの8本と、ledA、ledSensor、flashの3本、合計11本のポート数で実現できます。
プログラムはこうなりました。
#include "mbed.h" DigitalOut ledK[8] = { dp1, dp2, dp4, dp6, dp9, dp10, dp13, dp14}; DigitalOut ledA(dp11); DigitalIn ledSensor(dp15); bool sensorArray[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; bool ledArray[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; DigitalOut led(dp17); DigitalOut flash(dp5); void lightDetect(); int main() { for( int i=0 ; i<8 ; i++ ) ledK[i] = 1; flash = 1; while(1) { lightDetect(); //センサ状態を取得 ledA = 0; //光センサ点灯 for( int i=0 ; i< 8 ; i++ ) { if( sensorArray[i] == 1 ) ledArray[i] = 1; if( ledArray[i] == 0 ) ledK[i] = 1; else ledK[i] = 0; } wait(0.01); } } //光センサとして光を検知する void lightDetect() { ledA = 1; //光センサのモードにする for( int j=0 ; j<8 ; j++ ) //全てのセンサをOFFにする { ledK[j] = 0; sensorArray[j] = 0; } for( int i=0 ; i< 8 ; i++ ) { flash = 0; wait(0.0001); flash = 1; ledK[i] = 1; //特定のセンサのみONにする wait(0.0001); bool res = ledSensor; //センサの状態を読み込む if( res == 0 ) sensorArray[i] = 1; else sensorArray[i] = 0; if( i== 3 ) led = sensorArray[i]; //wait(3); //1ms光センサのモード ledK[i] = 0; //特定のセンサをOFFにする } return; }
実際に動作させるとこうなります。
光源の光に反応して、「光る光センサ」が点灯していく様子がわかりますね。
LEDを使った「光る光センサ」ができたので、これでちょっと遊んでみたいと思います。
2020.8.31 追加 つづきはこちら
追加終わり
コメント