常夜灯（フルカラーLED）

概要

秋月電子で大型フルカラーLED（35mA）が安価（200円）で販売していましたので、早速購入し“常夜灯”なるものを作成してみました。 ＜仕様＞

暗くなると自動的に点灯すること。点灯する暗さのレベルが調整できること。

RGB各々のLEDは10段階で明るさが変わること。つまり1000色（10×10×10）に変化できること。

音も出せること。これは泥棒避けの為です。

動作原理

暗さの検出は、CDS（Cadmium sulphide cell）を利用しました。 今回は、暗くなると電圧が下がるようにCDSと抵抗を接続しました。 点灯する暗さのレベルは、通常はボリュームを使用して調整するのですが、少し趣向を凝らしてみました。 起動時の暗さを記憶し、それを点灯するレベルとします。 つまり、点灯してほしい暗さで起動してあげればよいことになります。 尚、起動時だけでなくSWを押すことによって、このレベル（その時の暗さ）を再設定することも出来ます。

RGB各々のLEDを10段階の明るさに切り替えることが出来るようにするために、PWM方式を採用しました。 LEDが１個だけであれば、PICが内臓しているPWMモジュールを使用するのですが、今回はRGBと3つのLEDがあるのでこのモジュールは使えません。 そこでタイマー割り込みを駆使して実現してみました。

タイマー割り込みの周期は、約0.1msec（正確には128μsec）とします。

LEDの明るさを10段階としましたので、PWMの周期は、1msec（0.1msec×10）とします。

PWMのデューティサイクル【duty cycle】は、RGBの各LED毎に変えます。（これで明るさが変わります）

各LEDのデューティサイクルは、0～9の乱数を発生させ、その値を設定します。

＜乱数で0～9を発生させる方法＞

mikroCが提供している関数（rand）は、0～32767を返します。

これを利用して、0～9を得るには次のようにします。
cnt = (((double)rand()) / 32768.0) * 10.0;

音を出すために内臓モジュールのPWMを使用しました。 音の周波数は、500Hz、1KHz、2KHz、4KHz、8KHzと変化（100msec単位）させて見ました。 これはPWMの関数が用意されているのでとても簡単に出来ます。

回路図

ソースコード

//********************************************************************** #define ledR GPIO.F0 #define ledG GPIO.F4 #define ledB GPIO.F5 #define SWITCH GPIO.F3 //********************************************************************** static unsigned char led_cnt, ledR_cnt, ledG_cnt, ledB_cnt; void interrupt(){ if (INTCON.T0IF == 1) { INTCON.T0IF = 0; GPIO.F1 = ~GPIO.F1; // if ((led_cnt <= ledR_cnt) && (ledR_cnt != 0)) ledR = 0; else ledR = 1; // if ((led_cnt <= ledG_cnt) && (ledG_cnt != 0)) ledG = 0; else ledG = 1; // if ((led_cnt <= ledB_cnt) && (ledB_cnt != 0)) ledB = 0; else ledB = 1; // if (led_cnt < 9) led_cnt++; else led_cnt = 0; } if (PIR1.TMR1IF == 1) { PIR1.TMR1IF = 0; } } //********************************************************************** void Pwm_Change_DutyEx(unsigned int duty_ratio) { CCPR1L = duty_ratio >> 2; CCP1CON.F6 = duty_ratio & 0b00000001; CCP1CON.F7 = (duty_ratio & 0b00000010) >> 1; } //********************************************************************** void buzzer() { Pwm_Init(500); Pwm_Change_DutyEx((PR2 * 4) / 2); Pwm_Start(); Delay_ms(100); Pwm_Stop(); // Pwm_Init(1000); Pwm_Change_DutyEx((PR2 * 4) / 2); Pwm_Start(); Delay_ms(100); Pwm_Stop(); // Pwm_Init(2000); Pwm_Change_DutyEx((PR2 * 4) / 2); Pwm_Start(); Delay_ms(100); Pwm_Stop(); // Pwm_Init(4000); Pwm_Change_DutyEx((PR2 * 4) / 2); Pwm_Start(); Delay_ms(100); Pwm_Stop(); // Pwm_Init(8000); Pwm_Change_DutyEx((PR2 * 4) / 2); Pwm_Start(); Delay_ms(100); Pwm_Stop(); } //********************************************************************** void main() { unsigned char cntR, cntG, cntB; unsigned int tmp, ref; OSCCON = 0b01110000; // クロックは8Mhz CMCON0 = 0b00000111; // コンパレータは使用しない。 ANSEL = 0b00000010; // AN1を使用する。 TRISIO = 0b00001010; GPIO = 0b00000000; OPTION_REG = 0b10000000; // INTCON.T0IE = 1; INTCON.T0IF = 0; OPTION_REG.T0CS = 0; OPTION_REG.PSA = 1; OPTION_REG.PS0 = 0; OPTION_REG.PS1 = 0; OPTION_REG.PS2 = 0; // led_cnt = 0; ledR_cnt = 0; ledG_cnt = 0; ledB_cnt = 0; // INTCON.PEIE = 1; // これ以降の処理で割り込みを許可する。 INTCON.GIE = 1; // これ以降の処理で割り込みを許可する。 // ref = Adc_Read(1); while (1) { if (SWITCH == 0) { ref = Adc_Read(1); } if (Adc_Read(1) > ref) { ledR_cnt = 0; ledG_cnt = 0; ledB_cnt = 0; continue; } tmp = rand(); ledR_cnt = (((double)tmp) / 32768.0) * 10.0; tmp = rand(); ledG_cnt = (((double)tmp) / 32768.0) * 10.0; tmp = rand(); ledB_cnt = (((double)tmp) / 32768.0) * 10.0; buzzer(); Delay_ms(1000); } } //**********************************************************************

動作確認

大型フルカラーLED(35mA)です。 LEDに接続している抵抗は、100Ω位が良いのですが今回は330Ωと少し高めです。

PICとCDS周りです。CDSは秋月電子で1個40円で販売しています。

LEDの光の拡散には、ピンポン玉を少し繰り抜いて利用しました。

ピンポン玉をLEDに被せたところです。

LED直では、明るすぎますね。

様々な色に変化します。見ているだけでも楽しいですね。

如何ですか？ こんな簡単な仕組みの割には、綺麗に点灯しますね。

このページは稲崎様の閉鎖したHPのコピーで、著作権は稲崎様にあります。詳細 This page is a copy of Mr. Inasaki's closed website, and the copyright is held by him.Details