「CdSの抵抗値を測定してみた」ではCdSで明暗を感知してトランジスタをON/OFFすることによってLEDの点灯を制御した。
今度は、CdSで拾った明暗をON/OFFの情報としてPICに取り込んでみる。
今まで一度も真面目に考えたことが無かったが、PICのON/OFFはTTLレベルを基準にして判断してるんだって。
5V電源の場合、0.8V以下ならLow、2.0V以上ならHighと判断するのがTTLレベルというやつ。
というか、巷でそういう風に書かれているのでそうなんだろうということで、Microchipの資料で確認したわけでもなく、PICのデータシートに「TTL compatible input」って書いてあったなあという程度の認識(※1データシートを見てみた)。
PICのI/Oに直接CdSをつないでも、時々抵抗値の変わるただのプルアップかプルダウンに過ぎないので、きっとこんな感じにするんだろうと思う。
分圧に使う抵抗の値が問題になるが、こんなグラフで考えてみた。
オレンジは暗くしたときを20kΩと仮定して求めた電圧の線、青は明るいときを5kΩと仮定したもの、緑はTTLのHighの下限の2.0V、黄はLowの上限の0.8Vを表している。
横軸がCdSと直列につなぐ分圧抵抗の値。
青線が黄色より下で、オレンジが緑より上にあれば良いわけで、100~200kΩ程度でいいのかなということになる。
プログラムはこんな単純なものにした。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
void main(){ OSCCON = 0b01110010;//内部クロック8MHz ANSELA = 0b00000000;//全てデジタルI/O ANSELB = 0b00000000;//全てデジタルI/O TRISA = 0b00000000;//全て出力(RA5は入力のみ) TRISB = 0b00100000;//RB5のみ入力 APFCON0bits.SS1SEL = 1;//SS1 function is on RA5 not RB5 APFCON1bits.TXCKSEL = 0;//TX/CK function is on RB2 not RB5 while(1){ if(RB5 == 1){ RA0 = 1; }else{ RA0 = 0; } } } |
一応、プログラムのソース(main.c)。[BOOTHで販売中 PIC16F1827_CdS_LED_01]
データシートで確認が必要だったのは、
APFCON0bits.SS1SEL = 1;//SS1 function is on RA5 not RB5
APFCON1bits.TXCKSEL = 0;//TX/CK function is on RB2 not RB5
の2行で、CdSをつないだポートがデジタルI/O以外の特別な目的(SS1, TX/CK)に設定されないようにしておくためのもの。
上の行は初期値ではSS1に設定されてしまうので必須、下は初期値のままでOKだが明示的に書いておくために追加した。
こういうのっていつも悩むんだが、結局、データシートで「on RB5」を片っ端から検索して確認するのが手っ取り早いかも。
実際にそうすると、上の2つが出てくる。
他にも埋もれているのかもしれないが、とりあえずは狙い通りに動くのでよしとする。
下は、CdSにペンのキャップをかぶせて動作確認しているところ。
前半は電源が5V、後半は3.3Vで試してみた。
違いが分りにくいが、LEDの明るさが違う。
※1
データシートの表から抜粋してみた。
ポートによって違うがTTLレベルのI/Oポートとして用いる場合は上のとおり。
気になるのは3.3Vで動かす場合だが、
Low は 0.15VDD がMax.とあるので、0.495V以下
High は 0.25VDD + 0.8 がMin.とあるので、1.625V以上
ということのようだ。
ちなみに5Vの場合を同じ計算式に当てはめると、0.75V、2.05VとなってTTLレベルとほとんど同じだ。
つまり、ほぼ同じように比例配分されると考えられるので、5Vで設計して3.3Vに駆動電圧を変えても回路は同じでいけそうだ。
実際には何VでHighと判断されたりLowと判断されたりするのか調べてみた。
赤丸で示した点がLowからHigh、HighからLowになったところだが、どちらも実際には1Vあたりが閾値になっているようだ。
追記(約8秒間点灯するサンプル)
明るくなってからすぐ消灯するのではなくTimer0でカウントして、約8秒後にLEDを消灯するサンプルを書いてみた。 PIC16F1827_CdS_LED_8sec_01 (5253 ダウンロード ) Tweet