こんにちは、ENGかぴです。
マイコンのソフト開発をしているとコンパレータを使うことがあります。コンパレータは動作点付近で出力が頻繁に切り替わることがあり、ヒステリシス特性を持たせることがあります。PIC12F675を使ってヒステリシス特性の効果を説明しています。
PIC12F675のコンパレータの使い方については下記記事にまとめています。
PIC12F675を使ってマイコンの動きを勉強するためにPIC12F675の機能でできることについてまとめています。
PICマイコン(PIC12F675)で実現できる機能と解説リンクまとめ
PIC12F675のコンパレータでヒステリシス特性
PIC12F675のコンパレータにおいてリファレンス電圧を基準にアナログ入力を変化させた場合を考えます。電源電圧VDDをDC5.0V、リファレンス電圧を2.5Vとします。
コンパレータの通常の動き
通常の動作であればリファレンス電圧Vrefを基準に出力を切り替えます。アナログ入力電圧がVref>Vinであれば出力はLレベルとなりVref>VinであればHレベルを出力します。
これを防止するためにヒステリシス特性(シュミット回路)を持たせることがあります。
ヒステリシス特性を持たせた場合の動作
アナログ入力にノイズが乗っていたりすると出力がコンパレータ出力が頻繁に切り替わるようなチャタリングを起こす可能性があります。
コンパレータにヒステリシス特性を持たせる方法
ヒステリシス特性を持たせるためにVRCONレジスタの操作を行います。VRCONレジスタのVRRは1(Low range)をセットします。VRCONレジスタVR3~VR0レジスタの値を変更してヒステリシス特性を持たせます。
アナログ入力がVTHを一度超えたときにリファレンス電圧をVTLに変更することでアナログ入力がノイズなどの影響で低下したとしても2.08V以下になるまではHレベルを維持することができます。
アナログ入力のVTLを一度下回ったときにリファレンス電圧をVTHに変更することでアナログ入力がノイズなどの影響で上昇したとしても2.92V以上になるまではLレベルを維持することができます。
外部回路でアナログ入力が確実にヒステリシス特性範囲以外の電圧が検出できるように周辺回路を構成する必要があります。
PIC12F675の初期設定
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が消灯します。
ヒステリシス特性を実装する
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)で実現できる機能と解説リンクまとめ
最後まで、読んでいただきありがとうございました。