磁力と距離
picoにつないだだけの同じもので距離特性をざっくり測ってみます。
前回は感度45V/Tのdrv5053eaを使用しましたが、今回は感度が半分の23V/Tのcaホールセンサを使用します。なおこれも範囲をカバーできていないのでもっと感度低いものが必要です。
通常基板からプレートトップの距離が5mmなので、1.6mm基板+3.5mmスペーサのところですが、磁力範囲をカバーするため4mmスペーサを使用しています。

距離を測る機器がないため、スイッチを押していないニュートラルな状態と押し込んだ、ニュートラルな状態から-4mmの状態での平均ADC読み取り値を記録します。
またスイッチ下に1.6mm基板をスペーサとして敷いていき、4回繰り返しました。4mmスペーサで押し込んだ状態を0としています。

この0mmの状態で、およそホールセンサから距離が2mm開いているのでオフセット値を加えグラフにしてみます。雑計測なのであまりなめらかでないですね。

ググってみると磁力は距離の二乗に反比例するそうです。ぱっと見反比例のグラフなのでそんな感じがします。ホールセンサは磁力に対してリニアに電圧が変化し出力されますが、肝心の磁力が距離に対してリニアではないのですね。
押していない付近と押し込んだ付近とで感度が違います。同じ1.6mmの移動でも、2 – 3.6mmの移動量でADCは350変動していますが、3.2 – 4.8mmでは95しか変動しません。
SOCD機能がある以上、fpsでの挙動においてニュートラルから押し込む動作の精度が重要に思いますが、磁力の強い押し込んだ付近の方が高精度にとれるのですね。
磁力は距離の二乗に反比例するということなのでどうなのか見てみます。


それっぽさがあります。そもそもここで採用している距離というのがデタラメ(センサと磁石の距離こんな感じだよね)なので、補正値を二乗平均平方根誤差最小になるやつで求めてみます。


それっぽい感じがします。この近似式にホールセンサ読み取り値を入れれば押し込み量が求めて、press releaseの判定を処理できそうです。
何も考えていないので、もう少し正確に計測出来るようになったらモデルを検討したいですが、なんとなく押下量min, maxでの磁力を測定し、スイッチのストロークを入力すれば各スイッチに対応したキャリブレーションができそうな感じがしています。どうなんでしょう。その場合精度は筐体やスイッチの工作精度や軸ブレ量次第にはなりそうです。
またこの近似式から各距離での検出磁力もホールセンサの感度を入れることで推定できますね。L45はスペックが良くわからないので何も答え合わせできませんですけど
picoのスキャン速度
とりあえずpicoで1000回ADC読んでその時間と平均値を出してみました。picoのクロックを設定できるようなのでいくつか試してみました。
const int numSamples = 1000;
long sumA0 = 0;
int sampleCount = 0;
void setup() {
Serial.begin(2000000); // 高速シリアル通信
analogReadResolution(12); // 12ビットADC
}
void loop() {
// 1回A0を読む
int value = analogRead(A0);
sumA0 += value;
sampleCount++;
// 1000回読み取ったら出力
if (sampleCount >= numSamples) {
int averageA0 = sumA0 / numSamples;
Serial.print("time,");
Serial.print(micros());
Serial.print(",A0,");
Serial.println(averageA0);
// リセットして次の1000サンプルへ
sumA0 = 0;
sampleCount = 0;
}
}

クロック250MHzに設定した1ms間に250回ほど読み取れるようです。単純に50キーのキーがついてるとして1msに50回です。物足りなさは感じます。
A0ピンだけでなくA1ピンも加えて、2つのピンから読み取るようにして同じように計算してみました。

A0とA1の分があるので読み取っているキー数はこれの2倍となります。A0のみから読み取るのよりも遅くなってしまっていますね。
picoのデータシートp.557にADCのサンプルレートは500kHzで1基搭載し4つのADC入力とマルチプレクサで接続されていることが書かれています。

ADCは1基しか搭載していないので2ピン読み取らせるとむしろMUXの切り替え時間とかで遅くなってしまっている感じでしょうか。もし仮に1ピンあたり500kHz出たとしても50キーあると10kHzですからpicoではADCの搭載数、サンプルレートともに磁気キーボードを作るうえでは足らないのかなと思ったり。プロトタイプなら全然よさそうですが
マルチプレクサ
16チャネルのマルチプレクサ CD74HC4067SM96 の動作を確認します。
市販の磁気キーボードには大抵MUXが乗っておりADCピン数を拡張しています。マイコンにADCピンが60個とかついてないですものね。CD74HC4067SM96は一つで16個のADCピンを拡張できます。

S0~S3でP0~P15のどのピンから読み取るか指定し、dataピンからマイコンに指定したピンのADC出力が読み取れる感じの部品です。今回は抵抗で分圧して電圧値読み取れるか試してみました。

// セレクトピンの定義
const int S0 = 0;
const int S1 = 1;
const int S2 = 2;
const int S3 = 3;
// ADCピン
const int adcPin = A0; // GP26 = ADC0
// 読み取るチャンネル(P0〜P3)
const int channels[] = {0, 1, 2, 3};
const int numChannels = sizeof(channels) / sizeof(channels[0]);
//int型は4バイトchannnel配列は4要素計16バイト、channnell0は1要素4バイト、16/4=4要素らしい
void setup() {
Serial.begin(200000);
// セレクトピンを出力として設定
pinMode(S0, OUTPUT);
pinMode(S1, OUTPUT);
pinMode(S2, OUTPUT);
pinMode(S3, OUTPUT);
// ADCピンの初期化(Arduino環境では特に不要なこともあります)
analogReadResolution(12); // Picoでは12bit ADC(0〜4095)
}
void loop() {
for (int i = 0; i < numChannels; i++) {
setMuxChannel(channels[i]); // MUXのチャンネルを設定
delay(10); // セットアップ時間待ち
int adcValue = analogRead(adcPin); // ADCから読み取る
Serial.print("P");
Serial.print(channels[i]);
Serial.print(", ");
Serial.println(adcValue);
delay(500); // 待機
}
}
// マルチプレクサのチャンネルを選択する関数
void setMuxChannel(int channel) {
digitalWrite(S0, bitRead(channel, 0));
digitalWrite(S1, bitRead(channel, 1));
digitalWrite(S2, bitRead(channel, 2));
digitalWrite(S3, bitRead(channel, 3));
}
//bitreadでchannnelという引数に渡された値の、何ビット目の値を出すらしい

問題無く読みとれていそうです。使う分には sピンで指定→読み取り だけで難しいことはなさそうです。またenableピンもついているので、mux個数分のioピンを用意すればこんかいのpicoのようにADCが1基のみの搭載でも同じADCピンに複数のMUXを接続することができるようです。
速度とか切り替えとかノイズとかも次にpicoやオシロで確認したいです。
部品調達
何も知らない何も考えてないで始めているので、どれも性能が足りていないことがわかりました。
使える部品を買い足したいところです。
まずスイッチがL45が数個あるだけ状態なので、定番品を入手しておきたいところです。磁気キーボード関連何も知らないので何買えばいいのかもわからない、、
少し調べてみると、ストロークだけでなく磁力も公開されているものが多いのですね。例komとjadepro


gateronなどはデータシート自体公開しているようでしたが、あまり欲しい情報は得られませんでした。基本的にはストロークと1.2mm pcbでのtop, bottomでの磁力だけのようです。
本当に何も知らないのでks-20互換というのは本当に互換なのだと思っていましたが、磁力、磁石との距離、ストローク、どれもまちまちなのですね。まあ互換といっているのも名目上はユーザーなのでしょうけど。ks20互換が意味するのは極性とMXタイプであることぐらいなのですね。
磁気スイッチの種類というのもめちゃくちゃ多いそうで、わけわからん状態なのですが1年後も使用され続けていそうなものを何種類か見繕いたいところです。
drv5053caの23mV/mTより感度の低いホールセンサを調達したい。また5053は出力が0-2v固定なのでもっと広く見れるものが良いかなと思いました。その分細かく見れますものね。↑のように磁気スイッチは1.2mmpcbとして700Gs=70mTは最低でも見れなくてはならないですね。適当に調べてみた感じ候補はこんな感じでしょうか。基本的にはよく見る3端子のもので、スリープ機能付きのものは6端子です。
drv5053caは350Gsまでしか見れないのですが、今回L45を0.4mm程度浮かせると振り切ることなく計測できていました。L45のスペックがどんなものかはわからないですが、距離^-2というのは感度が極端に変わりすぎてめんどくさいなあと思います、
5053他は与えた電源と同じレンジで出力が見れるものと思います。また5056は片方の極性しか見ないため、倍細かく見れそうです。
スリープ機能付きのものは、ioピンこそたくさん必要ですが、MUXなしでオンオフ制御できそうです。どちらがいいのかは何んともわかりませんが、売っているので検討はしたいなと思います。計測範囲ちょっと狭いのですけどね。その話で行くともっといろいろホールセンサもラインナップはあるはずで、個人だとまず部品の選択肢から狭いのはきついなと感じます。

マイコンボードももっと高性能なものを使用したいところです。実際に使うにあたりどの程度のADC基数、sps、クロックが必要なのかは見ておく必要があります。ai君に調べてもらうとstm32がよさそうです。

市販品は8k当然な感じですがnucleoボードはUSB2.0対応のものはないそうです。でもteensy4とか高いのでnucleoボードでいったん試してみようかという感じ。そもそも8kHz必要なのかという話でもあります。
正確に押下量も取りたいのでマイクロメータもあったほうがよさそうです。mitutoyoのmhn2-25mxとかこういう感じでしょうか。どこまで正確にできるのやらとは思いますがたかがスイッチを押すだけに仰々しい設備導入とかとも思うのでこれくらいがちょうどよいとは思うけれどどうしたもんか

なんもわからなくても何もしないでもai君がarduinoコード出してくれるので楽なものですね。
もうちょいい環境整えて、具体的な話をしていきたい。
コメント