LoginSignup
0
0

Arduino Uno R4でロータリーエンコーダポジションをハードウェア計測

Last updated at Posted at 2024-01-08

初めに

ABZ相を持つロータリーエンコーダの回転角をArduino Uno R4でハードウェア計測するための方法を残します。Z相によるカウントリセットも可能です。

Arduino UNO R4 MinimaのMPUはRA4M1(R7FA4M1AB3CFM)です。
Renesasのサイトで「Renesas RA4M1グループ ユーザーズマニュアル ハードウェア編」をダウンロードしてください。
2024/01時点でRev.1.10でした。

開発にはArduinoIDE Ver2.2.1を使っています。

ハードウェア的な接続設定

エンコーダのA相をD3ピン、B相をD2ピン、Z相をD12ピンに入力します。ピンの選択には一定の制限があるので後ほど解説します。
当然ですがエンコーダとArduinoのGNDを接続してください。UNO R4はR3以前に比べて電源入力範囲が広がったため、電源も共用可能なケースが多いと思います。

低消費電力モードの解除

リセット状態ではタイマ(GPT、General Purpose Timer)とイベントリンクコントローラ(ELC)は無効になっています。
モジュールストップコントロールレジスタD(MSTPCRD)でGPTを有効にします。なお、本記事では32bitカウンタを使います。

  R_MSTP->MSTPCRD_b.MSTPD5 = 0; // 32bitのカウンタ2つ
  R_MSTP->MSTPCRD_b.MSTPD6 = 0; // 16bitのカウンタ6つ

モジュールストップコントロールレジスタC(MSTPCRC)でELCを有効にします。

  R_MSTP->MSTPCRC_b.MSTPC14 = 0;

入力ピンとタイマの設定

ピン及びタイマを設定します。最初にタイマのカウントを停止します。ただし、リセット時0なので省略可能です。

  R_GPT1->GTCR_b.CST = 0;

GPIOピンの汎用設定

GPIOピンをデジタル入力・内蔵プルアップに設定します。まず最初に入力に使うピンとMPUの内部ポートの関係を特定します。Arduino Uno R4のpinout画像をArduino公式サイトから引用します。
4c4417b7-a3f3-4f5d-938f-210e902d979b.png
入力に使うピンの横にあるP+3桁の数字に着目してください。百の桁がm、十の桁以下がnです。D3ピンを入力に使う場合、P104なのでm=1かつn=4です。P105とP110についても同様です。
PmnPFSレジスタを設定します。PDRでデジタル入力を指定、PCRでプルアップ有効を指定します。

  int m=1;
  int n=4;
  R_PFS->PORT[m].PIN[n].PmnPFS_b.PDR = 0;
  R_PFS->PORT[m].PIN[n].PmnPFS_b.PCR = 1;

タイマとGPIOの関係を設定

更に、A相とB相についてはタイマの一部として設定します。PMRをセットして周辺機能用のポートとして使用します。PSELについては0b11(GPT)を設定します。

  R_PFS->PORT[m].PIN[n].PmnPFS_b.PMR = 1;
  R_PFS->PORT[m].PIN[n].PmnPFS_b.PSEL = 0b11;

GPTの入力として使うピンについて

GPTに使えるピンには制限があり、マニュアル19.6の「入出力端子機能のレジスタ設定」を見ながら進めます。32bitタイマは2つあり、GP320とGP321と名前がついています。ここではGP321を使います。
GP321はGTIOC1AとGTIOC1Bという内部的な入力端子を持ち、GTIOC1Aはマニュアル22.1の表「GPTの入出力端子」に記載の通りGPIOのP105,P109,P405に接続されています。P105はD2、P109はD11、P405は無接続です。つまり、GP321タイマがA相の入力端子とて使えるのはD2とD11のみです。同様にB相はD3とD12に限定されます。
Z相についても制限があるので、ELC機能の項で説明します。

タイマの設定

A相とB相を使って位相計数機能を設定します。マニュアル22.3.10に詳細があり、この通りに設定すればOKです。ここでは位相計数モード1を用います。GTUPSRとGTDNSRは逆に設定するとカウント方向を逆にできます。組み付けや配線に合わせて選択してください。

  R_GPT1->GTUPSR = 0x6900;
  R_GPT1->GTDNSR = 0x9600;

GTPRにカウンタの最大値を入力します。ここではGPT321を使っているので32bitの最大値を設定します。

  R_GPT1->GTPR = 0xffffffff;

CSELCAをセットすることにより、Z相の入力で発生するELC_GPTAイベントでカウンタ値(GTCNT)を0にクリアする設定とします。ELC_GPTAはカウンタを動作開始させた後で設定するので、先にカウンタを開始するためにCSTを1にセットします。

  R_GPT1->GTCSR_b.CSELCA = 1 // ELS_GPTAでカウントをクリアする
  R_GPT1->GTCR_b.CST = 1;

ELCの設定

RA4M1はイベント駆動が可能なので、Z相によるカウンタクリアを実現するために割り込みイベント発生⇒カウンタクリアという2手順に分けて実施します。図解すると次のイメージです。

まずGPIOと割り込み番号の関係を調べた後、ELCの設定を実施した後でZ相GPIOを設定します。

GPIOからIRQを調べる

ELCで使う割り込み番号(IRQ)はGPIOのピンから決まります。D12の場合はP110なので、表19.7「入出力端子機能のレジスタ設定(ポート1)」を見るとP110はIRQ3に対応します。IRQが振られていないピンもあり、そのピンはELCに使えません。

ELCリンクの設定とELC起動

IRQ番号をGPT(A)およびELS_GPTAに相当するELSR0のHAに設定した後、ELCONを1にセットしてELCを有効にします。ただしIRQ番号とHAの設定値は1ずれます。

  R_ELC->ELSR[0].HA = 0x04; // IRQは0始まりだが、ELSRは0が停止を表すため1ずれる
  R_ELC->ELCR_b.ELCON = 1;

GPIOへの割り込み設定

GPIO側で割り込みを有効にするため、P110のPmnPFSのISELに1をセットします。

  R_PFS->PORT[1].PIN[10].PmnPFS_b.ISEL = 1;

以上で設定を終わります。お疲れさまでした。

肝心のカウント値読み出し方

GTCNTがカウント値にあたります。回転方向によっては負のオーバーフローを起こすため、longまたはsigned longにキャストすると楽です。位相計数モード1では信号は4逓倍されることに注意してください。

(signed long)R_GPT1->GTCNT / 500.0 * 4; // 一回転500パルスのエンコーダで4逓倍

最後に

低消費電力機能は罠だと思います。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0