光の強さで抵抗が変化する CDS光センサーを利用し、光量に従い発光量が変化する(調光)するシステムを作成する。
CDSはCd(カドミウム)とS(硫黄)を含む化合物の抵抗が光の強さで変化することを利用して作成されたセンサーです。早い変化は検出できませんが、安い価格で入手できます。
CDS素子の抵抗の変化する量は大きさで変化します。ここでは、数十kから数kΩまで変化する比較的小型の素子を利用します。黄金色の部分がCDSです。
回路テスターを利用して、抵抗値を測定してください。テスターにケーブルを接続し両端をCDSの端子に接続します。テスターのロータリスイッチを回転して抵抗レンジにすると、抵抗値を読み取ることができます。CDSにあたる光の強さを変化させ、抵抗値が変化することを確認してください。光を完全にさえぎったときの抵抗値と開放にしたときの(室内の明るさ)抵抗値を記録してください。
下の回路を組みます。丸で囲まれた抵抗がCDSです。電圧5Vを加え、光を完全にさえぎったときの電圧と開放にしたときの(室内の明るさ)電圧を記録します。電圧は、回路テスターのマイナス側を回路のグランド、プラス側を回路の出力(二つの抵抗の間)に接続し、ロータリスイッチを回転して直流電圧のレンジにして測定します。
先の実験と結果が一致するか、オームの法則チェックしてください。CDSの抵抗をr、CDSの上の抵抗をRとすると、出力電圧は、5*(r/(R+r))
となります。このとき、電源の電圧をテスターで測定し 性格に5Vにあわせて下さい。
PICは16レベルの電圧生成機能があります。C言語で以下の関数を実行すると、内部で
VCC*val /24 の電圧を生成することができます。ここで、VCCはPICへの電源電圧です。val
は変数で、0から15の値を設定します。
setup_vref(VREF_HIGH | val );
PICは、入力電圧を参照電圧を比較して、どちらが大きいかを判断する機能(アナログ比較)があります。この比較回路はアナログ電圧をディジタル値に変換する回路(AD変換)より簡単に作成できます。
16F648Aでは、この電圧比較機能があります。まず、
setup_comparator(A0_VR_A1_VR);
で、比較機能を設定します。これで、A0端子とA1端子を内部で生成した参照電圧と比較します、結果は、Cプログラムで、C1OUTとC2OUTとして利用できます。A0、A1
側の電圧が高いと、C1OUT、C2OUT は0 になります。
cds素子と抵抗を接続したセンサー回路の出力と参照電圧を比較することで、光が一定値以下になったことを判断できます。
なお、アナログ比較電圧は A0 端子を利用します。これは、Aポートを利用する場合の第
0 bit の端子ですが、設定用のレジスタにモードを設定することで、アナログ比較の端子として利用できるようになります。この場合、A1
端子もアナログ入力なり、ポートとしては利用できません。
16F648Aは3種のカウンター回路を内蔵しており、外部の信号の状態(0と1)変化の数を計測したり内部のクロックを計数して、状態が変化するまでの時間を計測できます。
また、タイマー2では、指定した幅のパルスを発生することができます。タイマー2の周期は以下の関数で設定します。
setup_timer_2(T2_DIV_BY_1,prd,1)
最初の、T2_DIV_BY_1 は、内部クロックをあらかじめ分周する割合を設定します。T2_DIV_BY_1
の場合は分周しません。T2_DIV_BY_2 では 1/2 に、T2_DIV_BY_4 では1/4 に分周します。内部発振回路の周波数は4Mhzですが、この1/4の周波数がタイマーに接続する内部クロックになります。したがって、したがって、タイマーに加わるクロックの周期は約1マイクロ秒になります。
次の変数 prd は発生するパルスの周期を決めます。内部クロックによる周期をTontとすると、周期は
(prd+1)*4*Tint
マイクロ秒 になります。PWMの周期用のカウンタは設定する値は8bitですが、内部で2bit追加されるため計10bitの周期になります。(prd+1)*4*Tint
の *4 はこの2bitに追加によります。
タイマー2では発生する周期のパルス幅だけでなく、そのパルス幅を指定することができます。まず、パルスを生成するには、以下の関数を実行します。これで、B3端子からパルスが生成されます。
setup_ccp1(CCP_PWM);
この設定をすると、B3端子は、ポートBの端子としては、利用できません。
パルス幅を指定するには以下の関数を利用します。
set_pwm1_duty(duty);
duty がパルスの幅を定めます。PWMの信号は最初 1 ですが、PWMのカウンタの値が
duty の値と等しくなると 0 になります。これでPWMのパルス幅が定まります。したがって、duty
の値は、PWMの周期 より小さな値とする必要があります。
一定周期のパルスを生成し、そのパルス幅を変えた信号を加えることで、接続した回路に加える電力を調整(制御)することができます。これを PWM(Pulse
Width Moduration)方式に呼びます。
実験回路は簡単です。光センサー回路を比較回路のA0に接続します。この値から、PWM
信号を生成します。信号はB3に出力されます。この信号でLEDを点灯します。PWMのプログラムでこのLEDの明るさは制御されます。
B0に接続したLEDは、比較回路の結果をチェックするのに利用してます。比較の値が0になると点灯するよう、プログラムします。
まず、pwmのモードと参照電圧を設定します。参照電圧の値は、cdsの特性と室内の明るさで調整する必要があります。次に、Bポートの下位4ビットを出力とし、タイマー2を pwm
モードに設定し、周期を設定します。ここでは、255ですから、パルス周期は255マイクロ秒になります。
繰り返し部で、比較回路の結果(C1OUT)を利用し、1のときは duty を800にします。この値が大きいと、周期に占めるパルス幅が多くなります。LEDはパルスが0のとき点灯しますから、dutyの値が大きいと暗くなります。dutyの値は、duty/4
が255以下とする必要があります。
C1OUTが0のとき(基準値より暗いとき)、duty を 10 と 400 にして明るさを変化させています。この時間間隔は、delay_ms(200);
で指定しています。
define VREF_HIGH 0x80 の定義は、<16f648a.h> に書かれているはずですが、欠けていますので追加しました。
#include <16f648a.h> #fuses INTRC_IO,NOWDT,NOLVP,NOMCLR//内部クロック、WDT,LVPなし #use delay(CLOCK=4000000) //クロック4MHz #define VREF_LOW 0xa0 #define VREF_HIGH 0x80 long duty; void main(){ //比較器を設定、A0と参照電圧を比較 setup_comparator(A0_VR_A1_VR); //参照電圧を設定、VCC*10/24 setup_vref(VREF_HIGH | 10); set_tris_b(0xF0); //RB3にPWM信号生成 setup_ccp1(CCP_PWM); //タイマー2の周期を設定 //内部クロック/4/64 、最後の1は割り込み間隔 setup_timer_2(T2_DIV_BY_1,255,1);//0..255 while(1){ if(C1OUT ==0 ) { //暗いとき //RB1の発光ダイオード output_bit(PIN_B0,0); //RB3をデューティ1000で点灯 duty=10; set_pwm1_duty(duty);//0..1023の範囲 delay_ms(200); //RB3をデューティ500で点灯 duty=400; set_pwm1_duty(duty); delay_ms(300); } else {//明るいとき output_bit(PIN_B0,1); duty=800; set_pwm1_duty(duty); delay_ms(200); } } }
外光の強さに対して点灯するパターンを変更して下さい。
点灯パターンを変化させる参照電圧を複数にしてください。