2018年8月19日日曜日

Nucleo DCOの構想 ~ いわゆるプロダクト・アウト

需要ははあまりなさそうなテーマですが、Arduino LFOと同じような仕組みでハイスペックなNucleoF767でDCOを試作したいと思います。

OTAを使ったVCAのDual OTA VCA、トランジスターラダーLPFのTLF01とアナログ回路で組んできたので、VCOもアナログ回路で組みたいところですが、一度、音源として汎用的に使えそうなデジタル・オシレーターを作ってみようと思います。

Arduino + MCP4922ではいいとこLFO程度が上限でしたが、Nucleo F767なら12bit DACを内蔵、動作クロック216MHz、double型のFPU内蔵、メモリも潤沢(Flash 2MB/RAM 512kB)、mbedでプログラミング可ということでNucleo F767をコアとして試作することにしました。

仕様案


1) 内蔵12bit DAC 1ch出力

Nucleo F767は2ch分のDACが内蔵されていますが、1つはオンボードのLEDと接続されていて出力波形が汚いので1chのみとします。

参考「Nucleo F446RE 内蔵DACのテスト

2) サンプリング・レート 48kHz以上

最低でも48kHzとします。12bit/48kHzなので20年ぐらい前のサンプラー相当です。

I2Sならオーディオ品質のDACを使えますが、とりあえず楽をする方向で考えます。I2SはPSoC 5LPで使ったことがありますが、NucleoやESP32で使ったことがないので後々。

参考「オーディオ用DACを使ったファンクションジェネレータ まとめ

3) 出力波形

SQR、SAWUP、SAWDOWN、TRI、SIN、NOISE。Arduino LFOでは計算時間が足りなくてNoiseは出力できませんでしたがNucleoならできそうです。

4) 3オシレーター

1オシレーターだと音が薄いので、3オシレーターをプログラム上でMIXして出力します。サンプリングレートを下げていけばできそうな気がしますが、問題は操作子が増えることです。1オシレーターで妥協するかもしれません。1~2オクターブ下の周波数を出力するサブオシレーターにするかも?出音を比較しつつ。

5) 出力周波数

ピアノの音階の27.5Hz~4,186Hzより広くするつもりです。POTの解像度が10bit(1024)程度しかないので、レンジ切り替えで対応すると思います。

6) 出力電圧

最低、-∞ ~ ±2.5V程度で考えています。DC成分のない両電源波形です。

1オシレーターの場合のブロック図

ほとんどArduino LFOと同じ構成ですが、両電源波形にするためDAC出力をACカップリングしています。プッシュスイッチを使ってレンジ、波形を切り替えると、フィードバックが必要になるので表示器としてLCDかOLEDを使うつもりです。

ロータリースイッチを使えば表示器は不要ですが、線数が増えまくります。

Phase POTは位相を可変するもので、1オシレーターだとあまり意味はがないんですが、複数あればオシレーターごとに位相をずらしてうねりをつくれます。

外観案


1オシレーターならこれぐらいのサイズで収まりそうです。3オシレーターにしようと思うとPOTx16 PizzaBoxぐらいの規模になりそうです。

内蔵DACからの出力波形


1kHzのサイン波を出力するプログラムを書いて出力波形を見てみました。サンプリングレートはとりあえず100kHzにしました。

DDSにつかうWaveテーブルは32,768要素にしました。簡単に出力テストしてみると、これ以上要素数を増やしてもあんまり効果はなさそうでしたが、メモリーが潤沢なので要素数は増やせます。

mbed Repository
https://os.mbed.com/users/ryood/code/Nucleo-F767_DCO_Test01/

処理時間の計測

ch1:D4 ch2:D5

ch1:D4はメインループ内で1マイクロ秒のWaitをかけてH/Lしていて、ch2:D5はサンプリング周期毎の割り込み処理の最初と最後でH/Lしています。

サンプリングレートが100kHzなのでch2の周波数は100kHzになっています。Hになっている時間(PW)は720.0nsでまずまず計算する時間の余裕はありそうです。

オシロで見ると、ch2の波形が多少ブルブル震えています。←ジッターあり。

ch1は、ch2の割り込みのタイミングで1マイクロ秒より引き伸ばされる場合があります。

以下、電源ノイズを避けるために、NucleoのUSB電源を電池使用の安定化電源にして測定しました。


出力波形

普通に内蔵DACで出力すると波形の上下でクリップするので、ファームウェアで小細工して3Vp-p弱の振幅にしました。ファームウェアの以下の部分です。

    //uint16_t v = val << 4;
    // avoid distortion of the built-in DAC
    uint16_t v = (val + 256) * 14;

出力波形(拡大)

ガタガタの幅は10usで、逆数は100kHzなのでサンプリングレートと合致します。

FFT

横軸は25kHz/DIVで100kHzと200kHz付近にエイリアスが現れています。

WaveSpectra

Audio Interface: TASCAM US-144II、MIC/LINE入力、24bit/96kHz
窓関数: Flat Top

THD: 0.03635%
THD+N: 0.19748%

出力にLPFをかけるにしても可聴帯域の20kHzあたり以下の帯域は通過域です。

メモ:


Nucleo F767のZIOヘッダは、Arduinoのシールドを使うと内側の穴が隠れてしまって使いづらい。

サンプリングレートを決めてからLPFを設計する。

MIDI対応できるように考えておく。

SyncIn必要?

0 件のコメント:

コメントを投稿