可変抵抗のツマミを回してLEDの明るさを可変します(2/2)

(1/2) 〔PICの動かせ方入門に戻る〕


前の頁では18F25K22(18F2xK22)の標準CCP機能で、CCP4とCCP5を使ってPWM出力を行いました。
18F25K22(18F2xK22)には他に拡張型CCP機能でECCP(ECCP1/ECCP2/ECCP3)が有ります。
このECCPのPWMモードには、シングルPWM・ハーフブリッジPWM・フルブリッジPWMが有り、
ハーフブリッジやフルブリッジはモータ等を回すのに使います、 ここではシングルPWMを利用して、
LEDの明るさを可変させてみたいと思います。
(PWM制御についての少し詳しい話はこちらのページを参考にして下さい。)

VRtoLED14  シングルPWM機能とは、
 PICの内部で生成された
 PWM(CCP1/CCP2/CCP3)信号はピンの
 P1A/P1B/P1C/P1D (P2A/P2B) (P3A/P3B)に
 それぞれ接続されています、
 なので、同じPWMを同時に4つ(2つ)のピンに
 出力が出来ますが、
 PSTRxCONレジスターにてそれぞれの
 ピン出力をON/OFF出来ます。
 これをPWMステアリング制御と言います。

 P1A/P1B/P1C/P1DをフルブリッジPWMと言い
 P2A/P2B、P3A/P3BをハーフブリッジPWMと言います。

 P2A(24/12)/P2B(26/11)/P3A(26/17)のピンは
 使用する端子をコンフィグで指定します。
 P2Aの端子割り当ては
 #pragma config CCP2MX=PORTC1 12番
 #pragma config CCP2MX=PORTB3 24番

 P2Bの端子割り当ては
 #pragma config P2BMX=PORTC0 11番
 #pragma config P2BMX=PORTB5 26番
 P3Aの端子割り当ては
 #pragma config CCP3MX=PORTC6 17番
 #pragma config CCP3MX=PORTB5 26番

この記事ではCCP1からPWM信号を作りP1Dの25番ピンから出力をしてみます。
(P1A/P1B/P1Cからは出力しません、OFFです、デジタル端子として使用可能です。)
VRtoLED11
 左図はPIC18F25K22のピン構成です。

 今回使用するピン番号は20番(VDD)と8/19番(VSS)を
 電源に配線します。
 CCP1出力は25番(P1D)ピンでアナログ入力は
 14番(AN15)ピンです。

VRtoLED12  左図は18F25K22での配線図ですが、
 18F23K22/18F24K2218F26K22も同じです。

 LEDは足が長い方をPIC側に配線です。
 半固定抵抗は10KΩでもOKです。


(サンプルプログラム)

半固定抵抗の値でLEDの明るさを可変させます。
拡張型CCP機能のECCP1でPWM信号(1KH)を生成しP1D(25番)端子から出力してLEDの明るさを可変します。
CCP1のPWM生成にはタイマー2を使用し、PWMのデューティ比は半固定抵抗の値を使用します。

@下記がプログラムソースです、
  MPLAB(R) XC8 C Compiler Version 1.38コンパイラを使用しています。
  MPLAB X IDEでプロジェクトを作成して新規ファイルにコピーペーストして貼り付けて下さい。 *2)
---------------------------------------------------------------------
#include <xc.h>

#define _XTAL_FREQ 16000000    //  delay用に必要(クロック16MHzを指定)

// コンフィギュレーションの設定(ここの記述に無い設定はデフォルト値での動作)
// 外部クロックは使用しない(PRICLKEN_OFF)
// 動作クロックを4倍では動作させない(PLLCFG_OFF):内部部クロックを使用する(INTIO67)
#pragma config PRICLKEN=OFF,PLLCFG=OFF,FOSC=INTIO67  // CONFIG1H
// 電源電圧降下常時監視機能ON(BOREN_NOSLP):監視電圧は(2.85V)に設定
// 電源ONから後65.6msにプログラムを開始する(PWRTEN_ON)
#pragma config BOREN=NOSLP,BORV=285,PWRTEN=ON        // CONFIG2L
// ウオッチドッグタイマー無し(WDTEN_OFF)
#pragma config WDTEN=OFF                             // CONFIG2H
// 外部リセット信号は使用せずにデジタル入力(RE3)ピンとする(MCLRE_INTMCLR)
// オシレータが安定するのを待ってシステムクロックを供給する(HFOFST_OFF)
#pragma config MCLRE=INTMCLR,HFOFST=OFF              // CONFIG3H
// 低電圧プログラミング機能使用しない(LVP_OFF)
#pragma config LVP=OFF                               // CONFIG4L

// アナログ値の変換と読込み処理
unsigned int adconv()
{
     unsigned int temp;

     GO_nDONE = 1 ;	      // アナログ値読取り開始指示
     while(GO_nDONE) ;        // 読取り完了まで待つ
     temp = ADRESH ;
     temp = ( temp << 8 ) | ADRESL ;

     return temp ;
}
// メインの処理
void main()
{
     unsigned int num ;

     OSCCON = 0b01110010 ;    // 内部クロックとする(16MHz)
     ANSELA = 0b00000000 ;    // AN0-4 アナログは使用しない、デジタルI/Oに割当
     ANSELB = 0b00000000 ;    // AN8-13アナログは使用しない、デジタルI/Oに割当
     ANSELC = 0b00001000 ;    // AN14-19アナログは使用しない、AN15のみアナログで使用
     TRISA  = 0b00000000 ;    // RA0-RA7全て出力に設定、1で入力 0で出力
     TRISB  = 0b00000000 ;    // RB0-RB7全て出力に設定
     TRISC  = 0b00001000 ;    // RC3のみ入力、それ以外RC0-RC7は出力に設定 
     PORTA  = 0b00000000 ;    // 出力ピンの初期化(全てLOWにする)
     PORTB  = 0b00000000 ;    // 出力ピンの初期化(全てLOWにする)
     PORTC  = 0b00000000 ;    // 出力ピンの初期化(全てLOWにする)
     // アナログ入力の設定
     ADCON1 = 0b00000000 ;    // VDDをリファレンスとする
     ADCON2 = 0b10010101 ;    // 読取値は右寄せ、A/D変換クロックはFOSC/16、4TAD後に変換開始
     ADCON0 = 0b00111101 ;    // アナログ変換情報設定(AN15から読込む)
     __delay_us(8) ;          // アナログ変換情報が設定されるまでとりあえず待つ
     // ECCP1の設定(拡張型CCP機能)
     CCPTMRS0 = 0b00000000 ;  // CCP1機能はTimer2を使用する
     CCP1CON  = 0b00001100 ;  // PWM機能(シングル出力)を使用する
     PSTR1CON = 0b00001000 ;  // P1DのRB4ピンのみPWM出力する、P1A/B/CはOFF
     T2CON    = 0b00000010 ;  // TMR2プリスケーラ値を16倍に設定
     CCPR1L   = 0 ;           // デューティ値は0で初期化
     CCPR1H   = 0 ;
     TMR2     = 0 ;           // タイマー2カウンターを初期化
     PR2      = 249 ;         // PWMの周期を設定(1000Hzで設定)
     TMR2ON   = 1 ;           // TMR2(PWM)スタート

     while(1) {
          num = adconv() ;    // 14番ピン(AN15)から半固定抵抗の値を読み込む
          CCPR1L = num/4 ;    // アナログ値からのデータでデューティ値を設定
     }
}
---------------------------------------------------------------------
AコンパイルPIC書き込みを実行して下さい。 *2)

BPICをブレッドボードに取付けて、半固定抵抗を回して見て下さいLEDの明るさが変わると思います。

《やさしく解説》

LEDについて

VRtoLED4

LEDには極性が有ります、
足の長いアノード側を25番ピンの方に、足の短いカソード側を電流制限抵抗の方に接続します。
また、LEDには流せる電圧と電流が決まっています、必ず電流制限抵抗を付けましょう。

電流制限抵抗
 LEDの順方向電流(IF)と順方向電圧(VF)がデータシート等に書いてあると思います、
 例えばIFが10mAで、VFが2.5Vで、picのアナログ出力が5Vとすると、
 (pic出力−順方向電圧)÷ 順方向電流 = 電流制限抵抗値
 よって、(5V - 2.5V) ÷ 0.010A = 250Ω(250Ωは無いので240Ωか270Ωを使います)
 10mAは0.010AというふうにAに変換して計算します。

 だいたい120Ω〜680Ωのあたりだと思います。
 LEDは5mAくらいで使った方が目に優しいでしょう、で470Ω?
 また、抵抗はLEDのアノード側とカソード側のどちら側に接続してもOKです。

 注意) PICの出力は20mA程しか流せません、これ以上のLED電流を流す場合は
     PICの出力をトランジスタで一旦受けてからLEDをつながないといけません。
     マイコン出力をトランジスタで一旦受ける場合はこちらを参考にして下さい。

半固定抵抗について

アナログ入力は電圧の0〜5Vを0〜1023の値に変換して読み込みます。
半固定抵抗は今回10kΩを使用で、だいたい60〜530位で読み込まれます。

ツマミを右に回せばLEDの明るさは暗くなり、左に回せば明るくなります。
また、半固定抵抗の配線を5V(赤線)とGND(黒線)で入れ替えると、
右に回しでLEDの明るさは明るくなり逆になります。
半固定抵抗の20kΩ辺りを取付ければもっとハッキリ変化が解るでしょう。

プログラムについて

プログラムソースのコメントを読んでもらえば大体何をしているのか分かると思います。

while(1)
 main()の中の処理は1回実行すると終了します、
 だからwhile(1)の、{ }の中に処理を書き込めば無限に繰り返します。
 もしwhile(1)を記述しないとプログラムはすぐ終了し、ツマミを回してもLEDは変化しません。

__delay_us(value)
 プログラムを指定した時間だけ一時停止します。
 value:停止したい時間を指定します、単位はマイクロ秒です。
 クロック8MHz動作では98560usまでしか指定できません。
 __delay_msなら98msまでです。

adconv( )
 アナログ(半固定抵抗)の値を読み取ります、値は0〜1023の範囲です。

アナログI/O
 アナログピンの設定は下記のレジスターにて設定します。(デフォルトはアナログ入力です)
 ANSELA = 0b00000000 ;
     アナログ入力を行うピンA(RA0-RA3/RA5)の指定をします。
     赤数字右からAN0(2ピン),AN1(3ピン),AN2(4ピン),AN3(5ピン),AN4(7ピン)の順
     1でアナログ、0でデジタル、この設定はAN0-AN4を全てデジタルI/Oに割当
 ANSELB = 0b00000000 ;
     アナログ入力を行うピンB(RB0-RB5)の指定をします。
     赤数字右からAN12(21ピン),AN10(22ピン),AN8(23ピン),AN9(24ピン),AN11(25ピン),
     AN13(26ピン)の順
     1でアナログ、0でデジタル、この設定はAN8-AN13を全てデジタルI/Oに割当
 ANSELC = 0b00001000 ;
     アナログ入力を行うピンB(RC2-RC7)の指定をします。
     赤数字右からAN14(13ピン),AN15(14ピン),AN16(15ピン),AN17(16ピン),
     AN18(17ピン),AN19(18ピン)の順
     でアナログ、0でデジタル、この設定はAN15をアナログにするです

 次にピンの入出力を設定します。(デフォルトは入力です)
 TRISA = 0b00000000 ;
     この設定はAN0-AN4全て出力に設定するです。
     1で入力、0で出力、右からAN0,AN1,AN2,AN3,AN4、残りはデジタルです。
 TRISB = 0b00000000 ;
     この設定はAN8-AN13全て出力に設定するですす。
     右からAN12,AN10,AN8,AN9,AN11,AN13、残りはデジタルです。
 TRISC = 0b00001000 ;
     この設定はAN15のみ入力に設定するです。
     右からAN14,AN15,AN16,AN17,AN18,AN19、残りはデジタルです。

アナログ変換情報設定
 ADCON0 = 0b00111101 ;
     この設定でAN15から読込めと指示しています。
     他のAN15以外から読込みたい場合は、赤数字の部分を変更します。
     AN0=00000,AN1=00001,AN2=00010,AN3=00011,AN4=00100,
     AN8=01000,AN9=01001,AN10=01010,AN11=01011,AN12=01100,AN13=01101,
     AN14=01110,AN15=01111,AN16=10000,AN17=10001,AN18=10010,
     AN19=10011 と変更して下さい。
     緑数字の部分は、1=アナログ変換有効 0=アナログ変換無効
     また、ADCON0の設定には8usほどかかります、delayを入れておきましょう。

 ADCON1 = 0b00000000 ;
     赤数字部分でA/D変換時の+側リファレンス電圧をどうするかの設定です。
     00:VDDのPIC電圧を使用する 01:5番ピン接続の外部VREF+を使用する。
     10:PIC内蔵の固定電圧を使用する。
     緑数字部分でA/D変換時の−側リファレンス電圧をどうするかの設定です。
     00:VDDのPIC電圧を使用する 01:4番ピン接続の外部VREF-を使用する。
     また、それ以外の数字部分の設定は今回このまま使用して下さい。

 ADCON2 = 0b10010101 ;
     赤数字部分で変換開始までの待ち時間(A/Dアクイジション時間)を設定する。
     とり合えずぅ4TAD(010)辺りで良いでしょう。
     緑数字部分でA/D変換を行う速度のクロックを設定します。
     000:FOSC/2 001:FOSC/8  010:FOSC/32
     100:FOSC/4 101:FOSC/16 110:FOSC/64
     また、それ以外の数字部分の設定は今回このまま使用して下さい。

PWM機能設定
 PWMを使用する為には以下の設定が必要です、
 この設定は1KHzの周波数で、PWM制御する設定です。
 LEDならこの位で良かろうと、適当なんですが、
 少し詳しい設定の説明はこちら(標準CCP機能での記述ですが基本は同じです)を参照して下さい。

 出力ピンを決める
 PSTR1CON = 0b00001000 ; この設定でCCP1のPWM出力はP1Dのみ出力、P1A/P1B/P1CはOFF。
                 1:ON 0:OFF
                 右からそれぞれP1A/P1B/P1C/P1Dの順です。
 尚、CCP2/3のPSTR2CON/PSTR3CONのばあいは
 PSTRxCON = 0b00000000 ; 右からPxA/PxBの順です。

 標準CCPと同じように、ECCP1とECCP2/ECCP3もそれぞれにTimer2/4/6の何れかを使用します。
 その設定はCCPTMRS0レジスターにて行います。
 CCPTMRS0 = 0b00000000 ;
                赤数字部分がCCP3用の設定で、緑数字部分がCCP2の用設定で、
                青数字部分がCCP1用設定の場所です。
                Timer2=00 , Timer4=01 , Timer6=10 (デフォルトはTimer2)

 次の記述例はCCP2でTimer4を使用する場合です。
 CCPTMRS0 = 0b00001000 ;    // CCP2でTimer4を使用する
 CCP2CON  = 0b00001100 ;    // PWM機能(シングル出力)を使用する
 T4CON    = 0b00000010 ;    // TMR4プリスケーラ値を16倍に設定
 CCPR2L   = 0 ;             // デューティ値は0で初期化
 CCPR2H   = 0 ;
 TMR4     = 0 ;             // タイマー4カウンターを初期化
 PR4      = 249 ;           // PWMの周期を設定(1000Hzで設定)
 TMR4ON   = 1 ;             // TMR4(PWM)スタート

  CCPR2L = num/4 ;   // アナログ値からのデータでデューティ値を設定
 なのでぇ、タイマー2/4/6が有るのでECCP1/ECCP2/ECCP3とCCP4/CCP5から最高3個まで同時に
 PWMを出力可能ですね。


相補PWM出力制御 *1)
memo3  左図の様にP1CピンがHIGH時はP1DピンはLOWを
 出力する様に反転させます(差動出力)、これを
 相補PWM出力制御と言います。

 下がP1DからPWMを出力する場合でしたが、
 CCP1CON  = 0b00001100 ;   // PWM機能(シングル出力)を使用する
 PSTR1CON = 0b00001000 ;   // P1DのRB4ピンのみPWM出力する、P1A/B/CはOFF

 P1C(アクティブHIGH)とP1D(アクティブLOW)から相補PWMを出力する場合は、
 CCP1CON  = 0b00001101 ;   // PWM機能(シングル出力:相補を行う)を使用する
 PSTR1CON = 0b00001100 ;   // P1CをPWM出力する、P1Dは反転出力、P1A/BはOFF
 CCP1CON = 0b00001101;
               赤色部分でPWMの出力パターンを設定します。
               1100:P1A、P1C をアクティブHigh、P1B、P1D をアクティブHigh
               1101:P1A、P1C をアクティブHigh、P1B、P1D をアクティブLow
               1110:P1A、P1C をアクティブLow、P1B、P1D をアクティブHigh
               1111:P1A、P1C をアクティブLow、P1B、P1D をアクティブLow

 ※ 但し、ECCP1/ECCP2/ECCP3の拡張型CCP機能のみ相補PWMを出力可能です。

《その他》

今回は14番・25番ピンを使用しましたが他のピンを使用する場合は下記の表を参照して下さい。
また、1番ピンは外部からのリセット端子ですが、コンフィグで MCLRE = INTMCLR を記述すれば
RE3のデジタル入力端子として利用できます。
ポートA
ピン番号 10
デジタル入出力ビット名 RA7 RA6 RA5 RA4 RA3 RA2 RA1 RA0
アナログ入力ピン名 AN4 AN3 AN2 AN1 AN0

ポートB
ピン番号 28 27 26 25 24 23 22 21
デジタル入出力ビット名 RB7 RB6 RB5 RB4 RB3 RB2 RB1 RB0
アナログ入力ピン名 AN13 AN11 AN9 AN8 AN10 AN12
PWM 出力ピン名 P2B/P3A P1D P2A P1B P1C

ポートC
ピン番号 18 17 16 15 14 13 12 11
デジタル入出力ビット名 RC7 RC6 RC5 RC4 RC3 RC2 RC1 RC0
アナログ入力ピン名 AN19 AN18 AN17 AN16 AN15 AN14
PWM 出力ピン名 P3A P3B P1A P2A P2B



リンクの見直し(*2) 2017/01/13
一部追記(*1) 2014/11/24


【きむ茶工房ガレージハウス】
Copyright (C) 2006-2020 Shigehiro Kimura All Rights Reserved.