一次ローパスフィルタと移動平均の周波数特性の測定
こんばんは、Operaです。
今回も
に便乗して溜めてたネタを放出していこうと思います、ローパスフィルタ系の記事の最終記事です。今回のネタはソフトウェアでの一次ローパスフィルタと移動平均の周波数特性の調査です。
測定プログラムを書くのには無駄に苦労しましたがネタ自体は単純なのでパパっと測定結果を出して終わりです。
前々々回記事→
前々回記事→
1.測定条件
今回はプログラムを実時間ベースで走らせるため、移動平均のほうは単位をサンプル数とかの無次元数から時間[sec]に変更しました。
測定周波数:1Hz-1MHz
タイムステップ:0.1us
一次ローパスフィルタ時定数:1ms
移動平均サンプル数:10000回(タイムステップ/時定数の値)
2.測定結果
まず、一次ローパスフィルタの周波数特性です。
こちらはゲインについては教科書通り、一次ローパスフィルタのカットオフ周波数(f=1/2πτ=160Hzあたり)のあたりから減衰が始まっていますね。
減衰量についても-20dB/decであり、こちらも教科書どおりとなっています。
位相についても同様にカットオフ周波数時に45度遅れておりいい感じです。
また、周波数が100kHzを超えたあたりからグラフが汚くなっていますが、これはプログラムのタイムステップに近づいてきたことによるノイズのようです。
もしかしたら周波数特性の測定プログラムがガバくて正しく拾えてない気もしなくもない...
次に、移動平均を取った時の周波数特性です。
こちらは位相については乱れまくりでもはや見づらいです、測定プログラムでは微分をして出力信号の頂点を出しているので、タイミングによってはこうなってしまうようです。
ゲインについては山を描きながら減衰しています。
これは移動平均の原理に原因があり、サンプルした区間が信号の周期と重なると周期信号をn周期分足し合わせることになり、結果ゲインが一気に下がってしまいます。
ただし、概形自体は一次ローパスフィルタに近く、減衰量も-20dB/decあたりになっていること、減衰が始まる周波数も160Hz付近に近いことを考えると基本的な特性は一次ローパスフィルタと同様なようです。
3.まとめ
結果として、所謂ローパスフィルタとして扱われるアナログ的な特性を持つ一次ローパスフィルタと比較すると、移動平均の場合は位相はうまく取得できなかったので置いておくとしてゲインについては周波数に応じ単調減少ではなく、極値を多く持っていることが分かりました。
今までの検証により移動平均のほうが配列がメモリを使う代わりに計算時間が少ないことが分かっていますが、このような不安定な特性があると実際にセンシングした信号を整えるなどの用途に使おうとすると微妙かなぁと思います。
個人的にはこの手の用事があるときは一次ローパスフィルタを使っていきたいかなと思いました。
スポンサーサイト
ソフトウェアでの一次ローパスフィルタの実装
こんばんは、Operaです。
今回もUEC koken Advent Calendar 2018に便乗して溜めてたネタを放出していこうと思います。
前回前々回に引き続き安定の極道入稿というか既に日付を超えています、書き始めたのはカレンダーの日なのでセーフということにしておきましょう。
今回のネタは前回取り扱った移動平均と同じく高周波の成分を減衰させる一次ローパスフィルタのソフトウェアでの実装を行います。
1.一次ローパスフィルタの計算式の導出
まず、プログラムで実装するために一次ローパスフィルタとして有名なRCフィルタ回路を題材に計算式を導出してみます。
ブログに数式を埋め込むのが面倒なので説明画像を出します。
お分かりいただけましたでしょうか。要するに最後の式を入れればOKというわけです。
2.ソフトウェアでの実装方法
次に、この数式をソフトウェアに入力してします。
今回はマイコンでのセンシングを想定しているので、⊿tは実際のところはセンサ読み取りの割り込み周期になるかと思います。
まあこんなもんですかね、内容自体はメモリも食わないしかなりシンプルです。
3.実行結果
試しにDT=0.01、TAU=1でステップ応答を取ってみました。
ステップの開始時間は1秒です。
結果として見事なステップ応答が得られました。
次の記事では周波数応答などにも触れていきたいなと思います。
マイコンでのセンシング向け軽量な移動平均の実装方法 後編
こんばんは、Operaです。
今回もUEC koken Advent Calendar 2018に便乗して溜めてたネタを放出していこうと思います。
今回のネタは自身初(?)のプログラミング系、マイコンでのセンシング向け軽量な移動平均の実装方法です。
前回記事では移動平均の計算において、毎度平均を取るという手法を取りました。
その結果、サンプル数を増やすと計算時間が比例増加するという問題が発生し、十分なサンプル数を確保したい際には計算時間が必要になってしまうことが分かりました。
今回記事では別の実装方法の説明とその評価を行います。
3.軽量な移動平均の実装方法
移動平均の別の実装方法は移動平均の特性を利用し、平均を毎回取らないことによって計算回数を最小限に抑えます。
以下の図を見て分かる通り、移動平均の計算式では毎度平均値を取っていますが、新しい値以外は既に前回平均値を計算したのに再度計算をしていて無駄に計算数が増えています。
そこで、移動平均の計算を簡略化するとなると前回計算した平均値に新しい値を加算し、またサンプル数に応じたn回前の古い値を減算してしまえば展開時の計算式は移動平均の元の式と同じのまま、計算数を減らすことができます。
※最初3回分はサンプリングが必要なため軽量版の数式が異なります
これをプログラムに実装するとソースコードは以下のようになります。
アルゴリズムとしては、古い値の減算を行うためにサンプル数のサイズの配列を確保し、その配列うち利用する位置を変更しながら配列の中身を新しいデータへとアップデートしていきます。
また、resultとtemp配列はstaticで定義しています。
temp配列は最初に初期化することで最初に配列が一周するまでに数式が変わるという問題をクリアし、例外処置なしでプログラムを回せるようにしています。
この関数を呼び出す際は以下のように現在の値を引数として渡して呼び出します。
そして、その実行結果は以下のようになります。サンプル数は3です。
前回のプログラムでは142usかかっているので若干高速化されていますね。
同様に、サンプル数5, 10の際の結果は以下のようになります。
サンプル数と実行時間の関係は以下のようになります。
青は前回の実行時間、オレンジが今回の実行時間になります。
何故かサンプル数が増えると遅くなるどころか速くなっていますが、これは恐らく最初temp配列の中身が初期化され0のときに計算時間が短く済むため若干速くなっているためだと考えられます。
今回は元の測定データの配列の大きさが30と小さいためそういうミクロな影響が表面化するのでしょう、アルゴリズム的にはサンプル数を増やしても実行時間は一定ということになります。
4.まとめ
というわけで、軽量な移動平均の実装方法とその評価を行ってきました。
実際にこの関数を利用する場合には、センシングしたデータを関数に渡し、それを無限ループで回して続けていくことになるかと思います。
やっぱりセンサのデータは数回平均化しただけじゃノイズが取り切れないので、こういう平均のサンプル数により計算時間が変化しないアルゴリズムを使ってあげるとマイコンのクソザコCPUをいたわていいですね。
マイコンでのセンシング向け軽量な移動平均の実装方法 前編
こんばんは、Operaです。
今回もUEC koken Advent Calendar 2018に便乗して溜めてたネタを放出していこうと思います。
今回のネタは自身初(?)のプログラミング系、マイコンでのセンシング向け軽量な移動平均の実装方法です。
1.はじめに
移動平均とは何かといいますと、時系列などで連続したデータ(ここではセンサの測定データとします)において、生の値だとノイズが強い場合に前後のある区間の値を平均するという処理を加える一種のローパスフィルタ的な処理のことです。
これについては説明を書いているサイトがいくらでもあるのでこれ以上は省略します。
んでもって、その移動平均はマイコンでのセンシングにおいて大いに役立つのでそれを軽量に計算しようというお話が今回のネタになります。
前編ではよくExcelとかで移動平均を実装するときに脳死で実装しているような内容をそのままプログラムにした場合の計算時間の評価を行います。
2.簡単な移動平均の実装方法とその計算時間の評価
例として、以下のような配列に移動平均を適用してみます。
所謂移動平均の場合、時系列データで前後のデータを取得しますが、センシングの場合未来のデータは取得できないので前のデータを取得することとします。
とりあえず、処理のためにmbedで適当にプログラムを書いてみました。
movingAverage関数が受け取った配列を基に移動平均を計算するプログラムです。
アルゴリズムとしては、単純にサンプル数の数だけ本来の値と共に過去の値を足し合わせ平均を取るという単純なものになっています。
今後のために計算において配列の10個目の値からスタートしています。
また、計算時間を計測するためにmbedのタイマー機能を利用しています。
そして実行結果は以下のようになります、最初10個は飛ばしているので値はゼロです。
実行環境は前回の記事、中華STM32F103C8ボードBlue Pillをmbedで使うで取り上げたBlue Pillです。
配列の特性上本来の値の一つ前の値になっていますね、どうやら正しく計算できているようです。
計算時間は148usです、意外とかかっていますね。
では、このプログラムですがサンプル数が増えたらどうなるでしょうか。
試しにサンプル数を5にしてみると、結果は以下のようになり、計算時間が241usに増えます。
更に、サンプル数を10にしてみると476usもかかってしまいます。
この時間の増え方...線形っぽい...!
どう見てもサンプル数に対して計算時間が線形増加です。
これじゃフィルタを強めにかけたいとなると無限に実行時間が増えてしまいますね。
さて、これではたくさんサンプルを取ってから移動平均を取って綺麗なデータが欲しいみたいな需要があるときには大変困ってしまいます。
後編ではこの移動平均について、軽量な実装方法の説明とその評価を行います。
中華STM32F103C8ボードBlue Pillをmbedで使う
こんにちは、Operaです。
所属している電気通信大学工学研究部のアドベントカレンダー企画に便乗して更新していきます。
1.はじめに
皆さんmbed使ってますか!
mbedはタイマー周りがソフトウェア実装になっているあたりに不満はありますが、その他はわりかし使いやすくて趣味レベルの開発では十分に使えるものだと思います。
高度な機能が必要ならレジスタ叩けば実装できますしね。
ただし、それよりも大きな問題がありmbedを使おうとすると如何せんボードが高いです。
Arduino UNO(3000円)に比べたらNucleo Boardシリーズ(1500円)は安いですが、それでも機器につけっぱなしにしたり燃えるの承知で使うのを考えると少しばかし使い勝手が悪いです。
そこで頼りになるのが我らが中国の怪しい中華マイコンボードです。
例に漏れず、STMマイコンにも怪しい中華ボードがあり、それがSTM32F103C8を搭載したBlue Pillです。
スペック、回路図などはWikiを参照すべし→Blue Pill
実売価格はAmazonだと500円ほどと高いですが、Aliexpressで本場中国から輸入すれば200円程度で手に入れることができます。
この価格帯なら普通のマイコンと同じ価格まで下がるので多少無茶して燃えても痛くも痒くもありませんね。
ただ、価格帯が安すぎるゆえにはんだ付けがガバくてピン間がブリッジしていたりする(実体験)個体もあるので、届いたら修正の必要がある可能性はあります。
この記事ではそんなBlue Pillをmbedとして使う方法についてまとめたいと思います。
2.用意するもの
必要なのは以下のとおりです。
・Blue Pill本体
・ST-Link(Nucleo Boardを使うのがよい)
・mbed開発環境の準備(アカウントを登録しよう)
Blue PillはNucleo Boardとは違ってライターが内蔵されていないため、USBを繋いで簡単書き込みとはいきません。
また、USB端子はついていますがこれはマイコンのピンに繋がっているためここにUSBを繋ぐとUARTで繋がるみたいな機能はないです。
Nucleo Boardを使う際にはST-Link部分を折って使いましょう(折るときに怨念でピンが指に刺さりやすいので気をつけて折る)。
3.配線
配線はシンプルで、Nucleo BoardのST-Link側に出ているピンの中からGND, 3.3V, SWCLK, SWDIOをBlue Pill上面のピンに接続すればOKです。
UARTを使いたければ加えてTX, RXもBlue Pill側の該当するピンに繋げれば使えます。
Nucleo Boardの首を折ったST-Linkの場合、まず回路図は以下のようになっています。
これを見る限り、一応ピンとして必要なピンは出ているようですね。
実際の首部分では以下のように配置されています。
あとはこれに従って接続すればOKです、Blue Pill側はなんとシルクの上に書き込みピンがあるからシルクが読めないというガバガバ設計っぷりですが一応横からピン配置は読むことができます、裏にも書いてあるのでそのほうが読みやすいです。
接続はこれで終わりになります。
4.書き込み
これでハードウェアの準備が終わったのであとはソフトウェアを書き込むだけです。
まず、mbedのプロジェクトを作ります。
この際、どのボードを選べばいいかという問題がありますがピン数の多いNUCLEO-F103RBを選べばレジスタが共通っぽいので大丈夫です。
I/Oピンの指定などはBlue Pill側のPA_1などの名前をそのまま使って定義をすることができます。
お試しとしてはPC_13がUSER LEDになっているのでこれでLチカプログラムを書くといいでしょう。
プログラムの書き込みの手順はおおまかにはmbed対応のボードと共通ですが一部異なり、以下の通りになります。
・ボードとST-Linkを結線してからUSB接続する
・binファイルは二度書き込む
・Resetボタンを押して起動
まず、ST-LinkをUSB接続する際、Blue Pillを接続する前にPCに接続してしまうとマイコンなしと認識され書き込みできなくなるため、ST-LinkとBlue Pillを接続してからUSB接続する必要があります。
これはNucleo Boardの首を折った後のマイコン側に書き込みする際も同じですね。
次に、binファイルを認識されたST-Linkのドライブに書き込みますが、一度目の書き込みは転送がすぐに終わり実際にはうまく書き込めません。
もう一度転送すると今度はファイル転送に時間がかかり、ファイルが正しく書き込まれます。
あとはボード上のResetボタンを押せばBlue Pillが立ち上がります。
二度書き込む理由は不明ですがまあ使えているのでいいとしましょう。
5.おわりに
以上が中華STMボードBlue Pillの使い方になります。
わりかし安くマイコンボードを使えるんで、量産用途とかにも使いやすいかなぁと思います。
実は入手がAmazonでボッタクリ価格500円で買うか中国からAliexressで200円で買うかが悩みどころで一番難しいみたいなところはありますが、ぜひ使ってみてください。