クリスマスシーズンなのでカラーLEDで遊んでみた。

巷は、クリスマスシーズンで夜になるとにぎやかにイルミネーションが輝いている。
せっかくなので、自分もフルカラーLEDでクリスマスの気分を・・・。
と、いうわけで、PIC 12F1822 と、フルカラーLED (OSTA71A1D-A) でイルミネーションを作ってみた。
とはいえ、ただ、LEDの色が変化していくだけではあるが・・・。
f:id:manpukukoji:20171217110755j:plain
フルカラー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をつなぐだけですので、今回は、手書きです。
必要に応じて、電源周りにコンデンサを入れてやっても良いかも・・・。
f:id:manpukukoji:20171217120039j:plain
プログラムは、以下のような感じです。

/**************************************************************
	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