手習ひデジタル信号処理(32) 正弦波の信号発生器、sin関数計算編その1

Joseph Halfmoon

今回から信号の発生に入るのですが最初は正弦波の発生です。音を作るにせよ、無線にせよ、何が無くても正弦波。デジタルな計算で波形を作るのに私のような素人でも思いつくのがsin()関数を使うことです。しかしsin()のような関数の計算には時間がかかる、そこで信号処理の人はいろいろテクを使うんでありますな。

※勝手に手習ひさせていただいております教科書へのリンクを掲げます。

三上直樹先生著、工学社『「Armマイコン」プログラムで学ぶデジタル信号処理

上記教科書の7.1『「sin」の計算方法とその方法を使う「正弦波」の発声法』を手習ひさせていただいております。

※実習はST Microelectoronics社製 Nucleo-F446REボード(STM32F446RE、Arm Cortex-M4F搭載)がターゲットボードです。ビルドは Arm社のWeb開発環境 Mbed Webコンパイラ(OS2)を使わせていただいております。なお、三上先生の御ソースは、Mbed Webコンパイラ環境(要無料登録)で誰でも参照可能です。

Sin関数を計算する算法

今回ターゲットとしている STM32F446REは、Arm Cortex-M4Fを搭載しているので単精度浮動小数のFPUを搭載しています。とはいってもハードウエアの演算命令として持っているのは加減乗除に平方根程度です。積和演算など信号処理向けの演算命令は持っていても、Sin/Cosのような超越関数の演算命令は持っていないです(x87の流れでもっているx86の方が少数派かと。)

Sin/Cosを計算するのはソフトウエアのライブラリを呼び出すことになるわけで結構大変、時間がかかると。時間がかかれば対応可能な信号の周波数が低くならざるを得ないので困る、と。

このごろFPGAとかハード系の実装でSin/Cosが必要な場合はCORDICと呼ばれるアルゴリズムを使うのが普通じゃないかと思います。ただしこれ、固定小数点の実装なので、今回のように浮動小数での信号処理向けではないです。

そこで三上先生が取り出されたのが「ミニマックス近似」という技です。ごく簡単な(しかし係数を求めるのが難しそうな)多項式で近似してしまう技なんであります。5次ではありますが、係数3個の多項式でやっつけてます。カッコいいです。

「ミニマックス近似」を調べると、最近のものはみなCQ出版の「インタフェース誌」に2017年に連載された記事が元になっているようです。著者は三上先生。こっちの元ネタもかい!

ミニマックス近似、どうも源流的には昭和の終わりごろ、1980年代末くらいに流行ったというか研究が進んだ算法みたいです。検索したら以下論文にあたりました。

ミニマックス近似式について

高次展開係数の組み込みによる準ミニマックス近似法

ま、ともあれ、この方法を使えばマクローリン展開などしなくても、そこそこの精度のSinの値を簡単な多項式で近似できると。

発生プログラムのビルドと実行

今回はまず、三上先生のサンプルプログラムをそのままビルドして動かし、正弦波を観察することにいたしました。Mbed上でのビルド結果が以下に。

build

いつもの如しで、メモリは余裕です。

三上先生のサンプルプログラムでは、1kHzの正弦波を発生するようになっています。それだけではツマラナイので、10kHz、100kHzに変更したケースもやってみました。変更は以下の1行、0を増やすだけ。でも外部回路的には無謀な挑戦。

//const float DPHI_ = C0_*1.0f/FS_; // 1 kHz に対応する値
//const float DPHI_ = C0_*10.0f/FS_; // 10 kHz
const float DPHI_ = C0_*100.0f/FS_; // 100 kHz

最初は1kHzでの時間波形です。ピークツーピークで約2.6V、1kHzの正弦波に見える波形がDAに接続した外付けLPFから出ています。LPFの特性的にはこの周波数帯であれば問題ない筈。

1kHzWave

折角なので、周波数スペクトルも観察してみました。1kHz、ほぼ0dBの基本波に対して、2k, 3k, 4k。。。と高調波が綺麗にでてます。LPF的には5kHz付近から落ちていく筈で、そんな感じ。

1kHzFFT

次は10kHzです。外付けLPFが働いている効果なのか、大分振幅が小さくなっています。しかし、ほぼほぼ10kHzの正弦波らしき信号がでています。

10kHzWave

スペクトルみたところがこちら。高調波のうち30kHzが見えないのは何故だか分かりませぬ。しかし、LPFのカットオフ周波数を超えているので気にしないっと。

10kHzFFT

さて最後は、ちょいと無謀にも思いましたが100kHzです。外付けLPF的には、ヤバイでしょ、という周波数ですが、まだピークツーピークで129mVくらいの振幅が残っていました。周波数はほぼほぼ100kHz。

100kHzWave

スペクトルを観察すると以下のとおり。

100kHzFFT

外付けLPFの帯域の問題はあるものの、計算の速さという点では十分100kHzも可能かと。いや、でも、単純にSin波作るだけでない、他の処理も始めるとそうも言っていられないか。

Sinのライブラリ関数と比べると実際どのくらい速いんでしょうか。これは次回の課題かな。

手習ひデジタル信号処理(31) Weaver変調器、周波数シフタその4、COS掛けてLPF へ戻る

手習ひデジタル信号処理(33) sin関数とFastSin関数の実行サイクル数測定 へ進む