LEDを光センサーとして使いたくて発電方式で試してみた。発電量が微弱すぎて感度/ノイズ/安定度などの問題がなかなか解決できず悩んでいたところ次のサイトが大変参考になった。参考元のサイトの記事はぜひ一度読んでみることをお勧めしたい。
この方法はLEDの寄生容量に蓄えられた電荷の自己放電時間がLEDへの入射光量(発電量)に比例することを応用したものだ。
この方法ならVDDからGNDまで確実に電圧が変化するため入射光量範囲も広く安定度も高そうだ。他の方法がADC/オペアンプ/コンパレータなどを必要とするのに対しGPIO1本だけで済んでしまう点が素晴らしい。さらにGPIO2本仕様にすれば点灯も行えるようになる...これ考えた人、天才!
雨模様で薄暗い室内の中で試した結果は次の通り。中華製の超安いLED(3mm)でも感度良好だ!素晴らしい!
回路は次の3種類が考えられたので全て試してみた。
(A)(B)(C)の順に(A)が一番感度が良くて、(B)は若干落ちるかなという程度、(C)は室内光程度の光量変化ではほとんど反応せず。GPIOの入力回路の特性による影響なのかな?ちなみに(B)は点灯も可能な回路であるが回路図に保護抵抗を入れるの忘れてた...試す人は保護抵抗を忘れないように。(-_-;)
せっかくなのでライブラリを作って見た。簡単なものなので説明する必要もないとは思うが、接続したLEDのCATHODEピンとANODEピンをテンプレート引数に指定することにより上記回路図の3種類を試すことができる。
【サンプル・スケッチ】
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 |
// // Arduino pro micro (ATmega32u4) // #include "ledsensor.h" #define CATHODE A3 #define ANODE 0xFF // A2 LEDSensor<CATHODE, ANODE> led; void setup(void) { Serial.begin(115200); } void loop(void) { static uint32_t t = 0; if (millis() - t >= 1000) { t += 1000; Serial.println(led.darkness(), DEC); } led.handle(); } |
【ライブラリ】
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 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
/* ledsensor.h - LED Ambiant Light Sensor Library Copyright (c) 2021 Sasapea's Lab. All right reserved. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef __LEDSENSOR_H #define __LEDSENSOR_H #include <stdint.h> #include <stdbool.h> #if ARDUINO #include "Arduino.h" #else #include "ioport.h" #define pinMode IOPORT::pinMode #define digitalWrite IOPORT::digitalWrite #define digitalRead IOPORT::digitalRead #endif template<uint8_t CATHODE, uint8_t ANODE = 0xFF> class LEDSensor { private: uint32_t _darkness; uint32_t _start; bool _measure; public: LEDSensor(void) : _darkness(-1) { light(false); } virtual ~LEDSensor(void) { } void light(bool on) { if (CATHODE != 0xFF) { digitalWrite(CATHODE, on ? LOW : HIGH); pinMode(CATHODE, OUTPUT); } if (ANODE != 0xFF) { digitalWrite(ANODE, on ? HIGH : LOW); pinMode(ANODE, OUTPUT); } if (on) _measure = false; else if (CATHODE != 0xFF) { _measure = true; _start = micros(); pinMode(CATHODE, INPUT); digitalWrite(CATHODE, LOW); } else if (ANODE != 0xFF) { _measure = true; _start = micros(); pinMode(ANODE, INPUT); } } uint32_t darkness(void) { return _darkness; } void handle(void) { if (_measure) { if (CATHODE != 0xFF) { if (digitalRead(CATHODE) == LOW) { _darkness = micros() - _start; light(false); } } else if (ANODE != 0xFF) { if (digitalRead(ANODE) == HIGH) { _darkness = micros() - _start; light(false); } } } } }; #endif |