PICマイコン(PIC12F675)のコンパレータとヒステリシス特性

組み込みエンジニア

こんにちは、ENGかぴです。

マイコンのソフト開発をしているとコンパレータを使うことがあります。コンパレータは動作点付近で出力が頻繁に切り替わることがあり、ヒステリシス特性を持たせることがあります。PIC12F675を使ってヒステリシス特性の効果を説明しています。

PIC12F675のコンパレータの使い方については下記記事にまとめています。

PICマイコン(PIC12F675)のコンパレータの使い方

PIC12F675を使ってマイコンの動きを勉強するためにPIC12F675の機能でできることについてまとめています。

PICマイコン(PIC12F675)で実現できる機能と解説リンクまとめ

PIC12F675のコンパレータでヒステリシス特性

PIC12F675のコンパレータにおいてリファレンス電圧を基準にアナログ入力を変化させた場合を考えます。電源電圧VDDをDC5.0V、リファレンス電圧を2.5Vとします。

コンパレータの通常の動き

ヒステリシス特性の例
ヒステリシス特性の例

通常の動作であればリファレンス電圧Vrefを基準に出力を切り替えます。アナログ入力電圧がVref>Vinであれば出力はLレベルとなりVref>VinであればHレベルを出力します。

マイコンにはアナログ入力部にコンデンサが内蔵されていますが、ノイズの影響が無視できないほどになるとVref電圧付近の動作において出力が頻繁に切り替わることがあります。

これを防止するためにヒステリシス特性(シュミット回路)を持たせることがあります。

GEEKJOB-未経験からITエンジニアに【オンライン無料体験】

ヒステリシス特性を持たせた場合の動作

ヒステリシス特性を持たせた例
ヒステリシス特性を持たせた例

アナログ入力にノイズが乗っていたりすると出力がコンパレータ出力が頻繁に切り替わるようなチャタリングを起こす可能性があります。

頻繁に出力が切り替わることがあってはソフト内の処理に影響が出ることもあるので誤動作防止のためコンパレータにヒステリシス特性を持たせるのが一般的です。

コンパレータにヒステリシス特性を持たせる方法

ヒステリシス特性を持たせる方法(電圧の範囲)
ヒステリシス特性を持たせる方法(電圧の範囲)

ヒステリシス特性を持たせるためにVRCONレジスタの操作を行います。VRCONレジスタのVRRは1(Low range)をセットします。VRCONレジスタVR3~VR0レジスタの値を変更してヒステリシス特性を持たせます。

アナログ入力がVTHを一度超えたときにリファレンス電圧をVTLに変更することでアナログ入力がノイズなどの影響で低下したとしても2.08V以下になるまではHレベルを維持することができます。

アナログ入力のVTLを一度下回ったときにリファレンス電圧をVTHに変更することでアナログ入力がノイズなどの影響で上昇したとしても2.92V以上になるまではLレベルを維持することができます。

リファレンス電圧を変更することでヒステリシス特性を実現することができますが、ヒステリシス特性が大きすぎることが問題になる場合はVRRをHigh rangeにしてヒステリシス特性が大きくならないようにするなど工夫が必要です。

外部回路でアナログ入力が確実にヒステリシス特性範囲以外の電圧が検出できるように周辺回路を構成する必要があります。

PIC12F675の初期設定

PIC12F675でコンパレータを使用する方法については下記記事を参考にしてください。

PICマイコン(PIC12F675)のコンパレータの使い方

上記記事からの変更点は動作切り替えのフラグを持たせたことやVTHとVTLを実現するためのVR3:VR0の値を定義したことです。

#include <xc.h>
//--------------定数定義----------------------------
#define _XTAL_FREQ	4000000
#define DF_VRCON 0xAA
#define UP_VRCON 0xAF
#define	BIT_SET	1
#define	BIT_CLR	0
//--------------変数定義----------------------------
unsigned char   CmpFlg = BIT_CLR;

void main(void) {
    //各種初期化  
    ADCON0 = 0x00;  //ADコンバータ使用しない
    ANSEL = 0x00;   
    TRISIO = 0x0A;  //GP1,GP3入力、その他出力
    GPIO = 0x00;    //ポートの設定 1:High 0:Low
    OPTION_REG = 0x4F;  //プリスケーラ128 WDTで使用
    //コンパレータ
    CMCON = 0x03;   //コンパレータCiN-とリファレンス電圧を比較
    VRCON = UP_VRCON;   //リファレンス電圧ON、VRR=1 
    __delay_us(20); //設定待ち

CmpFlgはメインループ内で同じ条件下であっても一度しか処理させないためにフラグで管理して使用するために宣言しています。#define DF_VRCONがVTLに相当し、#define UP_VRCONがVTHに相当します。

定義しておくことでプログラム内で定義した名前を指定するだけでよく値を変更する場合も定義内の1か所のみの変更で済みます。

コンパレータにヒステリシス特性を実装する

PIC12F675でヒステリシス特性を実装していきます。コンパレータを使用して電圧の可変を検知してLEDを点灯/消灯する回路を考えます。

動作確認用の回路図

ヒステリシス特性を持たせたコンパレータの動作確認の回路図
ヒステリシス特性を持たせたコンパレータの動作確認の回路図

可変抵抗VR1を可変していきリファレンス電圧がVTHを上回っているとVIN+<VIN-なのでCOUTが0になりLED1が点灯します。VTLを下回るとCOUTが1になりLED1が消灯します。

ヒステリシス特性を持たせるため一度点灯/消灯の動作をすればVTLとVTH間の電圧範囲での変化は無効となります。

ヒステリシス特性を実装する

    while(1){
        CLRWDT();
        
        if( COUT == 1){
            //VTL以下の時
            if( CmpFlg == BIT_CLR ){
                CmpFlg = BIT_SET;  //リファレンス電圧の変更は一度だけ
                VRCON = UP_VRCON;  //リファレンスを上げる
                __delay_us(20);    //設定待ち
            }
        }
        else{
            //VTH以上の時
            if( CmpFlg ){
                CmpFlg = BIT_CLR;  //リファレンス電圧の変更は一度だけ
                VRCON = DF_VRCON;  //リファレンスを下げる
                __delay_us(20);    //設定待ち
            }
        }
    }

コンパレータの出力判定の切り替えによってVRCONレジスタのリファレンス電圧を変更しています。リファレンス電圧を変更したとにはリファレンス電圧の安定化のためウェイトを約20us置いています。

COUTが1か0かで処理を分岐していますが、分岐内でのリファレンス電圧の変更は同条件化においては一度のみ処理したらよいのでCmpFlgを切り替えることで一度しか処理しないようにしています。

今回はメインループ上でリファレンス電圧の変更を行いましたが、この処理をコンパレータ割り込みの中で行ってもよいと思います。

ソースコード全体

以下のソースコードはコンパイルして動作確認をしております。チェックはしておりますがコメントなど細かな部分で間違っている可能性があります。参考としてお使いいただければと思います。

// CONFIG
#pragma config FOSC = INTRCIO
#pragma config WDTE = ON
#pragma config PWRTE = OFF
#pragma config MCLRE = OFF
#pragma config BOREN = OFF
#pragma config CP = OFF
#pragma config CPD = OFF

#include <xc.h>
//--------------定数定義----------------------------
#define _XTAL_FREQ	4000000
#define DF_VRCON 0xAA
#define UP_VRCON 0xAF
#define	BIT_SET	1
#define	BIT_CLR	0
//--------------変数定義----------------------------
unsigned char   CmpFlg = BIT_CLR;

void main(void) {
    //各種初期化  
    ADCON0 = 0x00;  //ADコンバータ使用しない
    ANSEL = 0x00;   
    TRISIO = 0x0A;  //GP1,GP3入力、その他出力
    GPIO = 0x00;    //ポートの設定 1:High 0:Low
    OPTION_REG = 0x4F;  //プリスケーラ128 WDTで使用
    //コンパレータ
    CMCON = 0x03;   //コンパレータCiN-とリファレンス電圧を比較
    VRCON = UP_VRCON;   //リファレンス電圧ON、VRR=1 
    __delay_us(20); //設定待ち
    
    while(1){
        CLRWDT();
        
        if( COUT == 1){
            //VTL以下の時
            if( CmpFlg == BIT_CLR ){
                CmpFlg = BIT_SET;  //リファレンス電圧の変更は一度だけ
                VRCON = UP_VRCON;  //リファレンスを上げる
                __delay_us(20);    //設定待ち
            }
        }
        else{
            //VTH以上の時
            if( CmpFlg ){
                CmpFlg = BIT_CLR;  //リファレンス電圧の変更は一度だけ
                VRCON = DF_VRCON;  //リファレンスを下げる
                __delay_us(20);    //設定待ち
            }
        }
    }
}
//---------------------end file----------------------------

関連リンク

PICマイコンを使ってマイコンのレジスタの設定やMPLAB X IDEのプラグインであるMCCを使用して動作確認したことについてまとめています。

PICマイコン(PIC12F675)で実現できる機能と解説リンクまとめ

PICマイコン(PIC16F1827)で実現できる機能と解説リンクまとめ

TECH::CAMPプログラミング教養【無料体験会】

最後まで、読んでいただきありがとうございました。

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