進捗ダイジェスト3週目
温度特性
zenaimさんとかはサーミスタ積んで温度補償していますとウリにしていますよね。他のキーボードでは都度キャリブレーションを行うからokのような感じもあります。
とにかく温度特性の取得と補償するかどうかは考えなくてはなりません。雑に想像するに常温~高くても40度はいかないだろうと想像しますがどうなんでしょ。
冷凍庫に放り込んだりヒーターを当てたりしながら、ホールセンサ及びスイッチのADC読み取り値時間変化を見てみたりしたのですが、、変わったり変わらなかったりなんもわからんとなったのでそのうちリベンジしたいと思います。
とはいえ恒温槽なんてないし、そもそもどこの温度を見るのか?ホールセンサならまだしもスイッチの中にある磁石に熱電対を当てることはできません。熱電対持ってないし。
何ともめんどくさそうな気がしているうえに最悪無視してもいいんじゃねという気がしています。
たとえばcal時のtop値と温度を保存しておいて、毎度top値に対してオフセットなりするだけでも良かったりしないかとか。
宿題です
ホールセンサ出力-押下量特性の取得
マイクロメータヘッドを買いました。使用用途が数式立てるためだけで、これしか使わないのでもったいないのですが必要だったので仕方なし。ところで磁力を測るのに使用するのはマイクロメータヘッドでよいんでしょうか。
買ったはいいもののマイクロメータ以外が何もないので急ごしらえな感じでいったん雑測定します。手元の範囲でもうちょい道具揃ったら再測定します。

最押し込みから0.05mm step, 7000点程度ADC値を取得し、平均とばらつきを見ています。ちまちま手動でマイクロメータを回し測っていきます。
底と天井のところは測定系とか色々適当なので裾引いていると思っていて、基本的には正規分布に沿っているとみてよいかなと思います。そうでなければ困る
平均を読み取り値として採用し、rangeがばらつき幅、6*stdが上下端切り落としたばらつき幅としました。外れ値らしい外れ値はないですが

L45測定値の平均値らを取り出し、底からの変位量でプロットしてみました。
averageを見ると距離に対して反比例のようなグラフをしています。底付近の方が磁力の減衰が少ないので高感度に傾きをとれています。
rangeとstdはおよそ一定で変化しています。距離、磁力に寄らずばらつきは一定とみてよさそうです。またこの測定環境においては、ADC読み取り値のばらつき幅は平均で36程度あり、電圧にして36/4095*3.3=0.03V程度幅を持っています。この幅分以下の値はふらふらばらつくので設定できないということですね。ぱっと思いつくのはホールセンサ出力にフィルタ入れたり、安定度の高いマイコンボードを使い対策とかでしょうか?

左軸青はADC読み取り値、右軸燈は0.05mmの変位量でADC読み取り値がどれだけ変化するか(感度)を表しています。ADC値/stepに変換しています
底からの変位0付近では0.05mmを変位させるとADC読み取り値は35程度変化します。閾値0.05mmを実現しようとしたとき、ばらつきが前後35以内に収まっていれば誤動作が起きなさそうでしょうか。
底からの変位2mm付近の中央では10程度の感度です。
天井付近では感度が3程度です。0.05mmを実現するためにはばらつきを3に抑えたいです。この時ばらつき36ですから無理ですね。

平均ばらつき度36であることから、ADC感度→どれだけ変位距離がぶれるのかをプロットしました。これから、底付近と天付近ではばらつきのインパクトが異なり底の方がばらつきによる必要なマージンは小さいです。
例えば底から2mmの位置で固定しているにもかかわらず、読み取り値が上下に0.1mm分ふらふらとばらつくことを示しています。そのためラピトリ値はこれより大きくしないと動かしていないのにon, offが勝手に入力されてしまいます。
このpicoでただ読み取るだけの環境では最悪値である上下0.35のマージンを入れた精度であればラピトリを実装できそうです。それくらいでも実用には問題ない気もします。現在ホールセンサにdrv5053を使用していますが、これをdrv5056にするだけで分解能分で倍はよくなりますから、加えてばらつきを抑えてやれば0.1の精度は特別なことをしなくても実現できそうな気がしてきました。

モデル式検討
モデル化というと仰々しいですが、2次の関数と連立方程式だけなので大したことなさそう。磁力⇔変位変換は非常に簡単な話であります。
先ほどのL45と同様に0.05mmずつボトムアウトから刻みホールセンサ出力を測定、をKOM, ZEN, JadeGamingの4種のスイッチについて行いまいした。この結果からスイッチのオンオフ判定やキャリブレーションに使用するためのモデル式を検討します。
余談ですが、ZENAIMのスイッチは極性がKS-20と同じN極下なので、プレートにちょっと細工すれば同様に使用できます。ただ磁力がKS20互換らより強いので、モノによってはホールセンサの検知範囲から外れてしまうかもしれません。私はZENスイッチにも対応できるように作りたいと思っています。
まずはどのような式にするのか決定する必要があります。ホールセンサはデータシートを見るとわかるように、磁束密度Bの変化に対してリニアに電圧値に変換され出力されます。
またこの比例定数は各ホールセンサの感度がデータシートに乗っていますからそれを参照します。drv5053caであれば[+23mV/mT]と記載があります。スイッチのスペックには基本的にガウス[Gs]で表記されていますが1mT=10Gsなので[+230mV/Gs]です。

$$ B\mbox(磁力) \propto Vout\mbox(ホールセンサ出力) $$
磁気スイッチのスペックなど見るとわかりますが磁束密度がそのままある位置における磁力の強さとして扱われているので、磁力と呼んでしまいます。
この磁力をホールセンサで電圧に変換し、それをマイコンのADCによって読み取った値を処理します。現在picoを使用してますが、ADCでは読み取った電圧を0~3.3Vの範囲を0~4095の12bitに変換し読み取りを行います。例えばADCで2000という値を読み取った場合ホールセンサの出力電圧は以下になります。
$$ Vout[V] = \frac{2000}{4095} * 3.3[V] = 1.6[V] $$
ですから当然ADC読み取り値も磁力に比例しています。
$$ B\mbox(磁力) \propto ADC $$
マイコンで読み取る値と磁力の関係がわかりましたので、スイッチの変位との関係も見てみます。
磁力と距離の関係を調べてみると、どうやら磁力は距離の二乗に反比例するようです。ホールセンサは磁力に対してリニアですが、肝心の距離特性はそうでないようです。めんどくさい、、
磁極のローレンツ力の式というのがあり下記のように表されるようです。磁極からの距離rの二乗に反比例しています。またベクトル量ですから傾くと磁力が変化するようです。スイッチを傾かせずに押し下げ、その直線状にホールセンサが水平に置かれることが理想というわけですね。
$$ B=\frac{\mu q_m}{4 \pi r^3}\overrightarrow{r} $$
スイッチの距離を磁力として取り出したいだけなので電磁気学なんて知ったこっちゃないです。とにかく下記のように表せるようです。
$$ B\mbox(磁力) \propto \frac{1}{r(磁極からの距離)^2} $$
ここで私がキャリブレーション時に使用できる距離という値は、スイッチのストロークだけとなります。磁極からの距離を想定したときに、基板の厚み、基板からスイッチ底までの距離、スイッチ底から磁石までの距離とよくわかりません。
とりあえず今回測定したように、スイッチ底打ちからの変位量を d [mm] としましょう。ストローク4mmのスイッチとすると、dは0~4の値を取ることになります。0の時ボトムアウトで、4の時トップアウトの状態になります。
また、モデル式に必要な磁極からの距離rというものを仮定して、そのための補正値を d0 [mm] と置きましょう。磁極からの距離を以下とします。
$$ \mbox{(磁極距離)} r = \mbox{(変位量)} d + \mbox{(補正値)}d_0 $$
実際に計算に使用したいのはADC読み取り値と変位量dですから、上の式にそれぞれ代入してみます。
$$ (B \propto ) ADC \propto \frac{1}{( d + d_0 )^2} ( =\frac{1}{r^2}) $$
多項式となると面倒ですが、この式を使えればとても簡単です。きっとそうに違いない。
比例定数a, 切片bとして、以下の式をモデルとして想定してみます。シンプルな一次式です。
$$ y=ax+b, (y=ADC, x=\frac{1}{( d + d_0 )^2} ) $$

また定数a, bについて考えると、傾きが大きいほど磁力が強くなるということですからaは磁石の磁力の強さを表していそうです。
bはx=0つまり磁極距離が無限大、スイッチが装着されていない何も検知していない状態ですから磁力0をホールセンサで読み取った値となりそうです。
実測から近似式
実際に実測値から近似式を作成し、モデル化を試みます。d0という便利な謎の補正値が吸収してくれるので、この時の変位量(0.005, 0.01, …)刻み幅がちゃんとしてればなんでもよいです。
今回初めて知りましたがエクセルは線形近似式をセルに打ち出せるのですね。[SLOPE()][INTERCEPT()]という関数を使用しa, bが求まります。
最小二乗法で線形近似式に実測をフィッティングしd0の値を得ます。グラフを見ると、いい感じにモデルに合っていそうです。
$$ y=a\frac{1}{( d + d_0 )^2}+b=\frac{10847}{( d + 2.88 )^2}+1221 $$

L45同様にKOM, ZEN, JGにも実施し近似式を求めました。近似式を求め使用することで、それぞれ異なるストロークと謎の磁極距離という問題が解消されます。任意のr=d+d0を代入すればよいですからね。

KS-20互換と呼ばれるスイッチは互換とはいうもののストロークも磁極距離も磁力もそれぞれ違うんだよなあと思いますが、こう見ると比較的似たような位置にいますね。ZENAIMスイッチは2倍ほど磁石自体の磁力強いことがわかります。これは実測だけでは磁極距離が含まれていないため正確にはわからないところです。ざっくりはわかりますけども。

余談ですがそれがユーザーにとり最適化はわかりませんが、ZENスイッチは非常に都合が良く素晴らしいと思います。磁力が強くSNが高い、ショートストロークで感度の高い場所のみを使える、種類がないため単純なキャリブレーションでよい。実のところZENスイッチであれば二乗に反比例などといわず、細かい変位におけるズレを妥協し線形近似してしまっても使う分には困らないし気づかないと思うのですよ。
以下はZENスイッチのADC / d特性ですが、距離二乗反比例だとしても、ほぼほぼ真っすぐじゃないですか?リニアですと言っても困らないと思う。

予定ですが、ロングストロークによる感度の悪化をデュアルセンサー化して解決しようかなと空想の中では思っていたりします。市販されている中ではまだないので他人から見て少し面白いかなと思ったり。
近似式からモデル式
得られた近似式では各スイッチについてのプロファイルにしかなりませんのでどのスイッチでもキャリブレーションできるように仮定したモデル式に一般化しましょう。
近似式の結果を踏まえてモデル式を少し整えます。切片bは4つのスイッチで似たような数値を取り、これはおよそ磁力0の時のADC値1V/3.3V*4095=1240に近い値を取っています。ほぼほぼそうだろうということでこれをbとします。また切片のあるグラフでは見づらいので左辺に移項しておきます。またb→y0と呼び名を変更します。
$$ Y=y-y_0=\frac{a}{( d + d_0 )^2}=aX $$

変数定数について整理しておきます。
d | 底からのスイッチストローク量[mm] | |
d0 | 磁極距離rの補正値[mm] | |
r | d+d0 | 磁極距離(理論式の磁石-ホールセンサ距離)[mm] |
X | (1/r)^2 | モデル式の横軸[mm^-2] |
y | ADC | 0~4095のADC読み取り値 |
y0 | 磁力0の時のADC読み取り値 | |
Y | y-y0 | モデル式の縦軸ADC |
a | モデル式の傾き、磁力の強さ |
キャリブレーションを実施することでモデル式から定数を決定し、y⇔dの相互変換を可能にする必要があります。

- スイッチを押したり離したりすることでボトムアウトおよびトップアウトでのADC値、y1, y2を得ることができます。
$$ y1=ADC_{bottom} $$
$$ y2=ADC_{top} $$
- スイッチのストロークを入力することでボトムアウトおよびトップアウトでの変位量、d1, d2を得ることができます。d1は底ですから0mm, d2はトップなのでストローク値になります。
$$ d1=0 $$
$$ d2=Stroke $$
これを代入し連立方程式を立てます。
\[ \begin{cases} y_1-y_0=\frac{a}{( d1 + d_0 )^2}=\frac{a}{( d_0 )^2}・・・① \\ y_2-y_0=\frac{a}{( d2 + d_0 )^2}・・・② \end{cases} \]
①よりd0が求まります
$$ d_0= \sqrt{\frac{a}{y_1-y_0}} $$
①-②よりaが求まります。
$$ y_1-y_2=a((\frac{1}{d_0})^2-(\frac{1}{d_2-d_0})^2) $$
$$ a=\frac{y_1-y_2}{((\frac{1}{d_0})^2-(\frac{1}{d_2-d_0})^2)} $$
よってキャリブレーションを実施し、y1, y2, d2を入力することでモデル式を使用できるようになります。
実際にラピトリ制御する際は、単純に考えるとまずADC値を読み取り初期位置を算出、そこからラピトリ設定値をoff状態なら-、on状態なら+し、そこからトリガーとなるADC値を算出する感じでしょうか。
初期値をD, Y、ラピトリ設定距離をRとします。
$$ d(初期値)=D $$
$$ y(初期値)=Y $$
$$ R(ラピトリ設定値) $$
ADC初期値を入力し初期位置を取り出します
$$ Y-y_0=\frac{a}{(D-d_0)^2} $$
$$ D=\sqrt{\frac{a}{Y-y_0}}-d_0 $$
次のトリガーとなる判定位置をD’とすると
$$ D’=D±R $$
d=D’が次のトリガーとなるADC読み取り値となる。
$$ Y=\frac{a}{(D’-d_0)^2}+y_0=\frac{a}{(D±R-d_0)^2}+y_0 $$
宿題
とりあえず磁力⇔ストローク量変換ができるようになったと思う。あとは部材とどいたら実測詰めていい感じにしていきたい。
温特をどうにかする。
ADC値のばらつき問題。フィルター入れたりマイコン変えたりしてみる。
したっけ実装に入っていく。
コメント