目次
電子ホタルとは
電子ホタルというのは蛍のように明るさが変動するあかりのことです。
今回の記事のプログラムが動いている様子
単色電子ホタル
単色電子ホタルに関してはPICで電子ホタルを作るで詳しく解説していますので、電子ホタルを作ったことがない方はこちらをまず作ってみてください。
原理は単色電子ホタルと同じでPWMを使います。が、フルカラーLEDの色制御にもPWMを使っているので、少し工夫する必要があります(フルカラーLEDに関しては後述)。
フルカラー用の蛍関数
フルカラーLEDの使用方法と原理
フルカラーLEDの使い方と、その色の出し方に関してはこれらを参考にしてください。
色合いはそのまま暗くする
RGBLEDの光を制御するとき、rduty,gduty,bdutyの3つのパラメーターをfor文の中で高速に回し、色を表現していました(上述の記事より)。
では、色合いはそのままで明るさを変えるにはどうすればいいのでしょうか。一つの方法として、各rgb値に明るさの割合をかけるというものがあります。
void rgbLED(unsigned int rduty,unsigned int gduty,unsigned int bduty,unsigned int duty){
int i=0;
rduty = rduty*duty/256; //各rgb値に明るさの割合(duty/256)を掛ける
gduty = gduty*duty/256;
bduty = bduty*duty/256;
for(i=1;i<256;i++){ //PWM部分
if(i<rduty){
RedLED = 1; //赤色LEDをオン
}else{
RedLED = 0; //LEDをオフ
}
if(i<gduty){
GreenLED = 1; //緑色LEDをオン
}else{
GreenLED = 0; //LEDをオフ
}
if(i<bduty){
BlueLED = 1; //青色LEDをオン
}else{
BlueLED = 0; //LEDをオフ
}
__delay_us(1);
}
}
上記コードのPWM部分は、RGBLEDで任意の好きな色を出すと全く同じになっています。その上に新たにduty/256を掛けた3つの文が追加されました。
dutyは明るさを調節する変数で、256までの数字をとれます。例えばduty = 128の時、各色の強さは1/2になります。全体として同じ割合だけ暗くなるので、色合いは全く変えることなく明るさを変えることができるのです。意外と簡単ですね。
P.S 引数がunsigned intなのは、上記3つの代入式でrduty*dutyをしたときにオーバーフローが生じないようにしたためです。実際intに変えて実行してみると、rduty=200の時などはオーバーフローが生じ、赤が全く光らなくなります。
完成した関数
勘のいい方は、上記のrgbLED関数をforループで回し、dutyにiを入れればだんだんと明るくなるようにできることに気付いているでしょう。これを関数にしてみました(下のfireFly関数)
void fireFly(unsigned int r,unsigned int g,unsigned int b){
int duty = 0;
for(duty;duty<256;duty++){ //段々明るく
rgbLED(r,g,b,duty);
}
for(duty;duty>0;duty--){ //段々暗く
rgbLED(r,g,b,duty);
}
}
これで、一定の周期でrbgに指定した色で蛍のように発光してくれます。
完成サンプルプログラム
回路
// PIC16F1938 Configuration Bit Settings
// 'C' source line config statements
// CONFIG1
#pragma config FOSC = INTOSC // Oscillator Selection (INTOSC oscillator: I/O function on CLKIN pin)
#pragma config WDTE = OFF // Watchdog Timer Enable (WDT disabled)
#pragma config PWRTE = OFF // Power-up Timer Enable (PWRT disabled)
#pragma config MCLRE = OFF // MCLR Pin Function Select (MCLR/VPP pin function is digital input)
#pragma config CP = OFF // Flash Program Memory Code Protection (Program memory code protection is disabled)
#pragma config CPD = OFF // Data Memory Code Protection (Data memory code protection is disabled)
#pragma config BOREN = OFF // Brown-out Reset Enable (Brown-out Reset disabled)
#pragma config CLKOUTEN = OFF // Clock Out Enable (CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin)
#pragma config IESO = OFF // Internal/External Switchover (Internal/External Switchover mode is disabled)
#pragma config FCMEN = OFF // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor is disabled)
// CONFIG2
#pragma config WRT = OFF // Flash Memory Self-Write Protection (Write protection off)
#pragma config VCAPEN = OFF // Voltage Regulator Capacitor Enable (All VCAP pin functionality is disabled)
#pragma config PLLEN = OFF // PLL Enable (4x PLL disabled)
#pragma config STVREN = ON // Stack Overflow/Underflow Reset Enable (Stack Overflow or Underflow will cause a Reset)
#pragma config BORV = LO // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), low trip point selected.)
#pragma config LVP = ON // Low-Voltage Programming Enable (Low-voltage programming enabled)
// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.
#include <xc.h>
#define _XTAL_FREQ 8000000
#define RedLED RB0
#define GreenLED RB1
#define BlueLED RB2
void PICinit(){
OSCCON = 0b01110000;
ANSELA = 0b00000000;
ANSELB = 0b00000000;
TRISA = 0b00000000;
TRISB = 0b00000000;
TRISC = 0b00000000;
PORTA = 0b00000000; //2進数で書いた場合
PORTB = 0x00; //16進数で書いた場合
PORTC = 0; //10進数で書いた場合
}
void rgbLED(unsigned int rduty,unsigned int gduty,unsigned int bduty,unsigned int duty){
int i=0;
rduty = rduty*duty/256;
gduty = gduty*duty/256;
bduty = bduty*duty/256;
for(i=1;i<256;i++){
if(i<rduty){
RedLED = 1; //赤色LEDをオン
}else{
RedLED = 0; //LEDをオフ
}
if(i<gduty){
GreenLED = 1; //緑色LEDをオン
}else{
GreenLED = 0; //LEDをオフ
}
if(i<bduty){
BlueLED = 1; //青色LEDをオン
}else{
BlueLED = 0; //LEDをオフ
}
__delay_us(1);
}
}
void fireFly(unsigned int r,unsigned int g,unsigned int b){
int duty = 0;
for(duty;duty<256;duty++){
rgbLED(r,g,b,duty);
}
for(duty;duty>0;duty--){
rgbLED(r,g,b,duty);
}
}
int main(void){
PICinit(); //PICを初期化
while(1){
fireFly(0,100,200);
fireFly(250,160,0);
fireFly(250,10,240);
fireFly(250,0,50);
}
return 0;
}
main関数内は4つの色の電子ホタルを繰り返しています。
今後のアイデア・発展
これで割と高度なイルミネーションのようなものが作れました。今後の発展としては、温度によって色が変わる電子ホタルなどは素敵ではないでしょうか。他にも、正常な動きをしているときは緑色の電子ホタルで、エラーが起きたとき(高温になった時など)には赤で点滅なんかも簡単に作れますね。
皆さんもぜひ応用して面白いものを作ってみてください。記事をお読みいただき、ありがとうございました!
ピンバック: Wak-tech » RGBLEDの色を温度によって変える