2017年2月22日水曜日

超音波流速計 優先順位の付け方を考える

 とりあえずPCの中でいろいろ試しています。実行時間は気にしないので、位相の動きは10フェーズ分を計算しています。実際の動作環境ではせいぜい8フェーズ程度ですが、まぁリソースに余裕あるし、人間的にキリがいいし。
 真面目に位相から気温と風速を計算すると10x10で100個の候補が出てくるので、さすがに何とかする必要があります。とりあえず明らかに計測レンジの外、例えば気温が+200℃だとか、風速が70m/sだとか、そういうのをある程度の閾値で止めます。今回は±55℃、±35m/sを閾値としました。サンプルデータは±50℃、±30m/sの範囲なのですが、計算誤差だったり丸めだったりで微妙にこの範囲を超える値があるので、大きめに閾値を設定しています。
 閾値で切った後でも、それなりの候補が残るので、とりあえずサーミスタの温度からn℃以内というフィルタを通すことにより、候補を5個程度まで絞り込みます。今回は5℃以内で切りました。

 で、そこからさらに信頼度を比較する必要があるのですが、色々比較方法を試した結果、以下のようになりました。
サンプルデータは前回のエントリの最後に貼ってありますが、ほぼ完璧というレベルで一致しています。「誤差の範囲で一致」というヤツですね。

 ちなみに、上のグラフは信頼度が一番高い値ですが、その下2個を含めると、以下のようになります。
温度も含めるとわけわからんことになるので風速だけですが。

 で、問題の「どういう比較をして値の順位を付けるか」ですが、「前回の風速と近い順にソートする」としています。前々回のエントリで「直前値は使えない」とか書いておきながらこのザマです。いやー、クローズドループって楽(おい。

 今回のテストデータは気温が1℃毎秒、風速が3m/s毎秒で変化するように作ってあります。しかし、実環境では温度が急激に変化する可能性は低いとは言え、風速が急激に変化するということは充分にありえます。
 特に位相位置をクローズドで回すと、一旦間違った値に飛んでしまった場合、正常な値に復帰するのが困難です。これは起動時の初期化にも言え、初期値を誤って判断した場合、偶然正しい位置へ飛べない限りは常に異常値を計測し続けることになります。

 ということで前回値を使わない、オープンループで現在の値を計算できる方法を探す必要があるわけですが、サクッと試した感じでは結構難しそうです。
 生データからは100個の候補が得られ、計測レンジとサーミスタの値で絞り込むと候補は5個程度まで減らせますが、そこからさらに絞り込む方法がありません。
 しかし、これが3軸のセンサを使えるとなると、候補は全体で300個となりますが、レンジで絞り込んで15個、そしてそれぞれの温度はすべて同じ値になるはずですから、温度でランキングすればさらに絞りこめるはずです。
 ということで、軸数を増やせばなんとかなるんじゃないかな、と甘い考えが有るわけです。
 じゃぁとっとと3軸のデータ作って試せよ、という話になるわけですが、単純に出力が3倍になるだけじゃなくて、入力の風速も3方向になったりとか、センサの設置向きを三角関数で計算して…とかとても面倒になります。
 そもそもノイズのない綺麗なデータで動いていても実環境で動くのか、という問題が出てきます。やっぱ風洞とかで試したいなぁ。

2017年2月21日火曜日

超音波風速計 いそうをよそうしてみる


 気温と風速を変えて位相を予想したグラフです。青と赤は左軸でそれぞれ気温と風速、緑は右軸で位相です。
 位相はゼロクロスの位置なので、40kHzの1周期分の25マイクロ秒までです。0未満、あるいは25以上では次の位相に飛ぶため、不連続な変化を起こします。

 シミュレーション(というほどではないけど)は、まず風速0m/s、気温15℃で開始し、しばらくしたら気温を上昇させ、50℃に達したら降下に転じ、-50℃に達したら上昇に転じ、というサイクルです。
 しばらくすると風速が上昇し、30m/sに達したら降下に転じ、というサイクルです。

 まず気温に対する位相の変化ですが、気温が上がると音速が上がり、スピーカーからマイクに到達する時間が短くなるため、位相が減少する変化となります(実測でもそのような変化です)。
 風速に関しては、いまのところ風速の正負と位相の前後はどのように設定してもいいので、てきとーに計算しています。

 とりあえず、このグラフのようにジタバタした位相から正しい気温・風速を計算する方法を考える必要があります。


 ちなみに、位相ではなく、SPからMICへの到達時間をグラフにすると以下のようになります。最初のグラフよりは、気温と風速が位相に与える影響がわかりやすいと思います。


 最初のグラフは、到達時間を25で割ったあまりを書いたグラフです。さすがに使用温度範囲+50℃から-50℃、計測範囲-30m/sから+30m/sまで、という環境で使う予定はありませんが、この範囲だと位相は200us、8フェーズ分くらい動きそうです。
 さらに蛇足を重ねると、超音波素子の動作温度範囲は-30℃から+80℃まで、マイコンの動作範囲は-40℃から+85℃まで、という感じです。他には明らかに低温・高温がヤバい部品はありません。心配なのはLDOや水晶がありますが、とりあえずマイコンの動作範囲であればなんとかなるはずです。南極は無理ですが、北極圏であれば記録的な低温でもない限りは使えるかもしれませんね。

超音波風速計 処理方法を考える


基板を作るにあたり、データ仕様にもいくつかの変更が加えられています。一番大きいものは、位相の正負をプログラム側で処理することと、チャンネルの設定が複雑になったことでしょうか。
 上の画像は横軸が経過時間[秒]、青がサーミスタ温度[℃]、赤がチャンネル2-0の位相[microsec]、緑がチャンネル5-3の位相[microsec]です。

 ブレッドボード上では、チャンネル0で送信したらチャンネル0で受信する、というような組み合わせがありましたが、基板化した際に配線のしやすさを優先し、コネクタ1には送信Ch5と受信Ch0、コネクタ2には送信Ch4と受信Ch1、というような組み合わせになっています。またセンサの配置とコネクタの接続によって対向するチャンネルの組み合わせが決定されます。現在は1セットしかありませんが、送信Ch2は受信Ch0、送信Ch5は受信Ch3、という組み合わせになっています。これはテーブルに保持する必要があるので、より多くのリソースを消費します。とはいえ0-5からなる2組の数字を6対持つだけなので、割合で言えば大したことはありませんが。


 それから、ファームウェアの変更で位相は0-25の範囲を取るようにし、前の位相・次の位相に変化するといきなり値が飛ぶような挙動となりました。上の画像では緑の線が後半に暴れていますが、24あたりにいるのは、24 - 25 = -1が正しい数字ということになります。これは負の値に限りませんが、位相が飛んだときはそれを正しく処理するプログラムが必要となります。
 干渉SAR画像に近いイメージですが、人間なら「たぶん位相n個分ズレてる」というような判断ができますが、プログラムでどうやるか、という問題です。取りうる範囲の位相全てで温度やら風速やらの候補を出し、一番それらしい結果を使う、という感じになるのかもしれませんが、どうやって順位をつけるか、という問題が出てきます。

 風速や温度はゆっくりと変化するわけだから、位相も前回値に応じて判断すればいいじゃないか、という事になりますが、場合によっては前触れ無く風速や気温が変化する可能性もあります。例えば爆風に晒されれば急激に気温や風速が変化します。とはいえ爆風の温度やら風速やらを超音波風速計で測るシチュエーションも思い浮かびませんが。
 他の、もっと現実的なシチュエーションとしては、起動時の位相をどうやって判断するか、という問題になると思います。起動直後は前回値から判断するという処理は不可能でなので、何らかの方法を用いて現在の位相を求める必要があります。

 とりあえず、数日はこの問題にかかりっきりになると思います。とはいえ、位相が1以上変わるような温度変化や風速というのはなかなか模擬できないので、そのあたりが難しいところです。PC上で風速やら気温やら渡したら位相を計算するようなシミュレータを作って、それの出力値で遊ぶ感じになるのかなぁ。

超音波風速計 とりあえず基盤を作ってみる


 試しにユニ基板で組んでみました。とりあえずシリアル通信と温度センサのあたりは動作確認できました。超音波素子(アナログ回り・PWM回り)はまだほとんど確認していません。

 ブレッドボード上では、PB0,1の波はPA0で計測、PB2,3の波はPA1で計測、のように規則性がありましたが、基板の方はもうすこし複雑になっています。またPB6-9を予約しているので、出力ピンの選択も面倒です。
 とはいえ、このあたりはすべてプログラムでどうにでもなりますから、計測性能にはほとんど関係ないはずです。
 それと、ブレッドボード上では位相を回路の方で合わせていましたが、基板ではソフトウェアで合わせようと思っています。おそらく位相から時間に換算するオフセット値で動かせるはずなんですが、そのあたりも追々確認していく必要があります。

 基板上は少し空きスペースが有るので、タクトスイッチ数個と、小型の液晶モジュールくらいなら接続できそうです。もっとも、GPIOの空きが極めて少ないので、I2Cの表示モジュールと、スイッチはSTBeeMiniデフォルトのリセットスイッチとユーザースイッチくらいしか接続できないでしょうけども。
 一応、CANのピンは開けてあるので、ちょっとしたイベントで風速を調べたい場合とかでも、この基盤をそのまま使えるはずです。CANバスなので、例えば「3次元風向風速計を5m間隔で500mに渡って100個配置し、空間の風向を把握する」みたいな使い方もできます。もちろん幅100m、高さ25mの2次元とか、それを複数個並べて100x100x25mの範囲の3次元的な風向とかも調べることもできます。ま、いくら可動部レスで信頼性が高いとは言え、最安構成でも部品だけで1セット2万円くらいはするでしょうから、100個並べれば200万円、さらにフレームとか考えれば1000万円くらいは余裕で行くはずです。もしも、数千万円規模でもいいから50mメッシュで3次元に風向風速計を並べたい、みたいな研究をしている人が居たらぜひお声がけを。って、そんなの怖くてやりたくないw。そもそもそんなことやるならLIDER使えという話で。

 冗談はさておき、やっとちゃんとした感じになってきました。ブレッドボードを振り回すわけにも行きませんが、基板になってしまえばいろいろできます。風速計自体を動かして出力値の健全性を確認したりとかもしやすくなります。
 まずはマイコン側のファームウェアの修正と、PC側のソフトウェアの修正をしなきゃ。

2017年2月20日月曜日

超音波風速計 やっぱり温度を測る

 最近ずーっと超音波風速計ネタですね。飽きるまでもうしばし掛かりそうなのでご了承ください。



 1枚目は横軸が経過時間[hour]、縦軸が℃で、青がサーミスタで計測した値、赤が超音波から計算した値です。
 2枚目は横軸がサーミスタの温度[℃]、縦軸は青が左のスケールで超音波から計算した温度、赤が右のスケールでサーミスタと超音波の差です。

 サーミスタと超音波の差はほとんどが±1℃程度に収まっているようです。時間経過の方を見てみると、超音波よりサーミスタが遅れているようです。例えば温度が下がるときは超音波のほうが先に下りますし、温度が上がるときは超音波のほうが先に上がります。これはほとんど流れのない部屋で計測しているので、サーミスタの時定数が大きくなっているのかもしれません。温度の計測誤差は大半がこの時間遅れの影響な気がします。そう考えると、超音波のほうが正しく、サーミスタのほうが正しくない(ちょっと前の)値を出している、とも言えそうです。

 それにしても、部屋の温度って暖房を止めたらコンスタントに下がり続けるんですね。1時間に0.5℃くらいのペースでしょうか。コレ暖房付けないでいたらどこまで下がるんでしょう。温度差が0になるまで下がるとしたら氷点下まで行くんでしょうか。30時間ぐらいかかりそうですけども。


 とりあえず、今回の計測では異常値らしい値は確認できませんでした。一番有り得そうな原因は潰したはずなので、おそらく発生することはないと思いますが、前回は11時間で7回程度だったので、発生頻度は高いとはいえません。もしかしたら今後出てくるかもしれませんが、今のところは問題ないと考えています。


 そろそろブレッドボードじゃなくて、ユニバーサル基板で作り直したいな。でも面倒くさい。いくら能動的アナログ素子使用禁止縛りとは言え、分圧抵抗の抵抗器もバカになりません。1chあたり抵抗が3本で6chあるので18本もあります。ってコレでも充分少ないんでしょうけども。あとはカップリングコンデンサが0.1uFとは言え18個ありますが、こちらは1608のチプコンがあるので、多少はらくだと思います。分圧抵抗もチップ抵抗にできればすっげー楽なんでしょうけど、手持ちにないのでどうしようもない。

 わざわざチップ抵抗を2種類買うために秋月を使うのもなぁ。前に東京に住んでる人と話した時に「東京に住んでたって電車代とか考えたら通販のほうが安いですよ」とか言われましたが、そういう問題かなぁ。そのあたりを乗り越えた先に新しい世界が有るのかもしれませんが、そこに達するには時間がかかりそう。いろいろな面で余裕が必用そうな気がします。
 手持ちの超音波素子が必要数に達しなければ秋月で買うしか無いので、その時にチップ抵抗も買うんですが、探したら必要数出てきちゃいました。ということで、しばらくは手持ちの部品で頑張ってみます。

超音波風速計 とりあえず温度を測る


 とりあえずゼロクロス検出のプログラムを修正して計測してみました。
 プログラムとしては、一旦エッジを検出したら80サンプル、8.88...マイクロ秒(80/9マイクロ秒)分スキップするという処理になっています。本来、1つのエッジで複数のゼロクロスがあれば、中央を取るとか平均を取るとかするべきですが、とりあえず今回は実装が簡単な方法を選びました。
 ただ、前回の11時間取ったときは計測開始から5時間ほど経ってからノイズが出ていたので、今回の1.5時間分程度ではサンプルとして足りないかもしれません。

 それと、計測誤差は-0.5℃から-2.5℃あたりにいるようです。これは位相から時間に計算するためのオフセットの値によるものです。適切な数値を設定すればゼロ前後に移動できます。

 またこのグラフにはありませんが、風速は温度に関係なく-0.25m/sを示していました。これはセンサ2セットの距離に関係するもので、工作精度に影響を受けますが、プログラムでオフセットできます。とりあえず、温度に関係なく誤差が一定というのは期待が持てそうです。


 今のところ温度やら風速やらはPC側で計算しているので、これをマイコン内で計算できるようにしたいな。でもその前に3軸化したい。

2017年2月19日日曜日

超音波風速計 異常を探せ


 位相ログに異常値が残っている場所と、正常値の場所の波形ログです。重なって見えづらいですが、波形には特に目で見ておかしいと言うほどの違いはありません。

 当初の予想では、かなりインピーダンスの高いであろうアナログ系の配線に何らかのノイズが入ったのではないかと思っていたので、この結果は予想外です。ノイズであれば回りにノイズ源になるようなものを置かないとか、いろいろ言い訳ができるんですが。


 位相の異常値も、正常値との差が1.25とか25とかであれば位相位置の計算に問題が有るんだろうな、という予想ができるんですが、せいぜい6セットの異常値からはそれぞれの関連性はわかりませんでした。
 とはいえ、波形には問題がない、とわかったのは収穫でもあります。というのも、前回、位相ログは取ったけど波形ログは取っていない時に、異常値が30個前後出ていました。この時のデータを見直せば何かわかることがあるかもしれません。
 それと、マイコン内で行っている計算も、プログラムは単なるC言語の演算ですから、関係ありそうなソースコードをPC向けにコンパイルして今回の波形ログを読ませて異常値が出るか、出た場合は計算過程でどういう値になっているか、といったことからもいろいろと分かるはずです。

 ということで、ノイズの原因をしらべるにはもう少し時間がかかりそう。


***追記

 不具合が発生して喜ぶというのも変な話ですね。上側が位相ログから抜き出したもの、下側が波形ログからPC上で計算した位相です。
 最初、プログラムミスで右側の値の計算を間違っていました。当然、値は異常値ではなく、正常値に近いモノが出てくるわけで、こりゃぁマイコン側の深いところの問題かなぁ、とか思ったわけです。でもミスに気がついて直すとマイコン上で計算したものと同様の異常値が出てきて安心しました。これならマイコンやコンパイラの問題ではなく、単なる計算ミスによる可能性が大きくなります。ということで、簡単にチェックができるので、不具合が再現してくれて一安心。
 マイコン側のメモリの関係で、配列の処理とかが結構面倒ですが、それでも再現性のない不具合よりは簡単です。さぁ、間違い探しの時間だ!

***追記

左の波形は、右の波形の一部を拡大したものになります。右の波形は一見すると綺麗な正弦波ですが、細かく見ていくと若干ノイズが乗っていたりします。ちょうどゼロクロスの部分で暴れると、位相検出でエラーとなるようです。
 波形の図を出して「特におかしい所はない」と言いながら、舌の根も乾かぬうちにこのような原因が見つかってしまいました。

 このような波形になってしまうのは、等価時間サンプリングを使っている以上は仕方ないことでもあります。解決策としては、等価時間サンプリング後からゼロクロス検出前の間でローパスフィルタを通す事や、一定間隔未満での検出は無効にする等、他にも色々考えられます。
 昨日?一昨日?あたりに取ったログでは2時間で30前後の異常値が発生していたので、それなりに頻度の高いエラーといえると思います。異常値があれば無視する、といった方法は取らないのが無難だと思います。
 またゼロクロス検出はマイコン内で1chあたり450回行い、1軸あたり2回、3軸で6回行われます。3軸10Hzだと毎秒1万3500回ほど計算する必要があるので、充分に計算負荷の軽い処理であることも求められます。
 さてどうしようか。