【PICマイコン】RGBLEDで任意の好きな色を出してみる(PIC16F1938)

Pocket

rgbLED関数を作る

前回、RGBLED(フルカラーLED)の使い方を学びました。今回は、PICを使って好きな色を出してみます。




pwmを使う

pwmとは、細かいオンオフを繰り返して何かを駆動する技術のことです。これに関しては、PICで電子ホタルを作るで詳しく解説しています。

上記の記事では一つのLEDの明るさをPWMで変えましたが、RGBLEDの3色の明るさを同時に変えるにはどうすればいいのでしょうか。

最も単純な方法は下図のように各色の明るさの割合(duty)を設定し、ループを回してオンオフ判定でしょう。

赤の割合をrduty(red duty)、緑をgduty,青をbdutyとしています。明るさのパーセンテージだと思えば簡単です。この縦線で区切られたブロック内をfor文で回し、i++等でカウントアップします。その値がrduty等よりも大きいかどうかでオンオフを切り替えれば、図のような光らせ方が実現できますね。

このブロックをいくつも繋げることで、長い時間この色を表現できるようになります。

pwmLEDの記事でも説明しましたが、人間の目は騙されやすく、このループを高速で行うと平均された色に見えるのです。上図でいえば、rgb=(40,100,30)の光、つまり少し白の混ざった緑色に見えます。

rgbLED関数を書いてみる

では、このような原理で様々な色を表現する関数を作ってみましょう。赤色LEDのピンに繋がっているPICのピンをRedLED、同様にGreenLED,BlueLEDとすると、


      void rgbLED(int rduty,int gduty,int bduty,int time){
        int i=0;
        int j=0;
        for(j=1;j<time;j++){
            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(10);
            }
        }
      }
    

と書けます。一般にrgbは最大値を255とした値で表されるので、iの値を256までカウントアップすることにしました(中のループ文)。引数にはrduty等の光の割合(最大255),どのくらいの時間継続させるかのtimeを入れました。中のループに__delay_us(10)があり、255回ループされるので、time*10(μs)*256秒間この色を光らせることができます。

上記の説明通り、iをカウントアップして、それよりもdutyが大きかったらLEDの点灯を維持、小さくなったらオフにするという構造です。使うときはこのようにします。


      rgbLED(200,0,250,100);    //紫色(赤と青のLEDが点灯)
      rgbLED(100,200,0,100);    //オレンジ色(赤と緑のLEDが点灯)
      rgbLED(250,150,150,100);    //白色
    

回路組み・実行例

では、RGBLEDを実際にrgbLED関数で駆動してみます。下図のようにブレッドボード上にRGBLEDと抵抗・PICを設置します。

RGBLEDの赤色LEDのピン(端っこで、最も長い脚の隣)に510Ωの抵抗を繋ぎ、それをPIC16F1938のRB0ピンに繋ぎます。同様に緑色LED(右端)→510Ω→RB1、青色LED(右から2番目)→510Ω→RB2。

RGBLEDの長い脚(GND)は電源のGNDに繋ぎましょう(図では青いジャンパワイヤで接続)。

これに、PICにプログラムを書き込むを参考に、PICkit3を接続します。これで回路は完成です!

完成プログラム(例)

例として、下のようなプログラムを書き込んでみます。まずRB0にredLEDを繋げたので、#define RedLED RB0としています。(他のGreenLED等も同様)。こうすることで、LEDを繋ぐピンを変えても#define部分だけ変更すればよくなります。


      // 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(int rduty,int gduty,int bduty,int time){
        int i=0;
        int j=0;
        for(j=1;j<time;j++){
            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(10);
            }
        }
      }
      int main(void){
        PICinit();      //PICを初期化
        while(1){
            rgbLED(250,100,180,100);      //白
            rgbLED(0,0,90,100);           //青
            rgbLED(250,0,50,100);         //ローズレッド
        }
        return 0;
      }

    

このプログラムは、始めに白(少し緑っぽいかもしれません)、青、ローズレッドを出力するものです。もちろん、rgbLED()内のduty比は好きな値にして構いません。これはあくまで一例です。これで、好きな色が出せるようになりましたね!

関連記事   ESP32でネットワーク上から現在時刻を取得する(NTP)

実際に動いている様子



Pocket

返信を残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です