巷は、クリスマスシーズンで夜になるとにぎやかにイルミネーションが輝いている。
せっかくなので、自分もフルカラーLEDでクリスマスの気分を・・・。
と、いうわけで、PIC 12F1822 と、フルカラーLED (OSTA71A1D-A) でイルミネーションを作ってみた。
とはいえ、ただ、LEDの色が変化していくだけではあるが・・・。
フルカラーLEDは、赤、緑、青と3つの色の組み合わせでカラーを表示するけど、12F1822のPWMは、残念ながら、独立しては、一つしかコントロールできない。と、いうわけで、割り込みを使って、3つの出力端子で、PWMもどきを作成してカラーのコントロールをやります。
今回、PICは、内部クロックを使って、8MHzで動かします。
ということは、1サイクル、0.125マイクロ秒なので、4サイクルで0.5マイクロ秒
タイマー0をフルにカウントすると、0.5X256=128マイクロ秒になります。
これを75回カウントすると、9.6ミリ秒 つまり、だいたい104Hzくらいの周期になります。
この104Hzの波をONとOFFにわけて、それぞれの色の強さをコントロールします。
蛍光灯が100Hzから120Hzくらいでチラチラしているのを考えると、104Hzくらいなら、なんとかごまかせるのではないかと、思ったわけであります。
75回の割り込みのうち、何回目でONとOFFを切り替えるかで光の強さが決まるので、各色、75種類の光の強さが演出できることになりますね。
あとは、RGBの光の組み合わせを考えるだけです。
今回は、まず、赤、緑、青の単色で、75階調を光らせた後、同様に各色を75階調で光らせますが、今度は、他の2色を中くらい(ステップ35)で点灯。 さらに、そのあと、擬似乱数の関数を使って、各色、ランダムに組み合わせて光らせます。 そして最後に3つの周期のサイン波を使って、3色の色を組み合わせます。
サイン波は、関数で作るとプログラムがでかくなっちゃうようなので、あらかじめ、エクセルで計算させて、データを作っておき、それを配列変数で読み込んで光らせます。
で、光らせてみたのが、これです。
PIC 12F1822でフルカラーLEDを点灯
ビデオは、1.5倍の速度にしていますので、実際は、もう少しゆったりと変化します。
ビデオでは、暗くしたときにチラチラが気になりますが、実際に現物を目で見る限りでは、わからない程度です。
気になる方は、もう少しPWMの周期を早くすれば改善されるでしょう。
LEDにかます抵抗も、色によって変えてやって、流す電流を調節すれば、色合いをコントロールできると思います。
回路図は、いたってシンプルで、PICと抵抗とLEDをつなぐだけですので、今回は、手書きです。
必要に応じて、電源周りにコンデンサを入れてやっても良いかも・・・。
プログラムは、以下のような感じです。
/************************************************************** 12F1822 ColorLED Pin assignment: (1)Vdd (2)RA5 (3)RA4 (4)RA3 MCLR 10Kohm Resister between Vdd (5)RA2 Blue LED (6)RA1 ICSPCLK / Green LED (7)RA0 ICSPDAT / Red LED (8)Gnd **************************************************************/ #include <pic.h> #define _XTAL_FREQ 8000000 __CONFIG( FOSC_INTOSC & WDTE_OFF & PWRTE_ON & MCLRE_OFF & CP_OFF & CPD_OFF & BOREN_ON & CLKOUTEN_OFF & IESO_OFF & FCMEN_OFF ); __CONFIG( WRT_OFF & PLLEN_OFF & STVREN_ON & BORV_25 & LVP_OFF ); const unsigned char Rsine[]={ 38,45,53,60,65,70,73,75,75,73, 70,65,60,53,45,37,30,22,15,10, 5,2,0,0,2,5,10,15,22,30}; const unsigned char Gsine[]={ 38,46,55,62,68,73,75,75,73,69, 63,55,47,38,29,20,13,7,3,0, 0,2,6,12,19,28}; const unsigned char Bsine[]={ 38,48,57,65,71,74,75,73,68,61, 53,43,33,23,14,7,2,0,1,4, 10,17,27}; unsigned int RDuty=0; unsigned int GDuty=0; unsigned int BDuty=0; unsigned char count=0; //Delay 100msec -------------------------------- void Delay_10ms(unsigned char time){ while(time--){ __delay_ms(10); } } void interrupt pwav(void){ if(TMR0IF==1){ TMR0 = 0; TMR0IF = 0; count++; if(count>75)count=0; if(count>RDuty){RA0=1;} else{RA0=0;} if(count>GDuty){RA1=1;} else{RA1=0;} if(count>BDuty){RA2=1;} else{RA2=0;} } } //------------------main void main(void){ unsigned int i,ri,gi,bi; //Initialization OSCCON = 0b01110010; // PLL disable, 8MHz internal clock ANSELA = 0b00000000; //All digital TRISA = 0b00001000; //GPIO dirction setting PORTA = 0b00000000; //GPIO initialize //--------------------------------------------------------- //TIMER0 INTERRUPT OPTION_REG=0b00000000; TMR0=0; TMR0IE=1; GIE=1; //---------------------------------------------------------- while(1){ GDuty=0; BDuty=0; for (RDuty=0;RDuty<75;RDuty++) Delay_10ms(10); for (RDuty=75;RDuty>1;RDuty--) Delay_10ms(10); RDuty=0; BDuty=0; for (GDuty=0;GDuty<75;GDuty++) Delay_10ms(10); for (GDuty=75;GDuty>1;GDuty--) Delay_10ms(10); RDuty=0; GDuty=0; for (BDuty=0;BDuty<75;BDuty++) Delay_10ms(10); for (BDuty=75;BDuty>1;BDuty--) Delay_10ms(10); GDuty=35; BDuty=35; for (RDuty=0;RDuty<75;RDuty++) Delay_10ms(10); for (RDuty=75;RDuty>1;RDuty--) Delay_10ms(10); RDuty=35; BDuty=35; for (GDuty=0;GDuty<75;GDuty++) Delay_10ms(10); for (GDuty=75;GDuty>1;GDuty--) Delay_10ms(10); RDuty=35; GDuty=35; for (BDuty=0;BDuty<75;BDuty++) Delay_10ms(10); for (BDuty=75;BDuty>1;BDuty--) Delay_10ms(10); for (i=0; i<200; i++){ RDuty=rand()/500; GDuty=rand()/500; BDuty=rand()/500; Delay_10ms(20); } ri=0; gi=0; bi=0; for(i=0;i<1000;i++){ RDuty=Rsine[ri]; GDuty=Gsine[gi]; BDuty=Bsine[bi]; Delay_10ms(10); ri++; gi++; bi++; if(ri>29)ri=0; if(gi>25)gi=0; if(bi>22)bi=0; } } //end of while } //end of main