====== マップメータ(電子物差し) ======
===== 概要 =====
地図を見るときに目的地までの距離を知りたくなるときがあります。
今回は、地図の上をなぞることによって、その距離を測定し、結果を表示させてみました。
この値を尺度換算すると実際の距離がわかります。
===== 動作原理 =====
地図の上をなぞる方法は、ロータりエンコードを使うことにしました。
古いマウスが手元にありましたので、その内部で使用されているロータリエンコーダが使えないかと考えました。
取り外して、調べてみると、次のような仕様なので何とか使えそうです。
* 1回転で48の変化(A相、B相の信号)※回路図上の図Bを参照してください。
* ローラの直径が22mm(1回転で約69mm)
この仕様より、距離を求める式は、次のようになります。
* 距離=(22mm÷48)×ロータリエンコーダの変化数×3.14159
マウスのふたを外してみました。
{{:imgpaste:202004:htmikan-20200429-205019.png}}{{:imgpaste:202004:htmikan-20200429-205023.png}}
小さなロータリエンコーダが使われていました。
{{:imgpaste:202004:htmikan-20200429-205028.png}}{{:imgpaste:202004:htmikan-20200429-205032.png}}
基板から外しました。
{{:imgpaste:202004:htmikan-20200429-205036.png}}{{:imgpaste:202004:htmikan-20200429-205039.png}}
小さな基板に組み直しました。
{{:imgpaste:202004:htmikan-20200429-205100.png}}{{:imgpaste:202004:htmikan-20200429-205103.png}}
===== 回路図 =====
{{:imgpaste:202004:htmikan-20200429-205532.png}}
===== ソースコード =====
※ロータリエンコーダの回転の有無および正転逆転の向きを知る方法
1msec毎の割り込み処理の中で、図Bの表で示す変化を検出し判断します。
//**********************************************************************
/*
<マップメータ(電子物差し)>
■機能概要
・ロータリエンコーダ
分解能(12ステップ/1回転)
直径22mm
■表示内容
・距離(mm単位)
■CONFIGの設定
・LVP_OFF
・MCLR_OFF
・WDT_OFF
・INTRC_IO
*/
//**********************************************************************
#define SW0 PORTA.F5
#define SW1 PORTB.F0
#define SW2 PORTB.F1
#define LED1 PORTB.F2
#define LED2 PORTB.F3
//**********************************************************************
static unsigned char RE_dat, RE_tmp;
static int RE_val;
void interrupt()
{
// 1msecの割り込み処理
if (PIR1.CCP1IF == 1) {
PIR1.CCP1IF = 0;
//
RE_tmp = PORTB & 0x03;
//前回の値との変化でロータリエンコンダの回転の有無を判断
switch (RE_dat) {
case 0:
switch (RE_tmp) {
case 0:
break;
case 1:
RE_val++;
break;
case 2:
RE_val--;
break;
case 3:
break;
}
break;
case 1:
switch (RE_tmp) {
case 0:
RE_val--;
break;
case 1:
break;
case 2:
break;
case 3:
RE_val++;
break;
}
break;
case 2:
switch (RE_tmp) {
case 0:
RE_val++;
break;
case 1:
break;
case 2:
break;
case 3:
RE_val--;
break;
}
break;
case 3:
switch (RE_tmp) {
case 0:
break;
case 1:
RE_val--;
break;
case 2:
RE_val++;
break;
case 3:
break;
}
break;
}
RE_dat = RE_tmp;
}
}
//**********************************************************************
void main()
{
static unsigned char buf[20];
static int length;
//
OSCCON = 0b01110000; // クロックは8Mhz
CMCON = 0b00000111; // コンパレータは使用しない。
// アナログの設定
ANSEL = 0b00000000; // A/D変換は使用しない。
// ポートの設定
TRISA = 0b10111100;
TRISB = 0b00000011;
OPTION_REG.F7 = 0; // PORTBをプルアップする。
// CCPの設定
PIE1.CCP1IE = 1;
PIR1.CCP1IF = 0;
CCP1CON = 0b00001011;
CCPR1L = 0xD0; // 0.001sec...(1÷8000000)*4*2000
CCPR1H = 0x07;
// TIMER1の設定
PIE1.TMR1IE = 0;
PIR1.TMR1IF = 0;
TMR1L = 0;
TMR1H = 0;
T1CON.T1CKPS0 = 0;
T1CON.T1CKPS1 = 0;
T1CON.TMR1ON = 1;
// 変数の初期化
RE_dat = 0;
RE_val = 0;
// LCD(液晶モニタ)の初期化
Lcd_Custom_Config(&PORTB,4,5,6,7,&PORTA,1,0,6);
Lcd_Custom_Cmd(LCD_CURSOR_OFF);
Lcd_Custom_Out(1, 1, "MapMeter V1");
// 割り込み(全体)の設定
INTCON.PEIE = 1;
INTCON.GIE = 1;
//
while(1) {
//長さの換算
length = (22.0 / 48.0) * (float)RE_val * 3.1415926535897932384626433832795;
//長さの表示
IntToStr(length, buf);
Lcd_Custom_Out(2, 1, buf);
Lcd_Custom_Out(2, 7, "mm");
//カウント値の表示
IntToStr(RE_val, buf);
Lcd_Custom_Out(2, 10, buf);
//スリープ(100msec)
Delay_ms(100);
//ゼロクリア
if (SW0 == 0) {
RE_val = 0;
Lcd_Custom_Out(2, 1, " ");
}
}
}
//**********************************************************************
===== 動作確認 =====
いつものブレッドボードで確認してみました。
左側の黄色のスイッチは、ゼロクリア用です。
{{:imgpaste:202004:htmikan-20200429-205656.png?500}}
ロータリエンコーダを取り付けた基板を手で持って転がします。
ここはもう少し工夫したいところですね。
{{:imgpaste:202004:htmikan-20200429-205749.png?500}}
30cmの物差しを測ってみました。まあまあの精度です。
{{:imgpaste:202004:htmikan-20200429-205807.png?500}}
如何ですか?
ロータリエンコーダも工夫次第でいろいろな使い方が出来ますね ^_^
このページは稲崎様の閉鎖したHPのコピーで、著作権は稲崎様にあります。[[elechobby:picdic:picdic|詳細]]
This page is a copy of Mr. Inasaki's closed website, and the copyright is held by him.[[elechobby:picdic:picdic|Details]]