2017年2月28日火曜日

超音波風速計 べくとるえんざん

グラフだけ見せられても何が何やら、という感じですが、超音波風速計にENUの軸を割り当て、それぞれの方向から風を当てるとちゃんとそのように出力されました。若干クロストークがありますが、風の軸が正確にわかっていない(シロッコファンを未整流で使ってるので軸が乱れてる)こと、そもそもの形状が乱流を出しやすそう、といった理由によると思われます。
 今のところ、軸ごとに双方向の平均で音速・差で風速を計測しており、音速から気温を換算しています。風速はそれぞれの3軸ベクトルとしてセンサの向きに回転させ、3軸分を加算してENU(East North Up)としています。

 一般的なお椀型の風速計は回転数と風速の換算値を何らかの形であらかじめ計測しておく必要がありますが、超音波風速計の場合は風速と時間が簡単な計算で換算できるため、未校正でもそれなりの数値になっています。とはいえどれくらい正確なのかはわかりませんが。

 現在はほぼすべての計算をPC上で行っているので、あまり実行速度は考慮していません。とはいえ、3軸ベクトルを1軸あたり2回ずつ回しているので、1回分の計算はかなり高負荷だと思われます。このままマイコンに移植するのはやめたほうが良いと思いますが、かといってどう処理すればいいのやら。やっぱり浮動小数点演算ができるF4を使うべきなんじゃないかなぁ(今更。


 でも、やっとENUの3軸で出せるようになったので、最低限「風向風速計」と言えるようになりました。少なくとも、「風速計」や「風向計」よりはマシだと思います。ちゃんと校正しないとだめですけどね。それはこれからの課題ということで。

超音波風速計 位相とか距離とか


 1枚目は横軸が時間、縦軸が温度。tempがサーミスタ温度、それ以外は位相から計算した温度。
 2枚目は横軸が時間、縦軸が音速から計算した気温とサーミスタ温度との差。
 1枚目と2枚目の横軸の範囲は違うので注意してください。2枚目は急激な温度変化でサーミスタが追従できないと考えられる範囲を除外しています。
 それぞれのセンサ間距離が157.5-159.5mmくらいと設定し、位相を17.5か18にするとだいたいいい感じになります。結構誤差がありますが、それでも±1℃程度なので、サーミスタの誤差とか、ちょっとした気流の影響とか、色々ありそうです。やっぱり恒温槽ほしい。

 配線時は何も考えずに配線し、位相はプログラム側で合わせる、というふうにしたのですが、偶然にもオフセットは打ち下ろしが18、打ち上げが17.5となりました。
 位相を合わせるのは圧電素子の極性を変えるだけなので、あとからでもやろうと思えばできます。個体に合わせてプログラムを変更するよりも、センサの極性を合わせてすべての個体で位相を統一したほうが楽かもしれません。次に配線をやり直す機会があれば、そのような配線を試してみます。

 センサ間の距離は表面で150mmになるようにフレームを設計しましたが、実際の圧電素子はケースの奥、およそ4mmほどの距離にあります。双方合わせて8mm分奥まったところにあるので、センサ間距離はおよそ158mmとなります。位相を0.5ステップで設定した場合、センサ間距離を157-160の間にすればかなり良い範囲になるので、そんなに外したパラメータにはなっていないはずです。
 センサ間の距離は158.0, 157.6, 158.85, 157.5, 159.55, 158.1としています(まだ厳密に設定したわけではありません)。Ch3UとCh2Lが少し離れた場所にいますが、Ch1U, Ch2U, Ch1L, Ch3Lの4個は0.5mmほどの範囲で、かなり優秀な感じですね。Ch3U, Ch2Lが少し飛んだところにいる理由はわかりませんが、そもそも高精度に組み立てられる構造ではないことや、センサの個体差を考えれば、こんなもんかなぁという気もします。


 これからは風速計としての性能を出していく段階ですが、校正手段が無いのがどうしようもないですね。恒温槽、風洞、無響室、いろいろなものが欲しくなってきます。

超音波風速計 位相を見てみる


 ある程度の時間、位相を取ってみました。
 1枚目は横軸が時間、縦軸は青のtempが温度、それ以外は位相です。
 2枚目は横軸が気温、縦軸は位相です。
 温度が低くなると音速が遅くなり、音の到達時間が伸びます。そのため位相が遅くなるわけです。ただし位相は0-25の範囲を取るので、Ch1L,Ch2L,Ch3Lは途中で0に戻っています。温度変化はゆっくりなので、0あたりに行ったり、25あたりに戻ったりと、結構暴れています。温度が高くなるのは暖房でかなり早い動きのため、暴れている時間も短いです。
 温度を横軸に取ったグラフで、23℃から24℃あたりで位相の変化が見られませんが、これは以前にも見られた傾向です。何の影響かわかりませんが、温度センサの時定数とかが関係しているのかもしれません。

 とりあえず、ほぼ無風の状態で温度と位相の変化が得られたので、センサ間距離やらのパラメータを設定して再現できるか試してみようと思っています。

 それにしても、超音波風速計は立体形状でそれなりの大きさが有るので、画面の前にあるととても邪魔。

2017年2月27日月曜日

超音波風速計 波形を見てみる


 センサの配置は上側の60度の位置がCh1、180度の位置がCh2、300度の位置がCh3となり、下側は上の対になるチャンネルになっています。下側240度がCh1、120度がCh2、0度がCh3ですね。トランスミッタが上にあればU、下にあればLで、Ch1-3のUとLの組み合わせで6経路分です。
 Ch2Uが明らかに山が低いのが謎です。最初の設置したセンサは変な挙動を示したので交換して、交換後は他の山と同程度の高さだったのですが、最近は常に低く出ています。何に使ったかわからないありあわせのトランシーバを使ってるのが良くないのかなぁ。

 とりあえず、Ch1U, Ch2U, Ch3Uはほぼ位相が同じで、Ch1L, Ch3Lは0.5フェーズ分ずれた位置にいます。これは圧電素子の極性を合わせていないためで、ソフトウェア側でタイミングを0.5フェーズ分移動させれば問題ありません。
 Ch2Lは0.25フェーズほどズレていて、これはちょっと謎です。0.25フェーズ分だと2mmくらいの差です。Ch2UとCh2Lは同じ面にトランスミッタとレシーバがついているので、2mmもズレているとは思えません。もっとも、フレームはネジで組み立てており、どれくらいの精度で組まれているかは不明ですが。


 等価時間サンプリングの波形が結構ノイジーなのが気になります。狭い範囲にフレームやらいろいろあるので、反射波とかいろいろ有るのかもしれません。

超音波風速計 祝・3軸化


 ついに超音波風速計が3軸化されました。
 フレームはタミヤのユニバーサルアーム、超音波TRのマウントはDMMの造形に出しました。とりあえず試作なので乱流とかは気にしません。
 センサ間は150mm程度、角度は水平から45度、120度毎に双方向を配置して3軸です。
 市販の超音波風速計は100mmで角度60度だったりするようです。100mmであればコンパクトになりますし、60度なら水平方向の投影面積が減るので横風に対する影響が減るという利点があると思います。

 とりあえず以前の1軸のソフトウェアでちょっとログってみましたが、かなりノイズが多いようです。配線が長くなった影響なのか、束ねてPWMがアナログ系に流れ込んでるのか、とりあえず影響があるのは間違いないようです。
 一応ワイヤハーネスは上下で分割しており、PWMを出しているときは別系統のハーネスのアナログには影響が出にくいようになっているはずですが、あんまり効果はないようです。

 基板も作ったし、3軸のフレームもできたし、あとはソフトウェア回りですね。

2017年2月26日日曜日

JS Orbitの更新

 久しぶりにちょこちょことJS Orbitをいじりました。
 JS Orbit



 大まかな変更として、1) 観測地点の上に可視範囲円を表示、2) 軌道予測線の長さを任意に設定できるように、3) ちょこっとデザイン変更、という感じです。


 1)はグレーで表示されている円です。これは衛星を選択中に表示され、観測地点を中心として現在選択中の衛星が仰角0度になるあたりの範囲です。
 2)は赤い予測線を衛星何周分表示するかという設定です。いままでは1周固定でしたが、任意の長さに設定できます。任意とは言えリアルタイムで更新し続ける都合から、せいぜい数十周程度までかなと思います。MeanMotionの値をコピーすればちょうど1日後までを表示します。MeanMotion*7であれば1週間後までです。例えばISSはおよそ15.5なので、だいたい100で1週間となります。TLEの鮮度の観点でも、実用的な表示速度という観点でも、だいたい100あたりが上限かな、と思います。とはいえこれは軌道何周分を表示するかという設定なので、例えば静止衛星であれば100を設定すると100日分となってしまいます。そこまではTLEの鮮度が持たないので、静止衛星であれば1桁台程度にとどめておくべきです。

 ほんとうは仰角30度の範囲とかも書きたかったのですが、計算が面倒っぽいので今回は省略しました。いい方法があったら教えてください。


 もうちょっといろいろやりたいんですが、とりあえず今回はここまで。

2017年2月25日土曜日

PSLV-C37

「100機同時衛星打ち上げ」で一瞬話題になったインドのPSLVから放出された物体のTLEが出始めました。まだ70個ほどのTLEしか出ておらず、全てが出揃うには時間がかかりそうです。

 JS Orbit

 PSLVの少し前にはSpace XのFalcon-9がIridium NEXTを10機まとめて打ち上げています。
最初に見たときは10数個の物体が並んでいると多いなぁと思ったものですが、いま見直すと結構スカスカな感じがしますね。

STM32F1のI2C ~NVICを添えて~


割り込み駆動のI2Cがやっとそれなりに動くようになりました。オレンジがFreeRTOSのIdle Hookでトグルしているピンで、I2Cの転送中にもIdleタスクが動いていることがわかります。
 STM32F1はStdPeriphLibという、メモリマップドのコンフィグを簡単に確認・設定できる関数群が用意されていて、ハードウェアの制御は基本的にこれらを使って操作するわけですが、ペリフェラルによって簡単に設定できるものもあれば、なかなかに難しいものもあります。いままで使ったペリフェラルの中でも、I2CとNVICの組み合わせはダントツに難しいと思います。
 特に一部のフラグは通常のC言語処理とまったく違う動きがあり、「特定のレジスタを読むとクリアされる(≒1回フラグチェックをするだけで情報が破壊される)」というのがあり、他にも「Aはaに対してtrueだが、Bはbとaに対してtrue」という戻り値をとる関数もあります。しかもBのチェックを行うと情報が破壊されるためAのチェックが行えない(逆も同様)、といった組み合わせになっています。
 このあたりが非常に面倒で、StdPeriphLibを使わずに、直接ビットを叩いたほうが楽だと思います。

 まだ最低限必用な割り込み処理しか行っていないのですが、しばらくはI2C+NVICは触りたくありません。「1回読むと情報が破壊される」ってデバッグが非常にやりずらい。量子力学とかもこんな苦労なのかなぁみたいな思いが浮かんできます。

 それにこれほどの苦労をしてなおまだ足りないのですから、I2Cセンサを使うよりSPIで叩けるセンサを探すほうが遥かに簡単だと思います。特にSTMのセンサは大抵がSPI/I2Cを1つのセンサで兼用していますし。もしかしたら自分のところのマイコンでI2Cが使いづらいからSPI/I2Cが兼用なのでは…と疑ってしまうほどです。

 SPIはあんまり厳密にチェックされていないので、バスにノイズが乗っても無理やり続行できちゃいますが、I2Cはノイズなどでバスがビジーとなると以降復帰できなくなります。そのあたりの動作を確認しておかないと怖くて使えないのですが、どーやったらいいんだろう。業務用だとI2Cにノイズ入れる専用の機材とか売ってるのかな。
 以前にそのあたりでかなり苦労してるので、ちょっと疑心暗鬼気味です。

2017年2月24日金曜日

STM32F1のI2C


 ためしにADT7420で計測してみました。青のt1が生データ、赤のt2が10サンプルの平均です。若干ノイズが大きい気がしますが、振幅は0.1℃程度なので、それなりにカタログスペックが出ているのかもしれません。
 センサは1SPS、16bitで初期化し、FreeRTOSのTaskDelayで1000msecウエイトをかけて約1Hzで取得しています。一応グラフの横軸は時系列になっていますが、タイムスタンプを出していないため、何らかの理由でデータが止まっててもログに残らないので、時間精度はあまりないと思います。


 今回、久しぶりにSTM32F1のI2Cペリフェラルを使用しました。このI2Cはかなり厳密に管理されており、上手く使うのはかなり大変です。
 今のところ転送完了をソフトウェアループでポーリングしているわけですが、例えば3軸センサを読む場合、9バイトの転送に0.2ミリ秒ほどかかります。200マイクロ秒というと大した事はない気もしますが、72MHzのマイコンなら200マイクロ秒でおよそ15k(1万5千)サイクル分あります。実用的なセンサ数だと1秒あたりこの数百倍ほどの実行時間をポーリングに使っていることになります。かなり無駄な気がしますよね。
 ということで、せっかくRTOSが乗ってるので、I2C転送中は別のタスクを行えるようにしたいのですが、なかなか大変そうです。
 STM32F1のI2Cは苦い思い出が多いので、もうちょっといろいろと試してみようと思っています。数日はI2Cにかかりっきりかな。

2017年2月23日木曜日

超音波流速計 温度特性?


 しばらく表示ソフトを起動しっぱなしでほったらかしてて偶然気がついたのですが。
 このグラフは縦軸が上端30下端-5で横軸は1メモリ1000秒(16.66...min)です。
 グラフの左側、部屋の暖房を止めてゆっくりと気温が降下しているのがわかります。と同時に、風速の値に微妙にオフセットが増えていることも読み取れます。これはおそらくセンサ距離の校正をしていないためだと思われます。
 超音波流速計はいろいろな計測誤差がありますが、一番大きく出てくるのはセンサの極性です。ただこれは50%という大きな値ですが、0%か50%のどちらかなので、補正は簡単です。もう1つ大きな要素は、センサ間の距離があります。今回は手元にあった樹脂部品でフレームを作っているため、センサ間の距離はおおよその数値を使っています。なので、ある温度で校正した場合、別の温度になるとオフセットが生じるはずです。このグラフはそれを表しているのだと思います。

 センサ間の距離を正確に測るというのはかなり面倒なので、おそらく実際に校正する場合は気温が既知の複数の空間を使用し、それぞれの温度と出力値から、「この距離と考えると近そうだ」という数値を探していくことになると思います。


 風洞もいいけど、やっぱり恒温槽ほしいなぁ。
 簡単な風洞なら1万円くらいでお釣りが来そうな気がします。ペルチェ素子はかなり安いし、電源も150Wクラスが数千円です(ATX電源なら更に安くて高出力が有るはずですが)。箱は発泡スチロールの箱で十分ですし、コントローラだってある程度までの性能であれば簡単なPI制御で充分なはずです。もしかしたら、恒温槽を作る上で一番手間(と予算)がかかるのはヒートシンクかもしれません。とはいえ、それほどの性能を求めないなら充分に手の届く範囲で作れると思います。
 もっとも、温度をキッチリと制御する必用は無いのであれば、室温・冷蔵庫・冷凍庫で3段階の温度を作れますし、冷凍庫の強弱を使えば4段程度は作れます。校正に必用なのは雰囲気の正確な温度だけで、これがわかれば理論値と実測値の差から大体の校正パラメータを算出することができるはずです。
 ということで、当面の課題は信頼性の高い温度計の入手ということになります。一般的に市販されている温度計は分解能0.1℃、精度1℃程度だと思いますが、少なくとも0.1℃くらいの精度はほしい気がします。でも精度が1桁上がると値段が1桁上がる、という感じなので、何か別の方法を考えないとなぁ。

***追記
 そういえば、缶サットの時に買ったADT7420というアナデバのデジタル温度センサが残ってた気がする。
ADT7420 I2C超精密温度センサモジュール - ADT7420 - ネット販売
 常温周辺で±0.20℃保証というヤツ。サーミスタよりははるかに高信頼だし、I2Cのポートなら予約してあるので接続可能。
 それにしても、缶サットってもう4年も経つのかぁ。あの頃からあんまり進歩してない気がするなぁ。そろそろまた缶サットやりたいなぁ(って毎年言ってるなぁ)。

2017年2月22日水曜日

超音波流速計 とりあえずGUIに表示する


 新しい計算方法を使って気温と風速を計算し、それを表示するプログラムを作ってみました。
 簡単にそれらしくなるようにパラメータを設定しているだけなので、計器としてはダメですが、とりあえずそれらしい波形は出ている気がします。
 例えばセンサを左右に振ればその分が風速として出ますし、息を吹けばちゃんと気温の上昇が検出されます。

 そろそろ「人間よりはマシ」な気流を発生させる手段を考える必要がありそうです。風洞ほしいなぁ。

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

 とりあえず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回ほど計算する必要があるので、充分に計算負荷の軽い処理であることも求められます。
 さてどうしようか。

超音波風速計 温度の計測


 11時間ほど、位相と波形のログを取ってみました。まず時系列でサーミスタと位相から計算した温度です。横軸が時間[sec]、縦軸が温度で、青が位相から計算した温度[degC]、赤が位相から計算した温度とサーミスタの温度との差です。
 最後の30分ほど、明らかに誤差が増えています。このあたりは部屋の暖房を使っているので、それによる急激な温度変化があるのと、気流が発生しているのが、誤差の原因だと思います。サーミスタの温度によれば、およそ500秒の間に5℃上昇し、その後も1000秒ほどで0.5℃ほど上昇しています。サーミスタと超音波では時定数に大幅な違いがあるので、気温が上がり続け、それに伴い超音波風速計の観測値は上昇を続けながら、サーミスタは時定数で少し遅れた温度を表示しているため、気温が上昇しているのに誤差は一定、という結果になっているのだと思います。
 5千秒から3万7千秒あたりは誤差が±1℃未満で収まっているので、温度変化がゆっくりであれば誤差は少なく、これは時定数の差が問題にならない程度の変化だからだと思います。


 同じデータですが、こちらは横軸にサーミスタの温度[degC]、青が位相から計算した温度[degC]、赤がサーミスタと位相の温度差です。
 前回は19℃以上で誤差が増えましたが、今回は問題ありません。


 とりあえず、無風状態での温度計測は問題ないかな、という感じです。とはいえ位相が±12usec以上になると異常値となると思いますが。

 また、今回2万6千サンプルほど取りました。異常値が6個ほどあるので、あとで波形を確認してみようと思います。とはいえ、位相ログが1MB程度なのに対し、波形ログは140MBほどあるので、ファイルを開くだけでも一苦労です。そこからたった6組のデータを探すのは、大変だろうなぁ。まぁ発生時間はわかっているので、なんとかなるでしょう。

超音波風速計 はじめてのけいそく


 とりあえず、風速と気温を計測してみた。やっと「超音波風速計」として、風速計としてそれらしい表を書けるようになった。
 向きを変えて2回ずつ、それぞれで強さを変えて息を吹いているというグラフ。心の目で見れば山が4個あるが、ノイズだらけというか、強さの変化がわからないというか。2個目の山に比べれば3個目と4個目は短いので、「あぁ、息が続かなかったんだな」みたいな想像はできるかな。それと、おもったよりも気温の変化が少なそうだ。
 風速は無風時で-0.25mくらいのオフセットが有るが、これは超音波センサの設置精度とかいろいろ有るんだと思う。MICとSPを1個にできれば設置精度の問題はかなり軽くなるんだろうけど、そのようなセンサが入手できないのでどうしようもない。例えば1素子の超音波測距モジュールからトランスデューサだけ取ってくる、という方法もないわけではないが、測距モジュールが1個2.5kJPYくらいで、超音波素子MIC/SPセットより1桁高い。少なくとも6素子必用なので、単純計算で15kJPYくらいになる。MIC/SPセットなら6組買っても測距モジュール1個より安い。


 まだ中途半端なノイズが出る謎とかいろいろあるが、とりあえずなんとか形になりそうな気配はしてきた。
 ノイズを詳しく調べるために波形をすべてログに保存しようと思ってるんだが、位相データに比べて波形データは70倍くらいある。前回1万サンプルくらい取ったときの位相データが0.7MBくらいなので、同じ期間で45MBくらいは覚悟する必要がある。


 いままでは「もう少しで機能がn個増える!」みたいな段階だったけど、これからは「もしかしたら不具合が1個消えてくれるかも」みたいな段階なので、ちょっとつらい。でもとりあえず「センサ部をあと1個作れば2軸の風速が測れる!」とか、「センサ部をあと2個作れば3軸の風速が測れる!」みたいな切り札は残ってる。いつ使うべきか。


 温度成層風洞が欲しい。

超音波風速計 温度を計算してみる



 前回、温度と位相の関係を確認するためにある程度のサンプル数を取ってみたが、せっかく双方向の位相と実際の温度のテーブルが有るので、エクセルで位相から温度を計算してみた。横軸が実際の温度、青が位相から計算した温度、赤が観測値と計算値の差、となっている。当たり前だが、ノイズの部分は誤差が大きい。それから、温度と位相の関係がなかった部分(19℃以上)は観測値と計算値の差が出ている。それでも大半の部分は観測値と計算値の誤差が1.5℃未満で、ほとんどは1℃未満に収まっている。かなり優秀といえるはず。まぁ、観測した温度から予想される位相を計算して、観測した位相との差を補正値としてもたせてるから、誤差が少ないのは当たり前なんだが。


 最後に、温度から音速を計算するのと、音速から温度を計算する式。気温をケルビンとすればかなり単純な式で計算できる。



 今回は1位相分以上の温度変化がないので計算が楽だけど、1位相分以上のズレをどうやって確認するか。今の時期なら窓を開ければスグに下側は確認できそうだが、人間が先にやられる気がする。

 近頃の口癖:恒温槽欲しい

 ちなみに、今のプログラムは等価時間サンプリングを行うために、マイクの安定を待ってるから、計測時間が結構が長い。約2msecあるので、音速で70cmくらい進む。反射波が入ってくると都合がわるいので、超音波を強く反射するモノを40cm以内に置くのは良くない。ということで必用な恒温槽は内側の短辺が80cm以上、ということになる。もちろん吸音材を貼るとかして反射を減らせば問題ないはずだけど。風洞試験するときは結構つらいかも。吸音スポンジもデコボコしたやつを使うと悪影響がありそう。

超音波風速計 温度と位相を計ってみる


だいたい6000サンプルほど取ってみました。廊下とのドアを開ければ気温が下がるし、ストーブをつければ温まる、北海道は便利ですね(やせがまん。
 縦軸がゼロクロスの時間でマイクロ秒、横軸がサーミスタで計測した温度で℃です。ゼロクロスの時間はCh0とCh1の双方から計測した値の平均を使用しています。一応風速による影響をキャンセルしているはずです。
 青が実際に計測した値で、赤は温度25℃の時と、現在の気温との時間差です。例えば、17℃の時は25℃の時と比べて6ナノ秒遅くなる、ということが読み取れます。

 19℃以上ではほとんど変化がありませんが、19℃以下ではかなり温度と相関が有ります。所々でノイズが有ったり、実測値が若干太かったりしますが、おおよそ気温と位相差に十分な相関がありそうです。
 計算上では25℃と26℃では725ナノ秒ほどの違いが有ります。今のプログラムでは時間分解能が0.11...マイクロ秒(1/9マイクロ秒)ほどなので、風速がゼロなら温度分解能は0.16℃ほどでしょうか。

 やっぱり動作確認するのに恒温槽がほしい。欲を言えば温度成層風洞。温度変化が少なくなる保温容器くらいなら簡単に作れると思うけど、一定の温度を設定できる恒温槽を作るのはかなり大変です。温度計を校正するための恒温槽を校正するのに、さらに高精度な温度計が必要になる。恒温槽を作るくらいなら高精度な温度計を買ってきて、温度変化の少ない箱に超音波風速計と一緒に入れて差を取るほうが楽だと思います。
 考えなしに超音波風速計を作りたいと思ってやってきましたが、どんどん大事になってきました。どーしよ。

2017年2月18日土曜日

超音波風速計 非対称な位相差の謎


 いくつか変な動きがあって、直接ADCのデータを見たくなったので、USARTを450kbaudにしてバッファを出力できるようにしてみた。いつもは115.2kbaudで、4倍くらいだけど、かなり早く感じる。

 波形を取り出したついでに35サンプル分くらい重ねてみた。アイパターンならひどいもんだけど、位相差に情報があるので、こんなもんだろう。



 無風と向きを変えた風で、3パターンの波形がこれ。無風時はほぼ位相差が無い(若干の位相差は工作精度の問題)。下の2波は風向が逆なのでチャンネルごとの位相のズレが逆転しているが、とりあえず位相差が出ているのはわかる。
 問題なのは、この際の位相ズレが非対称に起きているということ。位相遅れは3usecほど、位相進みは4.5usecほどある。風速に換算すると、それぞれ2.5m/sと3.6m/sほどとなる。双方ともほぼ同じタイミングで計測しているから、こんなにズレることはありえないはずだ。

 いろいろ計算してみると、無風時と有風時で流体の温度を1℃変えると実測値に近い結果となった。
 風は息を吹いて作ってるから、流体の温度変化が反映されている、というのはありそうな気もする。吐息の温度が室温+1℃程度なわけがないと思うのだが、ちょっと離れたところから吹いて雰囲気と混合されると温度が下がるのかな、とかいろいろ要素は考えられる。

 まだ確定じゃないが、意外と風速よりも温度のほうが変化が大きそうだ。知識として超音波風速計なら気温も測れるとは知ってるけど、ここまで強く出てくるとは。
 超音波は、風速計というより、流体の温度を測るセンサとしてのほうが感度が高いかもしれない。温度を測りたいなら定番だと熱電対だが、形状にもよるけど、気体に対しては時定数が数百秒ほど有るので、数m/s程度の気体の温度を分解能0.5℃くらいで90%時定数0.1秒未満で測りたい、みたいな用途に良いかも。どんなところでそんなの測りたいか知らないけど。

 とりあえずこの位相差の非対称性が本当に温度の違いなのか、別の要素なのかを確認する必要がある。やっぱり風洞欲しい。とりあえずヒートガンで冷風当てて確認かなぁ。

温度を測ってみる


 TIMのADCでサーミスタの電圧を計測し、マイコン内で温度の計算までを行ってみた。室温が25℃ほど、温かいのは指でつまんだ時、冷えているのはティッシュをかぶせてパーツクリーナーを吹いた時。氷点下10℃になるとか潜熱凄まじい(温度センサが正しいのであれば。


 今回、STM32F103CBTを使っており、このマイコンにはADCが2本乗っているが、まずは超音波MICにつながっているADCを転用した。しかしこれがかなり面倒だった。
 超音波MICを正確なタイミングでADCを行うために、ADCの変換開始はTIMのトリガを使っている。が、温度の変換であればTIMでトリガをする必用はないので、ソフトウェアで変換開始を指示できれば手っ取り早い。しかし、StdPeriphLibにはADC_Init以外に外部トリガを変更する関数がみつからなかった。もちろん自前でレジスタを叩いて変更することもできるはずだが、今回は別の方法を選んだ。
 まず試したのはTIM_GenerateEventでTriggerイベントを発生させることだった。STM32F1のTIMにはソフトウェアからイベントを発生させられるので、コレでADCの変換ができれば非常に簡単なのだが、どうやらそのような動作はできないらしい。
 しょうがないので、別の方法でイベントを発生させる必要がある。ということで、次に試したのがTIM自体を回すという方法。しかし複数回の変換トリガがかかってしまうと具合がわるいので、1回だけTIMが動いて欲しい。ということで予めSelectOnePulseModeでSingleモードにし、その後CmdでTIMを開始、直後に停止。その後でRepetitiveモードに戻す、という動作を行った。もしかしたら直後にTIMを止めているのに不都合があるかもしれないが、とりあえず今のところは動いている。
 あとはADCの変換終了を待ち、レジスタを読んで計算を行う、という感じで、特記するところはない。


 なぜADCはGenerateEventで動かないかという話だが、ADCのトリガ入力はちょっと独特で、実際にエッジがペリフェラルから出力される必要がある。そのためTIMのOCなどでADCをトリガする際は、OutputStateにEnableを設定する必要がある(TIMのOCでDMAをトリガする際はOutputStateがDisableでも問題ない)。
 GenerateEventは、リファレンスマニュアルにはTGをセットした場合、「SR.TIFがセットされ、有効な場合は割り込みやDMA転送が発生する」というような事が書いてある(割り込みが発生するのはSR.TIFの影響?)。TG以外はというと、OCの場合も似たようなもので、割り込みフラグのセットやDMA転送のトリガしか書かれておらず、OC状態が変化するとは書かれていない。
 ADCはペリフェラル間を直結したルートではなく、GPIOに近いところでエッジを検出しているので、実際にペリフェラルからパルスが出力されないGenerateEventでは動作しないのではないか、と思う。

 STM32F1のペリフェラル連携はこういうちょっと残念なところがたまにある。
 そもそもTIMのタイミングで何かを行いたい場合、大抵はDMA転送で事足りる。例えば1秒に100回、UARTで1バイトを送信したいなら、TIMからDMAにトリガがかかり、DMAがUART->DRにデータを渡し、それによりUART転送が始まる。SPIも同様で、TIMから直接UARTやSPIにタイミングが使われることはないはず。DAC(デジタル・アナログコンバータ)もDMA転送を経由する。
 ということを考えると、ADCとTIMの接続は、STM32F1のペリフェラル間連携ではかなり特殊な事例といえるはず。
 

 今のところ、PA0-5を超音波MIC、PB0-5, PB10-15を超音波SPに割り当てており、PA9, 10はUSART1、11以降はSTBee Miniのデフォルト機能が接続されている。残りはPA7, 8とPB6-9で、ADCを接続できるのはPA7のみ。PB8, 9はCANに予約で、PB6, 7はI2C1に予約かな。とりあえず空きはアナログ入力が1、GPIOはアナログも含めれば3箇所となる。ここまでピンを最大限使うのもかなり久しぶりな気がする。



ADC_RegularChannelConfig(ADC1, ADC_Channel_6, 1, ADC_SampleTime_28Cycles5);
ADC_ClearFlag(ADC1, ADC_FLAG_EOC);

TIM_GenerateEvent(TIM3, TIM_EventSource_Update);
TIM_SelectOnePulseMode(TIM3, TIM_OPMode_Single);
TIM_Cmd(TIM3, ENABLE);
TIM_Cmd(TIM3, DISABLE);
TIM_SelectOnePulseMode(TIM3, TIM_OPMode_Repetitive);

while (!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC));

uint16_t value = ADC_GetConversionValue(ADC1);
const float Vin = 3.3f;
const float R2 = 18;
const float T0 = 25;
const float R0 = 10;
const float B = 3380;

float Vout = value * Vin / 4096;
float Rth = (Vin - Vout) / (Vout / R2);
float tempC = 1 / ((log(Rth / R0) / B) + 1 / (T0 + 273.15f)) - 273.15f;

printf("Rth:%f kOhm\n", Rth);
printf("tmp:%f degC\n", tempC);

2017年2月17日金曜日

サーミスタの温度を計算する


 ご存知の通りMS Officeスイートは文字なり表なりを選択してCtrl-CでクリップボードにコピーしててきとーなドローソフトでCtrl-Vをすれば画像として保存できるんだが、すさまじい解像度が有る。

 とりあえず分圧回路の電圧から温度を計算する方法を考えてみた。間違ってたらごめんね。サーミスタ1つと抵抗1つの受動的な回路でも、様々な組み合わせがある。今回はその内で、サーミスタが電源側、固定抵抗がGND側の分圧抵抗を選んでみた。理由は特になくてきとーに選んだだけだが、とりあえずセンサの配線が断線すればADCは下限に張り付くし、短絡すれば上限に張り付くという判断が行える。もっとも、抵抗を逆にすれば解放で上限側、短絡で下限側となるので、どっちが好きかとかそういう話になる。厳密にはいろいろ有るんだろうけど、とりあえず動けばいいのでキニシナイ。

 以下のテキストボックスに必用な数値を入れればサーミスタの抵抗値(Rth)と温度(temp)を計算できる。とりあえずデフォルト値は手持ちのサーミスタの値を入れてある。
 入力値のチェックとかはしてないので、変な値を入れると変な動きをするのでやらないように。
 VinとR2は回路に合わせて設定し、B, R0, T0はサーミスタに合わせて設定する。Voutを変えればRthとtempが得られる。


Vin Volt
Vout Volt
R2
B degK
R0
T0 degC
Rth
temp degC
計算式は前述のとおりだが、基本的に加減と除算のみで計算できる。ただし1箇所だけlog eが出てきて、コイツが難関な気がする。
 一番、実行時のパフォーマンスが高い方法は、ADCの入力値から温度の値のテーブルを予め与えておくことだが、温度を8bit精度にしたってテーブルは4KiBになるし、±60℃の範囲でも0.5℃程度の分解能しか無い。5℃くらいの精度で十分、とか言ってたんだから0.5℃でも十分といえば充分なのだけど。そもそも抵抗やらADCやらサーミスタ自体やら、全て未校正で組んでそんな精度出るわけ無いだろ、と考えれば0.5℃でも充分なのかも。

 とりあえず次はマイコンで温度を計算する処理を組み込んでみて。なんかそのあたりで超音波風速計も飽きてくる気がするなぁ。

超音波風速計(番外編) 温度計を考える


昔買ってあったサーミスタの特性をグラフにしてみた。R, C, Zoutは中央の対数スケール、Voutは右の線形スケール。
 25℃の時に0.12mAになるよーに、という指定を守ると、だいたい0℃から35℃あたりで線形近似できるっぽい?電圧がだいたい0.5V-2.5Vというのも能動的アナログ素子禁止縛りプレイ中の今回は便利。出力インピーダンスは最大で25kΩあたりだが、この程度ならSTMに直結できるのでインピーダンス変換の必用もなし。

 しかし、このサーミスタ、時定数を下げるためかやたらと小さい。米粒よりも小さいぞ。それでも時定数4secだから、超音波風速計で測るより数桁遅い。超音波ってすごいねぇ。ナミ、スゴイ。

超音波風速計 とりあえずそれっぽい感じの何か


 C#のChartでリアルタイムに風速を表示してみた。息を吹いたりヒートガンで風当てたりすると波形が動くので気分が高揚します。途中で尖いピークが有るのはノイズだと思う。ほとんどのパラメータは固定だし、風速計としての性能はろくなもんじゃないが、とりあえずこういう画面があれば多少はモチベーションが維持できる。といいな。

 いまは2chしか計測してないので、10Hz近い速度で更新できてると思う。可動部がないので、回転式とくらべてもはるかに追従性が高いと思う。少なくとも手持ちの安い風速計じゃ「すごく熱いものを食べてホフホフする」くらいの息遣いではセンサの回転が止まらないし、超音波風速計ならちゃんと山と谷が見える。


 ちゃんと動作してるか確認するのは、やっぱり風洞とかほしいなぁ。あとはやく3軸化したい。

2017年2月16日木曜日

超音波風速計 時間を測りたい



 青のRAWがADCから受け取った値をFIRに通してAC結合した値、赤のETSが等価時間サンプリングで時間分解能を14倍にした値です。2枚目と3枚目は1枚目の一部を拡大した図になります。
 横軸はマイクロ秒単位です。縦軸にも数字がありますが、高さを示すラベル以上の意味はありません。

 実時間サンプリングの青に比べ、等価時間サンプリングの赤は横方向の分解能が高いのがわかると思います。
 縦軸はFIRの処理の関係で1bitあたりの分解能が決まりますが、結果をS16bitの変数に入れてるので、まだ5bitの余裕があります。32倍くらい分解能を上げられます。


 超音波がマイクに届くまでの時間は、RAWの値が500を超えるくらいを閾値にして検出すると、おおよそそれっぽい値が取れそうな気がします。波形の振幅幅によって閾値に達する時間が変わりますが、正確な数字はETSのゼロクロスで補正できると思います。


 遅まきながら、先人たちが超音波風速計を作ったときの方法を確認してみたところ、アナログ回路で増幅とAM復調を行い、閾値を超えるタイミングをタイマで検出しているようです。
 タイマでパルス幅を検出するのであれば、ADCよりケタ違いに時間分解能が高いので、AM復調でも充分な分解能が有るようです。
 しかし、今回はすべての処理をデジタルで行っているので、ADCの時間分解能がそのまま分解能になってしまいます。ETSは正弦波の立ち上がりには使えないので、単純なAM復調では処理できません。ハードウェア楽な分、ソフトウェアで苦労しているといえます。
 某社が作っている自衛隊向け無線機もソフトウェア無線化されており、機材の低価格化等を行っているようですが、ソフトウェア開発は大変だろうなぁ。ま、超音波はRFとくらべて周波数が5,6桁低いので、こっちは比べるまでもなくかなり楽なんでしょうが。

***追記
 

 3枚目の図の階段グラフを作ってみた。こっちのほうが実時間サンプリング(RTS)と等価時間サンプリング(ETS)の差がわかりやすい。
 RTSの分解能は1.556...マイクロ秒、ETSの分解能は0.111...マイクロ秒。風速換算でRTSが1.3m/s、ETSが0.088m/s程度となる。

*** 追記


 今更になってデータのとり間違いに気がつくなど。。。
 一番上の画像の波形の立ち上がりは、マイクの立ち上がりじゃなくて、FIRフィルタの立ち上がりである。ETSを行う上で波形が安定するまで(1.5msecくらい)待ってからADCを開始していたのを忘れていた。
 ということで、正しいマイクの立ち上がりはこの画像。青がADCの値で右軸のが電圧。赤がFIRを通した後。FIRの遅れは補正済み。
 ADC直後の生データは小さなノイズが乗っていて、FIRでだいぶ消えている。図らずもバンドパスフィルタの動作確認をしてしまった。

 FIRを通した後の波形は安定時で30000くらいだが、立ち上がりでは1フェーズあたり2000くらいのペースで15-20フェーズくらいかけてゆっくりと立ち上がってる。しかし風が当たれば波の高さが変わるから、特定の閾値で到達時間を測るのは無理そう。


 前回も少し触れたが、気温が30℃ほど変化すると1位相変化する。例えば25℃と-7℃では1位相変化し、25℃と-35℃では2位相変化する(センサ間150mmの場合)。北海道においては、-35℃というのはほぼないが、-7℃くらいはよくあるし、-21℃あたりも無くはない。位相差のみで音速を計算しようとすると大きな気温の変化に対応できないため、位相差以外で音速の変化を計測できないかと思ったわけだが、波形の立ち上がりを見る限り、結構大変そうだ。
 とりあえず、STMのADCにサーミスタでもつないで外部の温度を測って、その上で細かいところは位相差で計測、という感じになるかな。外部の温度を5℃程度の精度で計測できれば、位相差から音速を測り、音速から気温を求めることで、もう少し細かい気温が把握できるはず。どうせ風速計を作るなら温度センサを内蔵した気圧センサとか付けたほうが良いかも。でもそうすると湿度も測りたくなるという罠。まぁ多機能化はのちのち。

超音波風速計 ぶれっどぼーど


 写真を撮った後に間違いに気づいて修正したところがあるけど、だいたいこんな感じ。入出力ともに4ch分を配線してあるが、ADCは分圧抵抗が2ch分しかついてない。
 PWM出力はパスコンでDC成分を消した上で超音波SPに接続、アナログ入力はパスコンでAC結合して分圧抵抗でレベルを移動した後ADCに直結。PWM側はソフトウェアでDC成分を消せるので、SPと直結も可能。この回路で一番複雑なのは分圧抵抗じゃないかなぁ。

 SPとMICを並べて双方向で時間を計測できるようにしてある。それぞれの組み合わせでセンサの距離が微妙に違うので、その分の差はあるが、2LSB程度の差なので誤差の範囲な感じ。2LSBだと0.08mmくらいの精度。インシュロックでぐいっと引っ張って固定してこんな精度になるのかなぁ。
 もしも、12.5±5usecくらいずれてるなら、それはマイクの位相が逆なので、配線を入れ替えること。

 試しに1回吹いてみたら、時間差は4.3usecくらいだった。およそ3.5m/sに相当。軽く強めに息を吹いたらこれくらいかな、という感じ。


 今のところ、計測しているのは位相差だけで、「Time of Flight」みたいな値は取っていない。でも、双方向を平均して音速を計算してから風速を計算する、ということをやるなら、ToFは必須だと思う。どうやって正確な時間を測れば良いんだろうか。少なくとも10usecの精度で計測する必要がある。
 例えば25℃から15℃変化すると、風速が150mmで10usecほど変化する。つまり、双方向の平均と校正値のズレから風速を計算した場合、位相差を見るだけでは校正した気温±10℃程度の範囲でしか使用できない。北海道だと真夏と真冬でΔtが50℃くらいあるので、通年で使うなら位相差だけでは足りない。
 解決策が無いわけではなく、例えば精度が10℃程度で温度を測れる手段があれば、それで位相の変位量を補正して音速を計算する、とかできるはず。
 もっとも今の段階でそんな話をしてもとらぬ狸のなんとやら、なわけだが。

2017年2月15日水曜日

超音波風速計 マイコンでFIRとETSしてみた


 タイトル通りです。マイコン内でADCから読んだ値をFIRでAC結合し、それを等価時間サンプリングで9Msps相当にしてUARTにダンプ、未加工でグラフ化です(横軸のナノ秒だけExcelで計算してますが)。
 青が無風、赤と緑が息を吹いているときですが、安物の風速計を信用するならこの時の風速はそれぞれ2m/s程度だと思います。
 最初の1フェーズくらいは波形が安定せず、繰り返し信号とならないため等価時間サンプリングが異常値となります(波形の安定以外にも、フィルタの初期値の分もありそう)。ただ波形が安定してしまえば、マイコン内の処理でもかなり綺麗にできてる気がします。
 FIRは整数処理の関数を作って、次数は63です。2000サンプルを通すのに70msecかかっているので、PWM-ADCの5msec程度を大幅に超えています。もっとも、結構綺麗な波形なので、もっと短い期間でも充分な気がします。


 超音波風速計はいままで散々苦労したので、今回ももっと大変だろうなぁと思っていたのに、なんか拍子抜けするくらい簡単にここまで来ています。心配になってくるレベル。あと何日かすれば1次元の簡易風速は出せそう。そこから多軸化するのが大変だろうけど、それにしたって回路の追加はほとんど無いし。気を抜いてやる気を失ったりしないように気をつけて、もうちょっと頑張ろう。

超音波風速計 贅沢にペリフェラルをつかってみた



 TIM1本をディレイに使ってみた。結論から言うと、あんまりよろしくない気がする。ADC変換を行っていないときと、ADC変換を行っているときでは、マイコンに吸われる電流が違い、それが波形を乱している気がする。なので2000サンプルで8組分の等価時間サンプリングが可能だが、少なくとも最初の1組は読み捨てる必要がありそうだ。
 次のテとしては、ADCのDMAをサーキュラモードにして、最初の1周3ミリ秒を読み捨てて、次の3ミリ秒(2週目)を使う、といった感じかな。でも本来読み捨ては1msec程度で充分なので、無駄に2msecかかることになる。ま、それでも1chあたり10msecで8ch測ったとしても0.1秒未満なわけだが。

 あと等価時間サンプリングにこだわる必用はない気がする。うまく位相を計測するアルゴリズムを考える必要があるが。
 PCで処理するならBPF通してDC成分抜いてから位相を90度ずらしてAtan2に突っ込んで直線に変換して、とかいろいろできそうなんだが、浮動小数点演算を使いたくないのでもうちょっと軽いアルゴリズムが必用。こういうところはF4を使いたくなるねぇ。

 位相を検出したりするのはいろんな用途が有るので、方法もいろいろあるのだが、ADCからの生データはDCオフセットがあるのがつらそう。デジタルフィルタを通してAC結合してから位相比較になるのかな。


 現在使ってるハードウェアリソース
・TIM2(PWMのタイミング:80kHz)
・DMA1-2(PWM波形の転送)
・TIM4(ADC開始タイミングのディレイ:1MHz、TIM2のスレーブ)
・TIM3(ADCトリガ:642.85714kHz:TIM4のスレーブ)
・DMA1-1(ADCの転送)

 もーちょっとTIMが柔軟だったら、と思うんだが、できないことはしょうがないから他の方法で工夫しないと。
 でっかいホワイトボード欲しい。ある程度の広さの作業空間とセットで。