試作したタッチセンサ

導入編 で試作タッチパッドの動作確認を Delta-G 氏 製作の R4_Touch を使って行い、また 基本編 では CTSU 計測回路 の原理を紐解いてきましたが、日によってタッチ判定の閾値が微妙にズレて反応しなくなるという問題に遭遇しました。

おそらく気温や湿度、僕の指の静電容量変化が原因と思われますが、何らかの較正(=計器類の狂い・精度を、標準器と比べて正すこと)の必要性を感じた次第です。

僕としてはこの較正を、静的または動的な キャリブレーション と呼びたいのですが、ルネサスでは チューニング と呼び(名前はどうでも良いですが…)、しっかり対策が準備されています。が、e² studio やら何やらが基本なので、Arduino 環境では工夫が必要です。

幸い僕らには R4_Touch という優れたライブラリがあるので、これを使って安定動作を目指すのが今回のテーマです。

まずは結果から

以下の資料を参照し、試験的に作成したキャリブレーションの結果を示します。

  1. Renesas RA4M1グループ ユーザーズマニュアル ハードウェア編
  2. 静電容量センサマイコン 静電容量タッチ ノイズイミュニティガイド
  3. 静電容量センサマイコン 静電容量タッチ導入ガイド
  4. 静電容量センサマイコン アドバンスドモード(高度な設定)パラメータガイド
  5. RAファミリ 静電容量タッチ ソフトウェアフィルタ サンプルプログラム

図1 がキャリブレーション前の gif 動画で、R4_Touch デフォルトのパラメータを使用した動作例です(シリアルプロッタ は何気に便利ですね)。ピコピコと山が立っているところがタッチした瞬間です。見た通り、6個のスイッチの非タッチ状態(ベースライン)が異なります。

Delta-G 氏 の名誉のために言っておきますが、パラメータが悪い訳ではなく、よく実験をした上で、大抵のケースに対応できるであろう値が設定されています。)

一方 図2 のキャリブレーション後では、非タッチ状態のベースラインがほぼ揃い、閾値を1つにすることができました。暑い日でも雨でジトジトした日でも、安定して動作しています。

図1 キャリブレーション前
図1 キャリブレーション前
図2 キャリブレーション後
図2 キャリブレーション後

タッチ判定処理の概要

処理フローの全体像

図3資料5 から引用した全体像を示します。企業としては当たり前のことなのでしょうが、センサ形状やら使用環境やら、およそ商品開発に必要そうなツールやソフトウェアが準備されています。きっとこれらを研究・開発した人達がいるのでしょう、頭が下がります :100:

静電容量式タッチセンサの処理フローと CTSU ソフトウェア群
図3 静電容量式タッチセンサの処理フローと CTSU ソフトウェア群

また 資料4 には、表1 に示す通り、ルネサスが提供するツールを用いて調整できるパラメータが示されています(UNO R4 では設定できないパラメータは除外してあります)。

表中で ハイライトした行 は、CTSU ドライバ(つまり R4_Touch)が扱うべきパラメータで、今回の較正対象です。残りはアプリケーションで扱うべきパラメータですね。

CTSU パラメータ 自動チューニング 手動チューニング 高度なチューニング
計測(センサ駆動パルス)周波数 ✔︎
ICO 電流オフセット量 ✔︎
タッチ判定閾値 ✔︎
ヒステリシス ✔︎
ドリフト補正間隔 ✔︎
長押しキャンセルのサイクル ✔︎
ポジティブ・ノイズフィルタのサイクル ✔︎
ネガティブ・ノイズフィルタのサイクル ✔︎
移動平均フィルタの深度 ✔︎
計測回数 ✔︎
オフセットチューニング目標値 ✔︎
表1 CTSU パラメータと調整手法の位置付け

試験的キャリブレーション手法

資料3資料4 を元に、今回実施した「セルフキャリブレーション」および「タッチ判定閾値のチューニング」に関する処理フローを 図4 に示します。

図4 キャリブレーション/チューニングと調整パラメータ
図4 キャリブレーション/チューニングと調整パラメータ

それぞれを順番に見ていくことにします。

寄生容量の計測

図3 では、最初が「静電容量計測」となってますが、絶対値を測るわけではなく、非タッチ時の寄生容量とタッチ時の静電容量の差を計測します。で、その「容量」はというと、図5 に示す スイッチトキャパシタ の原理を用いて、回路に流れる電流を計測します。

必然的に、スイッチトキャパシタに印加する「センサ駆動パルス」の周波数を適切に設定しなければなりません。何故なら、計測する静電容量が大きい場合、充放電のサイクルが短いと、放電し切らないうちに充電することになり、計測値に誤差が生じるからです。

ところが、その具体的手法や評価基準に関する記述が見当たりません。下記表を元にルネサス製のツールが「最適値を設定する」か「高度なチューニングで設定する」との記述があるだけです。きっとルネサスのノウハウなのでしょう。

  計測(センサ駆動パルス)周波数 計測回数 計測時間 [μs]
CTSU(RX130 の例) 4.0 MHz 8 526
^ 2.0 MHz 4 ^
^ 1.0 MHz 2 ^
^ 0.5 MHz 1 ^

ではどうしたかと言うと、「オフセットチューニング目標値」に対する「ターゲット値」なるものが示されているので、計測値が、デフォルトとされる「37.5%」に対する「15360」に最も近くなる「計測(センサ駆動パルス)周波数」と「計測回数」の組み合わせを探索することにしました。

オフセットチューニング目標値 ターゲット値
25.0% 10240
30.0% 12288
35.0% 14336
37.5% 15360
40.0% 16384
45.0% 18432
50.0% 20480

ここではプログラムを見るより、探索処理が出力するデバッグ情報の方がイメージが湧き易いと思うので、以下に説明を試みます。まずは記号の説明です。

記号 説明
SNUM CSTS パラメータのうち、計測回数 を表します。
SPDA 計測(センサ駆動パルス)周波数 をベースクロックの分周比で表したものです。ベースクロックを周辺回路クロック PCLKB(24MHz)に設定した場合、例えば分周比「2」は 1/6、即ち 4MHz を表します。以降分周比が「1」増える毎に 1/81/10、… と続きます。
RC リファレンスカウンタを意味しますが、探索処理では計測レンジの上限値を表しています。
SC センサカウンタ、即ち計測された静電容量に相当します。

また 資料4 から次の制約条件を読み取りました。

  • センサカウンタ SC と計測範囲の上限値 RC はオーバーフローしてはならない
  • センサカウンタ SC は計測範囲の上限値 RC を超えてはならない
  • 計測範囲の上限値 RC は、100% のターゲット値(40960)より広くなければならない

この制約条件の元に、センサカウンタ SCターゲット値の 15360 に最も近くなる SNUMSPDA の組み合わせを探索することとしています。

以下は、あるタッチ電極に対する探索結果です。3つの候補(target candidate)のうち、最後の 計測回数=1計測(センサ駆動パルス)周波数=16 が解として求まりました。

SNUM = 8, SDPA =  2, RC = 58979, SC = 65535 --> overflow
SNUM = 4, SDPA =  2, RC = 29488, SC = 46677 --> SC: out of range
SNUM = 4, SDPA =  3, RC = 39322, SC = 52285 --> SC: out of range
SNUM = 4, SDPA =  4, RC = 49156, SC = 55369 --> SC: out of range
SNUM = 4, SDPA =  5, RC = 58989, SC = 57460 --> target candidate
SNUM = 4, SDPA =  6, RC = 65535, SC = 59027 --> overflow
SNUM = 2, SDPA =  2, RC = 14743, SC = 23334 --> SC: out of range
SNUM = 2, SDPA =  3, RC = 19663, SC = 26164 --> SC: out of range
SNUM = 2, SDPA =  4, RC = 24579, SC = 27676 --> SC: out of range
SNUM = 2, SDPA =  5, RC = 29494, SC = 28711 --> RC: narrow range
SNUM = 2, SDPA =  6, RC = 34416, SC = 29514 --> RC: narrow range
SNUM = 2, SDPA =  7, RC = 39316, SC = 30128 --> RC: narrow range
SNUM = 2, SDPA =  8, RC = 44254, SC = 30679 --> target candidate
SNUM = 2, SDPA =  9, RC = 49160, SC = 31144 --> target overshoot
SNUM = 1, SDPA =  2, RC =  7365, SC = 11657 --> SC: out of range
SNUM = 1, SDPA =  3, RC =  9824, SC = 13090 --> SC: out of range
SNUM = 1, SDPA =  4, RC = 12292, SC = 13862 --> SC: out of range
SNUM = 1, SDPA =  5, RC = 14752, SC = 14359 --> RC: narrow range
SNUM = 1, SDPA =  6, RC = 17211, SC = 14750 --> RC: narrow range
SNUM = 1, SDPA =  7, RC = 19669, SC = 15079 --> RC: narrow range
SNUM = 1, SDPA =  8, RC = 22128, SC = 15348 --> RC: narrow range
SNUM = 1, SDPA =  9, RC = 24582, SC = 15584 --> RC: narrow range
SNUM = 1, SDPA = 10, RC = 27035, SC = 15741 --> RC: narrow range
SNUM = 1, SDPA = 11, RC = 29497, SC = 15918 --> RC: narrow range
SNUM = 1, SDPA = 12, RC = 31963, SC = 16085 --> RC: narrow range
SNUM = 1, SDPA = 13, RC = 34415, SC = 16240 --> RC: narrow range
SNUM = 1, SDPA = 14, RC = 36879, SC = 16327 --> RC: narrow range
SNUM = 1, SDPA = 15, RC = 39341, SC = 16483 --> RC: narrow range
SNUM = 1, SDPA = 16, RC = 41796, SC = 16566 --> target candidate
SNUM = 1, SDPA = 17, RC = 44231, SC = 16689 --> target overshoot
Number of Measurements (CTSUSO0.CTSUSNUM): 1
Sensor Drive Pulse (CTSUSO1.CTSUSDPA): 16

う〜ん、これでも分かり難いですネ。

オフセットチューニング

そもそも「オフセット」とは何なのか、ハードウェアマニュアル資料4 を読んでいて、最も分かり難かったのがこのパートです。図5図6 の僕の解釈は、次のようになります。

電源からの I1 に比例した電流が、電流ミラー回路を通じて Iout として出力され、ICO(電流制御発振器)で変換されたパルスがセンサカウンタ SC として計測される。

一方、実際の静電容量は、スイッチトキャパシタにセンサ駆動パルスを印加する DAC からの電流 I2 も流れ込んで計測されるため、この影響を排除する必要がある。

つまり「ICO の制御電流 Iout で補正してやろう」という魂胆だと解釈したワケです。この手の補正をハードで処理するかソフトでやるかは、ありがちな選択肢だと思います。

図5 CTSU 計測回路
図5 CTSU 計測回路
図6 自己容量方式のオフセットチューニング処理
図6 自己容量方式のオフセットチューニング処理

と言うことで、本パートのデバッグ出力を示します。ターゲット値の 15360 とセンサカウンタ SC との差 diff が最小となる offsetICO 電流オフセット量 として決定しています。

offset: 0, sensor count: 16687, diff: 1327
offset: 1, sensor count: 16492, diff: 1132
offset: 2, sensor count: 16305, diff: 945
offset: 3, sensor count: 16119, diff: 759
offset: 4, sensor count: 15960, diff: 600
offset: 5, sensor count: 15765, diff: 405
offset: 6, sensor count: 15596, diff: 236
offset: 7, sensor count: 15420, diff: 60
offset: 8, sensor count: 15237, diff: 123
Sensor offset (CTSUSO0.CTSUSO): 7

また 資料4 には、この想定が成り立つ条件として以下の記述があり、念のため確認しました。

計測値は、電流制御発振器(ICO)の出力リニアリティ特性の良い範囲に収まるようにオフセットチューニング目標値を調整する必要があります。

ICO リファレンスカウンタ特性
図7 ICO リファレンスカウンタ特性

図7 は、ICO リファレンスカウンタの特性を測定したグラフです。もう一方のセンサカウンタも、回路的にはほぼ同じ特性を持つと考えて良いかと思います。

ただ、このグラフをもって「出力リニアリティ特性の良い範囲に収まる」と判断して良いかは、定かではありません…

さて、試作したタッチパッドの6個のタッチ電極に、上記処理を施した結果を示します。各電極で offset が働き、冒頭の 図2 で示した通り、非タッチ状態での計測結果(ベースライン)が、ほぼ ターゲット値の 15360 付近に揃う結果となりました。メデタシ、メデタシ。

pin:  9, div: 16, gain: 0, ref_current: 0, offset: 13, count: 1
pin:  8, div: 16, gain: 0, ref_current: 0, offset: 14, count: 1
pin: 15, div: 16, gain: 0, ref_current: 0, offset: 33, count: 1
pin: 16, div: 16, gain: 0, ref_current: 0, offset: 35, count: 1
pin:  3, div: 16, gain: 0, ref_current: 0, offset:  7, count: 1
pin:  2, div: 16, gain: 0, ref_current: 0, offset:  0, count: 1

感度計測 〜 タッチ判定閾値決定

今回は、ほぼ全てのタッチ電極特性が揃ったのをイイことに、ターゲット値の 15360 に適当なゲタを履かせて閾値としました。しかし本来は、非タッチ時とタッチ時の計測結果を統計処理するなどして、それぞれのタッチ電極ごとに閾値を決めるべきです。

また実用上は、タッチパッドに汚れが付着したり、一時的に水滴が付くなど、ベースラインが変化する可能性もあるので、ドリフト補正も必要です。

今のところタッチ判定に影響を与えるほどではありませんが、油性マジックで描いた囲み数字がかすれてくる程度にペタペタと触っているためか(手垢が付着!?)、現にドリフトが発生し始めています。

タッチ電極ごとに閾値を持たせれば、移動平均や適当な時定数でフィルタ処理するなど、ドリフト補正の実装も容易だと思います。

サンプルプログラム

今回作成のソースコードを GitHub に上げました。「Arduino UNO R4の周辺回路レジスタをモニターするプログラム」で作成した PeripheralMonitor が組み込んであったりと、少々分かり難いところがあるかも知れませんが、紹介しなかった CTSU ドライバでの「移動平均」も組み込んであるので、よかったら覗いてみてください。

おことわり

R4_Touch には 自動チューニングのサンプル が添付されていますが、UNO R4 FiWi からのコマンド入力がうまくいかなかったり、算出されたパラメータやタッチ判定の閾値がイマイチだったりと、現時点のバージョンは、僕が試作したパッドと相性が良くありません。原因は CTSU 仕様の解釈の違いにあります。

とは言え、今回紹介した僕の手法が、他の人にとって合わない可能性もあります。Delta-G 氏の言葉 を借りれば、これで「間違いない」とか、「最善である」とか、「正解である」などと主張するつもりは毛頭ありません。

質問や疑問、ご提案などあれば、コメントを頂ければと思いますし、フォーラムでの議論 にご参加頂ければ、なお良いと思います :dizzy:

最後にちょっとだけ注意事項を…

資料2 には、TS 端子とタッチ電極の間にダンピング抵抗を接続することが推奨されています。一方 Minima の回路図WiFi の回路図 を見ると、Love ピンは直接 MCU に接続されていています。無闇に触って静電気で MCU にダメージを与えないよう、注意しましょう!