クリスマスシーズンなのでカラーLEDで遊んでみた。
巷は、クリスマスシーズンで夜になるとにぎやかにイルミネーションが輝いている。
せっかくなので、自分もフルカラー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