JH7UBCブログ

アマチュア無線 電子工作 家庭菜園など趣味のブログです

ATtiny402 ロータリーエンコーダテスト

2023-08-20 11:15:42 | ATtiny
 ATtiny402でロータリーエンコーダーを使うテストをします。

 Arduino UNOなどでは、Rotary.hというライブラリを利用することができます。確認はしていないのですが、ライブラリでは割り込みを使っているのではと考えています。

 ATtiny402では、ピン状態割り込みが使えないようなので、割り込みを使わない方法でロータリーエンコーダの制御プログラムを組みました。このプログラムは「wsnakのブログ」のロータリーエンコーダの記事のプログラムを利用させていただきました。ありがとうございます。

 今回のテストでは、ロータリーエンコーダはAmazonで購入した安価なものを使い、ロータリーエンコーダの回転方向が時計回りの時にカウントアップ、反時計回りの時にカウントダウンするようにして、カウント値をLCD1602に表示するようにしました。

 テストした回路図です。ロータリーエンコーダのA端子をD0(PA6)にB端子をD1(PA7)に接続し、それぞれを10KΩでプルアップします。
 

 ロータリーエンコーダの回転方向の判定方法を簡単に説明します。
 下の図のように、ロータリーエンコーダのA,Bの値を読み取り、Aをbit1、Bをbit0としてCurDatの値に加えます。A,Bの値が変わったらCurDatの値を左に2ビットシフトし、A,Bの値を加えます。エンコーダの1クリックで、A,Bの値が4回変わりますので、その都度同じ操作をします。



 1クリックが終わったとき、エンコーダが時計回りの時、CurDatの値は0x4Bに、反時計回りの時は0x87になりますので、この値で回転方向が判定できます。

 スケッチです。
 機械的なロータリーエンコーダを使う場合、チャタリング対策が必要です。
 スケッチでは、その対策をソフトで行っています。ひとつは、入力が安定するまで1msのdelayを入れました。それから、入力が同じかどうかmatchCntでカウントして、2回以上一致したら処理するようにしています。wsnackさんは5回以上の一致を確認していますが、1msのdelayを入れたので2回で十分のようです。
---------------------------------------------------
/*
    ATtiny402 Rotary Encoder test
    2023.8.19
    JH7UBC Keiji Hata
*/

#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 16, 2);

//Rotary Encoder関係定義
#define REA 0 //D0
#define REB 1 //D1
byte curDat;
byte befDat = 0;
byte rotDir = 0;
int Count = 0;
byte inputMatch;
byte matchCnt;
byte rotPat = 0;

void setup() {
   pinMode(REA, INPUT);
   pinMode(REB, INPUT);
  //ロータリーエンコーダ初期値設定
   curDat = 0;
   if(digitalRead(REA)){
     befDat |= 2;
  }
  if (digitalRead(REB)){
     befDat |= 1;
  }
   //LCD初期設定と初期画面表示
   lcd.init();
   lcd.backlight();
   lcd.clear();
   lcd.setCursor(0,0);
   lcd.print("Rotary Encoder");
   lcd.setCursor(0,1);
   lcd.print(Count);
}

//Rotary Encoderの回転方向判定
signed char CheckEnc(byte dat) {
   rotPat <<= 2;//左に2bitシフト
   rotPat |= (dat & 0x03);//datの下位2bitを加える
  if (rotPat == 0x4B) {
     return 1; //時計回り(CW))
  } else if (rotPat == 0x87) {
     return -1; //反時計回り(CCW)
  } else {
     return 0; //どちらでもない
  }
}

void loop() {
     signed char val;
     curDat = 0;
     if (digitalRead(REA)) {
       curDat |= 2;
    }
     if (digitalRead(REB)) {
       curDat |= 1;
    }
     if (befDat == curDat) {
       //befDatとcurDatが一致したときの処理
       if (!inputMatch) {
         matchCnt++;
         if (matchCnt >= 2) { //2回以上一致したらフラッグを立てる
           inputMatch = 1;
           val = CheckEnc(curDat);
           if (val != 0) {
             Count += val;
             lcd.setCursor(0, 1);
             lcd.print("    ");
             lcd.setCursor(0, 1);
             lcd.print(Count);
           }
         }
       }
    } else {
       //befDatとcuDatが一致しなかった時の処理
       delay(1);//1ms待つ(チャタリング対策)
       befDat = curDat;
       matchCnt = 0;
       inputMatch = 0;
    }
}
---------------------------------------------------
ブレッドボードです。ロータリーエンコーダを回すごとに科カウントアップ、カウントダウンされます。このプログラムは、クリックの取りこぼしも少なく、けっこう優秀です。



最新の画像もっと見る

コメントを投稿