Arduino UNO R4 静電容量式タッチセンシングユニット(CTSU) - 基本編
前回の「導入編」 では、CTSU ライブラリの R4_Touch でとりあえず試作タッチスイッチを動作させました。ただ、空中配線のせいもあると思いますが、日によって微妙にタッチの反応速度が異なり、安定して動作させるには判定閾値の調整が必要なことが分かりました。
そこで今回は、Renesas RA4M1グループ ユーザーズマニュアル ハードウェア編 の P.1418 「41. 静電容量式タッチセンシングユニット(CTSU)」を紐解き、キャリブレーション手法の検討につなげたいと思います。幸い R4_Touch は、マニュアルに沿って作られているので、仕様と実装を突き合わせながら、CTSU の使い方が学習できると思います。
また今回を「基本編」としたのは、CTSU がサポートする3つの計測モードのうち、実用上もっとも基本的な「自己容量自己容量マルチスキャンモード」の紐解きだからです。
他の計測モードとして、マトリックス状に配置した2つの電極間の差を取ることで寄生容量をキャンセルする「相互容量方式」があり、その紐解きを「応用編」としたいのですが、結構ムズそうで、辿り着けるかどうか分かりません
CTSU 動作原理の復習
ここでは CTSU 計測回路の図だけを示すので、詳細は マニュアル の P.1444「41.3 動作説明」を読むか、導入編の CTSU の動作原理 を読み返してください。
ノイズ除去について
人がタッチ電極に触れた際、コモンモードノイズ が回り込み、駆動パルスによるタッチ電極への充放電周波数とノイズの周波数が近い場合、計測に影響を与える可能性があります。
このノイズの影響を減らすため、MCU には「高域ノイズ低減機能(スペクトラム拡散機能)」が組み込まれてます。これをあえて利用しないという手はないでしょう。
詳しくは、静電容量タッチ ノイズイミュニティガイド を読むと、勉強になると思います。
計測のフロー
マニュアル では、ハードウェアに視点を置き、処理フロー、状態遷移、タイミングチャートの3つで仕様が記述されています。それゆえソフトウェア仕様に落とす前段階として、それら相互の関係を意識しながら、それぞれを噛み砕いて再表現してみました。
何よりまずは自分自身の理解のため、そして誰かの役にも立つことを願って…
CTSU 初期設定フロー
「CTSUCR1.CTSUPON = 1」などの表現は抜きに、CTSU 計測回路にとっての意味や目的を確認しながらフローを追いかけてみました。
flowchart TB A["1. TSCAP 端子外付け
コンデンサを放電"] --> B["2. TS 端子 I/O ポート設定"] --> C["3. CTSU 入力クロック許可"] --> D["4. CTSU 電源設定"] --> E["5. CTSU ベースClock設定"] --> F["6. CTSU 電源オン"] --> G["7. 安定待ち"] --> H(["停止状態/計測開始待ち"])
-
TSCAP 端子を汎用 I/O ポートに設定し、一定期間 Low レベルにすることで外付けされたデカップリングコンデンサに溜まった電荷を放電します。
-
TS 端子を、ポート mn 端子機能選択レジスタで周辺機能用の入出力ポートに設定します。
-
CTSU のモジュールストップ状態を解除し、電源とクロックの供給すれば CTSU が動き出せる状態にします。
-
タッチ電極の静電容量に応じた基準電圧を印加するため、 CTSU の電源動作モードと電源能力を設定します。
-
スイッチトキャパシタと ICO の動作に必要な、CTSU のベースクロックを設定します。
-
TSCAP 接続 SW をオンし電源と繋げることで、外付けしたデカップリングコンデンサの充電を開始します。
-
タッチ電極に安定した基準電圧を印加できるよう、TSCAP 端子に外付けしたデカップリングコンデンサの充電完了を待ちます。
動作完了フロー
次章の「状態遷移」上は、Status 1
から Status 0
に遷移した際に実行すべきアクションかと思います。
flowchart TB A[1. CTSU 電源オフ] --> B[2. モジュールスタンバイをオン]
-
CTSU の電源をオフにし、TSCAP 接続 SW を切断します。
-
CSTU をモジュールストップ状態に移行させます。
状態遷移
CTSU ステータスレジスタ(CTSUST)には、計測回路の内部状態が書き込まれます(図の見通し良くするため「相互容量フルスキャンモード」の遷移は除外してあります)。
ソフトウェア上は、処理の過程でステータスをチェックすること以外、あまり意識する必要はなく、強調した処理 を実行するだけです。
flowchart TB S0([Status 0
停止状態/計測開始待ち]) S1([Status 1
計測チャネルの更新/計測終了判定]) S2([Status 2
センサ駆動パルス設定待ち]) S3([Status 3
センサ駆動パルス出力開始/センサ安定待ち区間]) S4([Status 4
計測開始/計測区間]) S5([Status 5
計測完了]) S0 -- ソフトウェアまたは外部トリガで 計測開始を指示 --> S1 S1 -- 次に計測すべきチャネルがなく測定終了 --> S0 S1 -- 計測チャネルの設定要求割り込み --> S2 %%S1 -- 相互容量フルスキャンモードで計測2回目の場合 --> S3 S2 -- 計測チャネルを設定(→ 完了後 IOC クロックが動作) --> S3 S3 -- センサ安定時間が経過 --> S4 S4 -- 所定の計測時間が経過 --> S5 S5 -- 動作クロックが2クロック経過 --> S1
自己容量マルチスキャンモードの動作
自己容量シングルスキャンモードでは、任意の1チャネルの静電容量を計測します。「4. CTSU 計測開始」後は、ICU(Interrupt Controller Unit)が管理する3つの割り込みにより計測処理が進むので、アプリケーションは、結果が書き込まれた SRAM 上のデータを非同期に読み込み、タッチを判定することができます。
flowchart TD A([1. 初期設定]) --> B[2. 割り込み動作設定
(DTC または ICU)] --> C[3. CTSUレジスタ設定] -- 電源安定時間を経過 --> E[4. CTSU 計測開始] --> F([5. CTSU 計測動作開始]) -- チャネル設定要求割り込み 発生 --> H H[6. 計測チャネル設定] -- 結果読み出し要求割り込み 発生 --> J J[7. 計測結果読み出し] -- 計測終了割り込み 発生 --> L L[8. タッチ判定処理]
-
「CTSU 初期設定フロー」完了後は
Status 0
状態となるところから始まります。 -
チャネル設定要求、結果読み出し要求、計測終了 の各割り込みに対し、予め SRAM ↔︎ レジスタ間の転送処理を定義したハンドラ関数を登録します。
-
CTSU 動作クロックと計測モード(自己容量マルチスキャンモード)、スイッチトキャパシタ、センサ安定待ち時間、計測チャネルの設定を行います。
-
CTSU コントロールレジスタ 0 の CTSU 計測動作開始ビットに1を書き込むことで計測を開始します。
-
計測回路は
Status 1
に遷移し、ソフトウェアは、チャネル設定要求割り込み(CTSU_CTSUWR)を待ちます。 -
計測回路は
Status 2
に遷移し、チャネル設定要求割り込み ハンドラが予め SRAM 上に設定されたチャネル設定を所定のレジスタに転送します。計測回路はStatus 3
に遷移し、センサの安定を待ちます。 -
計測回路は
Status 4
に遷移し、結果読み出し要求割り込み(CTSU_CTSURD)ハンドラが、ICO の計測結果データを SRAM に転送します。 -
全チャネルの計測が終了すると
Status 5
に遷移し、計測終了割り込み(CTSU_CTSUFN)が発生します。
割り込み処理について
マニュアル の P.1457「41.3.3.2 割り込み」には、CTSU の3つの割り込みに対する処理が示されています。これらの実装には、IRQManager クラス と DTC(Data Transfer Controller)の利用が必須です。また周辺モジュールで発生するイベントを CPU を介さずに別モジュールと接続する ELC(Event Link Controller)の知識も必要です。
しかし、残念なことに僕がこれらに習熟していないので、ここでは R4_Touch をコードリーディングした結果の概要紹介に留めたいと思います。
タッチピンの設定
Minima/WiFi のピン番号 を指定すると、以下の処理が実行されます。
- 対応する TS 端子を計測チャネルの登録
- CTSU 初期設定フローの実行
- 3つの CTSU 割り込みハンドラの登録(
initialize_CTSU()
) - 割り込み要因に対応する SRAM ↔︎ レジスタ間の転送設定(
initialize_DTC()
)
計測モードは「自己容量マルチスキャンモード」にハードコートされています。また必要な数だけピンを指定した後は、TouchSensor::start()
により計測を開始します。
チャネル設定要求割り込みハンドラ
initialize_DTC()
により、チャネル設定を格納した SRAM からレジスタへの Write
処理が設定されているため、対応する割り込み要因をクリアするだけの処理となっています。DTC を使わない場合は、チャネル設定を CTSUSSC、CTSUSO0、CTSUSO1 レジスタへ書き込むコードを記述します。
結果読み出し要求割り込みハンドラ
initialize_DTC()
により、計測結果を格納したレジスタから SRAM への Read
処理が設定されているため、対応する割り込み要因をクリアするだけの処理となっています。DTC を使わない場合は、2つの ICO カウンタ CTSUSC、CTSURC を読み出すコードを記述します。
計測終了割り込みハンドラ
割り込み要因をクリア、コールバック関数の実行、および次の計測動作開始を指示しています。タッチ判定はコールバック関数でも可能ですが、touchRead()
関数で SRAM に転送された計測結果を非同期に参照して行うことも可能です。
2つの ICO カウンタがオーバーフローした場合、CTSUST レジスタの CTSUSOVF ビットか CTSUROVF ビットが立つとの記述がありますが、そもそもキャリブレーション時にオーバーフローしないようパラメータを設定すべきなのだと思います。
R4_Touch による動作確認
Arduino IDE のソースコードデバッガを使い、コードをトレースするのも勉強になるのでアリですが、ここでは 導入編 で試作した回路の TS 端子をオシロスコープで、CTSU レジスタを PeripheralMonitor で観測した結果を示します。
オシロスコープは TS02
端子を観測しています。設定では TS 端子へのパルス駆動周波数は、周辺モジュールクロック PCLKB
(24MHz)の 32 分周(CTSUSDPA[4:0] = 15)、つまり 750KHz ですが、ノイズと同期しないようにランダムなパルスを出力する「スペクトラム拡散機能」をオンにしているため、結構ブレて観測されました。
その他の設定値は R4_Touch のデフォルト値にお任せしています。
設定項目 | 設定値 | レジスタ | ビット | 値 |
---|---|---|---|---|
ベースクロック | 24MHz(PCLKB を1分周) | CTSUCR1 | CTSUCLK[1:0] | 0x00 |
計測モード | 自己容量マルチスキャンモード | ^ | CTSUMD[1:0] | 0x01 |
同期ノイズ低減 計測時間 | 3(推奨設定値) | CTSUSDPRS | CTSUPRRATIO [3:0] | 0x03 |
^ 基本パルス数 | 62 パルス(推奨設定値) | ^ | CTSUPRMODE [1:0] | 0x02 |
^ 高域ノイズ低減機能 | ON | ^ | CTSUSOFF | 0x00 |
センサ安定待ち時間 | 0x10(推奨設定値) | CTSUSST | CTSUSST[7:0] | 0x10 |
センサオフセット | 電流オフセット量 0 | CTSUSO0 | CTSUSO[9:0] | 0x00 |
計測回数 | 1 | ^ | CTSUSNUM[5:0] | 0x00 |
リファレンス ICO 電流 | 電流オフセット量 0 | CTSUSO1 | CTSURICOA[7:0] | 0x00 |
センサ駆動パルス | 750KHz(ベースクロックの1/32) | ^ | CTSUSDPA[4:0] | 0x0F |
ICO ゲイン | ゲイン 100%(推奨設定値) | ^ | CTSUICOG[1:0] | 0x00 |
こうやって洗い出してみると、導入編の 検出原理に基づく CTSU のポイント で想定したパラメータでは足りませんでした
次回は…
ルネサスが提供する FSP には、CapTouch という モジュール と API、それにスライダーやパッド、ホイールなどの UI に対応したミドルウェアがサポートされていますが、Arduino 開発者が「いらねぇ」と思ったのでしょうか、残念ながら UNO R4 にはポーティングされていません(TrustZone とか、他にも載せて欲しい機能、ありますよね)。
e² studio 環境 では 静電容量式タッチセンサ対応開発支援ツール が使えて、前章で洗い出したパラメータの チューニングが可能 なようですが、幸いにも R4_Touch には Auto_Tune という自動チューニングの例題があるので、次回はこれを紐解いてみたいと思います。
ホント、Delta-G 氏 さまさまです