Arduinoで、オモチャオシロを作る上で、FFTで周波数
表示機能も欲しいんだけど、2KBのSRAMで収まるのか
を確認するために、テストプログラムなどをゴニョゴニョ。
昨日の、空きメモリ計算しようとすると、
「r28 cannot be used in asm here」
とか出てきちゃうのは、色々とBBSなんかを眺めていると、
他にも困ってる人がいるっぽい。でも、原因はまだ不明
な感じ。
色々、テストパターンを試して、どんなときに起きるのか
を調べてみたんだけど、ちゃんと切り分けできるところ
まではいけなかった。
でも、なんとなくどんなときに起きるのかは、少し
判った。
特定の関数を、特定の呼び出し方(引き数の指定)で
呼び出すときに、なぜかFFTライブラリが悪さして、
プログラム全体でこんなエラーでコンパイルが
はじかれるみたい。
それらの関数では、charが引き数だったり、その前に
fprintfでゴニョゴニョと数値文字列変換をやって
いたりというのが、なんとなく置きに召さないっぽい。
具体的には、printfで空きメモリを表示させるか、
LCDに表示するか、という関数類で発生してるみたい。
FFTライブラリの中身(実体)はインラインアセンブラ
で書かれているので、具体的にナニが悪いのかを
突き止めるのは難しそう。型変換周りなのかなぁ?
と思って、型変換関係のウォーニングをすべて
取り除いたんだけど、消えなかった。
ただ、一つ得たものがあった。空きメモリを調査
するためのライブラリが悪さしてるのかと思って、
独自に空きメモリを計算する処理を、
http://jeelabs.org/2011/05/22/atmega-memory-use/
http://www.noah.org/wiki/Arduino_notes
このページを参考にして、独自に計算する関数を
書いてみた。ものすごく単機能で、まさにヒープと
スタックの間のメモリ空間のSRAM数を数えるだけ
の処理。こんな感じ。
extern unsigned int __heap_start;
extern void *__brkval;
// RAMEND and SP seem to be available without declaration here
int freeRam () {
// __brkval is the address of the top of the heap if memory has been allocated.
// If __brkval is zero then it means malloc has not used any memory yet, so
// we look at the address of __heap_start.
//int stack_top;
return (int)SP - ((int)__brkval == 0 ? (int)&__heap_start : (int)__brkval);
}
参考ページのままでは微妙に動かなかったので、
色々と弄って、それなりに動くように改造。
なんでも、malloc使ってるときは__brkvalが、
使ってないときは__heap_startがヒープのアタマ
になってて、スタックポインタのアドレスから
そのどちらかを引けば余ってるヒープサイズが
求まるという処理。
(externの部分はプログラム先頭に、関数は
適当なところに置けばok)
とりあえず、それなりに動くようで、この関数の
戻り値を、単純にprintfでシリアル出力するだけ
なら、コンパイルでエラーにならないみたい。
んで、ぶつぶつ言ってても仕方ないので、これを
元にして、FFTライブラリを使ったときのメモリ
使用量を計測してみる。
まず、32点、64点、128点でそれぞれのメモリ使用量
を計って、それら同士で差を取って見る。うん。
なんとなく、
http://wiki.openmusiclabs.com/wiki/ArduinoFFT
ここで解説されている通りの差分が表示されること
が見て取れた。
他の処理と、FFT、メモリ監視ロジックをあわせて、
今のところ、64点FFTで400バイトちょっと。128点
だと200バイトくらいになっちゃう。
これだと、ちょっとロジックを書くだけでも、
このエリアにスタックが進行してくるから、
128点は厳しいだろうな。できれば128点でFFT
掛けて、実数化で64個のデータとして表示
したかったんだけどな。まぁ、ないモノは
仕方ない。
次。
FFTがそれなりに入りそうな感じなので、次に
FFT結果を対数表示にした場合のことを考える。
ArduinoのFFTライブラリには、対数表示するため
の機能が付いているんだけど、この数値って、
どうやったらdb表記に換算できるのか?という
部分。
んで、実際に数値を入れて、リニアの場合と
log表記の場合で見比べてみる。
…なんだかよくわからない数値になっちゃう。
ウィンドウ処理を省いて計算して、出てきた結果
が、2を底とした単純なlog計算になっているわけ
じゃぁないみたい。
改めて、ライブラリに付属していたtxtファイルを
眺めてみる。
複素数→実数化計算の説明の中に、
scale factor = 255/(181*256))
なんてのがある。これ怪しいかな、なんとなく。
でも、log計算の説明個所には、
it uses a lookup table to calculate the
log of the square root, and scales the
output over the full 8b range {the
equation is 16*(log2((img^2 + real^2)^0.5))}.
っていうのがある。
これならわかる気がするんだけど、そんな数値に
なってるの?ホント?
いずれにしても、窓関数を使うことで、特定周波数
の成分はその両側に分散しちゃったり、削り落とす
エネルギーがあるから、1Vrmsの波形を入れても、
0dbよりは小さい値で拾うことになるはずなんだよな。
オモチャのオシロとは言っても、ある程度根拠が
ないとどうしようもない代物にしかならないから
なぁ。このあたりは、面倒でもちゃんと詰めて
おかないと、いかんよなぁ。
あぁ、なんだろう?この妙な数値…
http://gigazine.net/news/20140413-minnowboard-max/
MinnowBoard MAX。なかなかのスペックだし、x86系
64ビットCPUなのはイイカンジなんだけど、x86系
のATOM搭載なら、折角ならWindowsやPC系Linuxとか
がそのまま入るようにしてあればいいのにな。
動かすときにGUIは要らなくても、開発時には
バーチャル環境として最新のWindows機やLinux環境
で開発できれば、色々とサクサクなんだと思うんだ
けどな。
http://settembre21x.blogspot.jp/2013_10_01_archive.html
ディスクリートのアンプ。いいなぁ。
https://twitter.com/tokoya/status/458774888795209728
そうか。空飛ぶスパゲッティ・モンスター教は、
3Dプリンタでできたのか。なるほど。なんつって。