---
---
マイコンの設定値を連続的に変化させるには、Push SWやボリュームを使うよりロータリーエンコーダを使用した方が操作性が向上します。 ロータリーエンコーダには、2つのSWが組み込まれており、ノブを回すことでそのSWが交互にOn/Offします。 具体的なタイミングは下図に示したように、A_pin の波形とB_pin の波形の位相が90°ずれて出力され、そのずれ方で回転方向を知ることができます。
プログラムでは、前回のモニター結果と、今回のモニター結果を組み合わせてノブの回転方向を見極めています。このため、もし、チャタリングが発生しても、時間の経過で出力が安定したときの最終的なカウント値は常に回転方向と一致した正しい結果が得られます。この方法を採用することで、プログラミングが大変にシンプルになりました。
<ロータリーエンコーダ製品例>
基本的な使用例として、ロータリーエンコーダの回転で、4つのLEDに表示される2進数を増減させるプログラムを示します。
// File name: Rotary Encorder
// Description:
// ロータリーエンコーの回転に対応した
// 値を4ヶのLEDで表示する。
// Notes: 4MHz内部クロック
// LED RC0-3
// Rotary Encorder
// RB4,RB5
// Language: MPLAB xc8
// Target: PIC18F14K50
#include < xc.h>
#define _XTAL_FREQ 4000000 // delay_ms(x) のための定義
#define LED LATC
#define A_pin PORTBbits.RB5
#define B_pin PORTBbits.RB4
//-- コンフィグレーション --------
#pragma config MCLRE = OFF, PWRTEN = OFF, BOREN = OFF, BORV = 30
#pragma config WDTEN = OFF, WDTPS = 32768, STVREN = ON, FOSC = IRC
#pragma config PLLEN = ON, CPUDIV = NOCLKDIV, USBDIV = OFF
#pragma config FCMEN = OFF, IESO = OFF, HFOFST = OFF, LVP = OFF
#pragma config XINST = OFF, BBSIZ = OFF, CP0 = OFF
#pragma config CP1 = OFF, CPB = OFF, WRT0 = OFF
#pragma config WRT1 = OFF, WRTB = OFF, WRTC = OFF
#pragma config EBTR0 = OFF, EBTR1 = OFF, EBTRB = OFF
//-------プロトタイプ--------------------------------------------------
char readRE(void);
#pragma code
void main(void){
char count = 0;
OSCCON = 0b01010010; // 内部クロック4Mhz
PORTC = 0;
TRISB = 0xF0; // PortB 入力
TRISC = 0xF0; // PortC RC0-3出力
ANSEL = 0; // デジタル入力
ANSELH = 0;
INTCON2bits.RABPU = 0; // RA/RB WeekPullUpをONに設定
while(1){ // 繰り返しループ
count += readRE(); // 変化分を加算する
// LED = count >> 2; // 1ノッチで4カウント進むタイプ
LED = count; // ノッチのないタイプ
} // ここまで繰り返し
}
//------------------ readRE ------------------------------
// 直前の状況と今回の状況を合わせた16通りの組合せから
// 左右どちらに回転をしたのか判定することができる
// 戻り値は (-1,0,1) の3通り
//--------------------------------------------------------
char readRE(void){
static char RE_states[] = {0,-1,1,0,1,0,0,-1,-1,0,0,1,0,1,-1,0};
static char RE_old = 0; // 共通変数(値は保存)
char RE_now;
RE_now = B_pin * 2 + A_pin; // 今回情報の読取
RE_old <<= 2; // 前回の読取値と
RE_old |= ( RE_now & 0x03 ); // 今回の読取値を組合わせる
return (RE_states[(RE_old & 0x0F)]); // 変化分を戻り値をする
}