【実験】マイコンでLEDを光らせる

Uncategorized

プログラムを書き込んだマイコンをつかって、LEDを光らせました。

光センサをつなげて、明るさに応じてオンオフを切り替えられます。

プログラムを書き込むための道具

今回使ったのは、下記の道具です。

  • マイコン
  • ライター
  • プログラムソフト
  • その他(PC,ケーブル、回路素子)

プログラムソフトで書いたプログラムを、ライターを通して、マイコンに書き込みます。

マイコン

写真の黒い素子がマイコンです。

PIC16F1829の写真

型番はPIC16F1829です。

ライター

PICKit4というライターを使いました。

PICKit4の写真

フリスクの箱くらいの大きさです。

プログラムソフト

MPLAB X IDEという、開発ソフトウェアを使いました。

Microship Technologyという会社の無料ソフトです。

アセンブリ言語とC言語が使えます。

その他(PC,ケーブル,ワイヤ)

プログラムを書くPC、PCとライターをつなぐケーブル、ライターとマイコンをつなぐジャンプワイヤが必要です。

LEDをオンにする

LEDをつなぐピンの出力をオンにすれば、LEDがつきます。

例えばマイコンの「RC2」というピンにLEDをつなげる場合、

RC2=1;

と書けばいいです。

大電流を防ぐために、抵抗をはさもう!

「RC2-LED-抵抗-グラウンド」のようにつなげばOK

タイマーでオンオフを切り替える

PIC16F1829にはタイマー機能が搭載されています。

クロック周波数を8MHzにしている場合には、TMR0IFという値が32μsごとに1になります。

 

以下、少し難しい話
命令サイクルが1進むごとにTMR0というレジスタに1ずつ加算されていきます。TMR0は255のつぎには0にもどります。もどるときにTMR0IFが0だった場合には、TMR0IFが1になります。もどるときにTMR0IFが1だった場合には、TMR0IFは1のままです。
難しい話おわり。

 

以下は、1秒ごとにオンオフをくり返すソースコードです。

#pragma config FOSC = INTOSC // 発振
#pragma config WDTE = OFF // WDT 無効
#pragma config MCLRE = OFF
#pragma config PLLEN = ON // PLL 有効
#pragma config LVP = OFF
#include <xc.h>
void main()
{
PORTC = 0b00000000; // クリア
OSCCON = 0b11110000; // 動作クロック:32MHz
TRISC = 0b00000000; // 全て出力モード
ANSELC = 0b00000000; // 全てデジタルモード

OPTION_REG=0b11011000; //プリスケーラはオフ
while(1)
    {
    RC2 = 1; // RC2 を HIGH に
    TMR0IF=0;
    for(int i=0;i<31250;i++)
        {
        while(TMR0IF==0){}
        TMR0IF=0; //TMR0IFが1になったら0に戻して、i++
        }
    RC2 = 0; // クリア
    TMR0IF=0;
    for(int i=0;i<31250;i++)
        {
        while(TMR0IF==0){}
        TMR0IF=0;
        }
    } // 無限ループ
}

ちなみに上6行くらいは、「おまじない」です。私にもわかりません。

パルスで明るさを調整する

原理:オンオフを高速で切り替える

LEDは、基本的には明るさを調整できません。

例えば0~0.6Vまではオフ、0.6V以上はオン、というようになっています。0.6V以上に電圧を上げても、より明るくなったりはしません。
(オンオフの境目で電圧を動かすのならばできますが、シビアです)

 

そこで、電圧をパルス波形にすることで明るさが変わるように「見せ」ます。

パルス波形というのは例えば、

「4秒オンにして1秒オフ、4秒オンにして1秒オフ」

というようにオンオフをくり返していく波形です。

 

オンオフの間隔をもっと短くすると、人間にはLEDがつきっぱなしに見えます。

上の例は周期5秒ですが、この周期を5msくらいにすれば、オフになっていることはわかりません。

 

さらに、オンオフの時間の割合を変えることで、明るさを変えていきます。

上の例ではオンオフの比が8:2でした(デューティー比80%といいます)。
これを2msオン、3msオフというようにすると暗くなったように見えます(デューティー比40%)。

実装

PR2の値でパルス波の周期を、CCPR1Lの値でデューティー比を決めます。

(PR2+1)が1周期のサイクル数、CCPR1L/256がデューティー比になります。

 

以下は、約1秒ごとに明るくなったり暗くなったりをくり返すプログラムです。LEDへの出力はCCP1というピンです。

void main()
{
    OSCCON = 0b11110000; // 内臓クロックを 32MHz に設定
    ANSELC = 0x00; // PORTC はすべてデジタル設定
    TRISC = 0x00; // PORTC はすべて出力モード
    CCP1CON = 0b1100; // CCP1 を PWM モードに設定
                    // CCP1X, CCP1Y はともに 0
    T2CON = 0b111; // タイマ 2 の分周比を 1:64 に設定
    PR2 = 0xff; // タイマ 2 のカウンタと比較する値
    CCPR1L = 160; // デューティサイクルを設定
    OPTION_REG=0b11010111;//8.192msでTMR0が一周

    int i=0;
    while(1){
        
    CCPR1L=254;
    for(i=1;i<250;i++)//TMR0で時間を計る
        {
        while(TMR0IF==0){}
        CCPR1L--;
        TMR0IF=0; //TMR0IFが1になったら0に戻して、i++
        }
    
    for(i=0;i<250;i++)//TMR0で時間を計る
        {
        CCPR1L++;
        while(TMR0IF==0){}
        TMR0IF=0; //TMR0IFが1になったら0に戻して、i++
        }
    }
}

「おまじない」は省略しています。

照度センサーで暗いときだけオンにする

原理:フォトダイオードでオンオフの時間を調整する

フォトダイオードを照度センサーにして、明るさを変えます。

フォトダイオードに入る光が明るいと電流が大きくなり、暗いと小さくなります。

基本的にはフォトダイオードに流れる電流が大きいほどデューティー比を小さくし、電流が小さいほどデューティー比を大きくします。

実装:フォトダイオードの電流値を読み取らせる

実装の際には、フォトダイオードの電流の入力にアナログ/デジタル変換(AD変換)を行う必要があります。

PIC16F1829のAD変換機能を利用します。

AD変換の準備ができたあとにADGO=1を入力するとAD変換がはじまります。
AD変換が終わると変換結果がADRESHに出力され、ADGOの値が1から0に戻ります。

ADRESHの値は0~255の範囲です。

 

以下がソースコードです。フォトダイオードの電流入力はAN2で、LEDの出力はCCP1です。

「電源-フォトダイオード-CCP1-抵抗1-グラウンド」、
「CCP1-LED-抵抗2-グラウンド」のようにつなぐよ!

void main()
{
    OSCCON = 0b11110000; // 内臓クロックを 32MHz に設定
    ANSELC = 0x00; // PORTC はすべてデジタル設定
    TRISC = 0x00; // PORTC はすべて出力モード
    CCP1CON = 0b1100; // CCP1 を PWM モードに設定
                    // CCP1X, CCP1Y はともに 0
    T2CON = 0b111; // タイマ 2 の分周比を 1:64 に設定
    PR2 = 0xff; // タイマ 2 のカウンタと比較する値
    CCPR1L = 160; // デューティサイクルを設定
    OPTION_REG=0b11011000; //8.192msでTMR0が一周
    
    ANSELA = 0b00000100; // AN2(RA2) をアナログモードに設定
    TRISA = 0b00000111; // RA2 を入力モードに設定
    ADCON0 = 0b00001001; // AN2(bit6-2:00010) + ADC enable(bit0:1)
    ADCON1 = 0b00110000; // ADC に内部 RC 発振を利用

    OPTION_REG=0b11010111;
    TMR0IF=0;
    while(TMR0IF==0){} //AD変換の準備ができるまでの時間稼ぎ
    TMR0IF=0;
    while(TMR0IF==0){}
    TMR0IF=0;

    while(1){    
        while(!ADGO){ //ADGOが0になるたびにAD変換
        CCPR1L=155-ADRESH;
        ADGO=1;
        }
    }
}

さいごのwhile構文の中については、フォトダイオードの出力が明るいときでも150程度だったことを反映させています。

「おまじない」は省略です。

結果

フォトダイオードの値に応じて、LEDのデューティー比をかえるプログラムをマイコンに入れました。

すぐ上に書いたソースコードです。

フォトダイオードを指で覆ってみます。

LEDが暗い

↑before↓after

LEDがついた

成功です。光りました。

 

おわりー!

コメント

タイトルとURLをコピーしました