状態遷移図
LCD表示
ガラケーのUI設計みたいだな(^q^;;
2016年2月28日日曜日
オーディオ用DACを使ったファンクションジェネレータ ハンダ付け完了
動作チェック
ブレッドボード上で動作させたのと同程度の波形は出ているようだ。ロータリーエンコーダーはまだつないでいなので要チェック。
LCDは直接基板に取り付けると表示が見難いのでケースの蓋に貼り付ける方向で考えた。
LCDをでかくする?
どうせケースの蓋に貼り付けるなら秋月のAQM1602Aにしたほうが見栄えはいいかもしれない。
<追記:2016.03.01>
この向きだと表示が上下逆になってしまう。物理的に逆にすると表示域がキーパッドと干渉するのであきらめた。
</追記>
2016年2月27日土曜日
オーディオ用DACを使ったファンクションジェネレータ ハンダ付け
テストはまだですが、ハンダ付け完了
部品面
3.3V LDOには手製の放熱板をとりつけた。
アルミ板を金鋸でカットして共立で売ってた熱伝導シートで貼り付けた。
ハンダ面
ジャンパは0.6mmのポリウレタン線を使用。
テスト表を作っていたら回路図を間違えていたのに気づいたので、続きは次回。
部品面
3.3V LDOには手製の放熱板をとりつけた。
アルミ板を金鋸でカットして共立で売ってた熱伝導シートで貼り付けた。
ハンダ面
ジャンパは0.6mmのポリウレタン線を使用。
テスト表を作っていたら回路図を間違えていたのに気づいたので、続きは次回。
2016年2月24日水曜日
オーディオ用DACを使ったファンクションジェネレータ 基板設計 続き
回路図
基板図
結合テスト用のブレッドボードの配線図
PSoC Creatorのプロジェクト
https://github.com/ryood/I2S_FG/tree/master/PSoC/I2S_FG/PrototypingKit_FG_Test.cydsn
電源電圧にシビアそうなので電源電圧を監視するために分圧抵抗を追加。ファームウェアでDelSigADC(デルタシグマADC)コンポーネントで測定。内蔵の基準電圧を利用。
I2C LCDのコントラストを調整できるようにファームウェアを変更
3.3VのLDOが熱を持つようなので放熱板をつけられるように位置を修正(アルミ板を加工して小さいのを作って接着する予定)
基板上でI2C/I2Sを配線しやすいようにPSoCのピンの設定を変更
基板をカットしてケースと合わせてみる
電池ボックスと基板はなんとか収まりそう。ケースの上面にキーパッドを貼るとLCD見難くなるかも。LCDは蓋にはりつけてフラットケーブルでつなごうかな?
基板図
結合テスト用のブレッドボードの配線図
PSoC Creatorのプロジェクト
https://github.com/ryood/I2S_FG/tree/master/PSoC/I2S_FG/PrototypingKit_FG_Test.cydsn
やったこと
電源電圧にシビアそうなので電源電圧を監視するために分圧抵抗を追加。ファームウェアでDelSigADC(デルタシグマADC)コンポーネントで測定。内蔵の基準電圧を利用。
I2C LCDのコントラストを調整できるようにファームウェアを変更
3.3VのLDOが熱を持つようなので放熱板をつけられるように位置を修正(アルミ板を加工して小さいのを作って接着する予定)
基板上でI2C/I2Sを配線しやすいようにPSoCのピンの設定を変更
部品並べ
基板をカットしてケースと合わせてみる
電池ボックスと基板はなんとか収まりそう。ケースの上面にキーパッドを貼るとLCD見難くなるかも。LCDは蓋にはりつけてフラットケーブルでつなごうかな?
2016年2月22日月曜日
オーディオ用DACを使ったファンクションジェネレータ 基板設計
部品並べ
電池を単4×3にすればケース(タカチPB-2)に収まるかもしれない。ぎりぎりっぽいのでもう少し考えてダメなら電池を外出しにする。
回路図
基板図
単4×3の電池ケースの幅は40mmでタカチのPB-2は110mmなので66mm+40mm=106mmで基板と電池ケースは干渉するかしないか。
R1とC10はピンソケットを使って差し替えできるようにする。
電池を単4×3にすればケース(タカチPB-2)に収まるかもしれない。ぎりぎりっぽいのでもう少し考えてダメなら電池を外出しにする。
回路図
基板図
単4×3の電池ケースの幅は40mmでタカチのPB-2は110mmなので66mm+40mm=106mmで基板と電池ケースは干渉するかしないか。
メモ:
R1とC10はピンソケットを使って差し替えできるようにする。
2016年2月21日日曜日
オーディオ用DACを使ったファンクションジェネレータ 結合テスト
配線図
I2C LCDの電源のOn/OffはMOS-FETで行うつもりだったが、秋月のAQM0802は1mAしか消費しないのでPSoCのGPIOで直接駆動することにした。
LCDの電源実測値
Github:
https://github.com/ryood/I2S_FG/tree/master/PSoC/I2S_FG/PrototypingKit_FG_Test.cydsn
PSoC CreatorのTopDesign
PCM5102aのサンプリングレートを382kHzにするために48MHz駆動させていたが、演算が追いつかないようだ。
20MHzの水晶で80MHzに逓倍した場合と40MHzに逓倍した場合を比較してみた。サンプリングレートはどちらも
80MHz駆動
40MHz駆動
40MHzの方はときどき出力レベルの更新が間に合っていないようで波形が崩れている。
ch1:LPF通過後 ch2:LPF通過前
10kHz程度でも1次LPFだけでは波形のガタガタがわかる→正弦波の歪になる。外付けにするにしてもう少しスパっと切れるLPFは必要かな?
DMAのバッファの更新をL/RでPing Pongで書き換えすれば48MHzでも間に合う?
L/R出力して、LのDMA転送終了でバッファを書き換えてRを使えば間に合う?
CPUは内蔵クロックで80MHz駆動してI2Sのクロックだけ外付けのクリスタルで生成できないか?(非同期)
<追記:2016.02.24>
非同期作戦はI2SコンポーネントがUDBで作られているのでMaster Clockと同期していないとダメと怒られてBuildできなかった。
PSoC Creatorをだまして96MHz駆動させるのは成功。(10MHz水晶を使う設定で80MHz駆動させて実は12MHzの水晶を使って96MHz駆動させる)
長時間動かして壊れたらいやなので完成してから実験する予定。
</追記>
I2C LCDの電源のOn/OffはMOS-FETで行うつもりだったが、秋月のAQM0802は1mAしか消費しないのでPSoCのGPIOで直接駆動することにした。
LCDの電源実測値
電圧: 3.28Vちょっと怖い感じもするが、実測では0.15mAしか流れていなかった。PSoCのPinの設定は「Strong Drive」で正負両方FETでドライブされている。
電流: 0.15mA
PSoCの駆動周波数
Github:
https://github.com/ryood/I2S_FG/tree/master/PSoC/I2S_FG/PrototypingKit_FG_Test.cydsn
PSoC CreatorのTopDesign
PCM5102aのサンプリングレートを382kHzにするために48MHz駆動させていたが、演算が追いつかないようだ。
20MHzの水晶で80MHzに逓倍した場合と40MHzに逓倍した場合を比較してみた。サンプリングレートはどちらも
40MHz(I2Sコンポーネントに入力したクロック) / 32bit / 2ch / 2 = 312,500Hz出力に2000pF/470Ωの1次RC-LPFを入れている。
80MHz駆動
ch1:LPF通過後 ch2:LPF通過前
40MHz駆動
40MHzの方はときどき出力レベルの更新が間に合っていないようで波形が崩れている。
出力波形
ch1:LPF通過後 ch2:LPF通過前
10kHz程度でも1次LPFだけでは波形のガタガタがわかる→正弦波の歪になる。外付けにするにしてもう少しスパっと切れるLPFは必要かな?
メモ:
DMAのバッファの更新をL/RでPing Pongで書き換えすれば48MHzでも間に合う?
L/R出力して、LのDMA転送終了でバッファを書き換えてRを使えば間に合う?
CPUは内蔵クロックで80MHz駆動してI2Sのクロックだけ外付けのクリスタルで生成できないか?(非同期)
<追記:2016.02.24>
非同期作戦はI2SコンポーネントがUDBで作られているのでMaster Clockと同期していないとダメと怒られてBuildできなかった。
PSoC Creatorをだまして96MHz駆動させるのは成功。(10MHz水晶を使う設定で80MHz駆動させて実は12MHzの水晶を使って96MHz駆動させる)
長時間動かして壊れたらいやなので完成してから実験する予定。
</追記>
2016年2月19日金曜日
オーディオ用DACを使ったファンクションジェネレータ ファームウェアのコーディング+α
配線図
やったこと
- MOS FETによるLCDの電源のスイッチング
- 3.3V LDOで電源供給
- キーパッドから電卓のように周波数値を入力する
Github:
https://github.com/ryood/I2S_FG/tree/master/PSoC/I2S_FG/UI_Test.cydsn
MOS FETのスイッチング
MOS FETのスイッチングはハイサイドだと電源電圧が上げられないのでローサイドで行った。
Hi Side
Low Side
メモ:
2N7000をLTSpiceで使う方法はトラ技2016年1月号付録の「LTSpice使いこなし事典」にのっていた。モデルが.SUBCKTで記述されているのでcmp\standard.mosに直接記述はできない。
2016年2月15日月曜日
Arduinoで4×4のキーパッドの読み取り 続き
「Arduinoで4×4のキーパッドの読み取り」の続きで「押して離して」を判定するようにしてみた。
配線は前回と同じ。
押しっぱなしにしても連続入力されない。
//------------------------------------------------------
// KeyPad_Scan // // D2..D4 KeyPad Column Input (Pull Down) // D5..D9 KeyPad Row Output // //------------------------------------------------------ static char keypadChar [] = { '1', '4', '7', '*', '2', '5', '8', '0', '3', '6', '9', '#', 'A', 'B', 'C', 'D', }; int cnt; void setup() { pinMode(2, INPUT); pinMode(3, INPUT); pinMode(4, INPUT); pinMode(5, INPUT); pinMode(6, OUTPUT); pinMode(7, OUTPUT); pinMode(8, OUTPUT); pinMode(9, OUTPUT); Serial.begin(9600); Serial.println("Key Scan Start.."); } //------------------------------------------------------ // keyScan1(): 押されているキー // return: キースキャンの結果 0..15 // 押されていない場合は -1 //------------------------------------------------------ int keyScan1() { int i, j; for (i = 0; i < 4; i++) { digitalWrite(i + 6, HIGH); for (j = 0; j < 4; j++) { if (digitalRead(j + 2) == HIGH) { digitalWrite(i + 6, LOW); return i * 4 + j; } } digitalWrite(i + 6, LOW); } return -1; } //------------------------------------------------------ // keyScan(): 押して離されたキー // return: キースキャンの結果 0..15 // 変化がない場合は -1 //------------------------------------------------------ int keyScan() { static int keyBuff; int kv, kvv; //チャタリング防止 kv = keyScan1(); delay(1); kvv = keyScan1(); if (kv == kvv) { if (kv != keyBuff) { keyBuff = kv; return kv; } } return -1; } void loop() { int v; v = keyScan(); if (v != -1) { Serial.print(keypadChar[v]); // 20字で改行 cnt++; if (cnt > 20) { cnt = 0; Serial.println(""); } } }
オーディオ用DACを使ったファンクションジェネレータ UI系のテスト
配線図
Github
https://github.com/ryood/I2S_FG/tree/master/PSoC/I2S_FG/UI_Test.cydsn
P15[0]とP15[1]につなげる。P15[2]とP15[3]はkHzクロック用。「PSoC 5LP Prototyping Kitを外付けクリスタルで動作させる」
I2Sを32bit/382kHzにするとビットレートは24.448MHz。PSoCのI2Sコンポーネントの仕様により、2倍の48.896MHzのクロックを入れないといけないが、PSoC 5LPのクロックの最大値は80MHzなので48.896MHzで駆動する必要ありそう。
今回は12MHzの水晶でPLLで逓倍して48MHzで駆動。
48MHzでは駆動周波数が低くて演算が追い付かない場合、80MHz駆動にするためには20MHzの水晶で4倍で駆動、2倍の40MHzをI2Sコンポーネントに入力するとI2Sのサンプリングレートは312.5kHz。
I2CのPullUpはPSoCの内部プルアップを使用。内部PullUpした場合、抵抗値はおそらく5.6kΩ
http://www.cypress.com/knowledge-base-article/tolerance-internal-gpio-pull-updown-resistance-psoc-135
RST線をHにするのを忘れていて最初動かなかった。AQM1602で動作確認して気づいた。
Row×4、Col×4なのでGPIOのでポート1個でちょうど8個。Port3では動作しなかった。P3[2]があやしい。PSoC 5LP Prototyping Kit、3枚で試したがいずれもP3[2]がおかしいようだ。
Port2に変更したら動作した。
パラレルLCD(HD44780)でテストした時の使えるポートと関係あるかも?
「PSoC 5LP Prototyping KitでChar LCD(HD44780)を使う まとめ 」
キーパッドの入力系のPullDownもPSoCのPinの設定でPullDownしている。
秋月の「ロータリーエンコーダ(24クリックタイプ)」はPanasonicのEVERやaitendoのRE1111とはAB相の遷移の仕様が違ったのでコードを変更。1デテントで2個進む感じ。
やったこと
- PSoC 5LPを外付け水晶振動子(12MHz)で駆動
- I2C LCD(AQM0802@秋月)
- キーパッド
- ロータリーエンコーダ
Github
https://github.com/ryood/I2S_FG/tree/master/PSoC/I2S_FG/UI_Test.cydsn
外付け水晶振動子
P15[0]とP15[1]につなげる。P15[2]とP15[3]はkHzクロック用。「PSoC 5LP Prototyping Kitを外付けクリスタルで動作させる」
I2Sを32bit/382kHzにするとビットレートは24.448MHz。PSoCのI2Sコンポーネントの仕様により、2倍の48.896MHzのクロックを入れないといけないが、PSoC 5LPのクロックの最大値は80MHzなので48.896MHzで駆動する必要ありそう。
今回は12MHzの水晶でPLLで逓倍して48MHzで駆動。
48MHzでは駆動周波数が低くて演算が追い付かない場合、80MHz駆動にするためには20MHzの水晶で4倍で駆動、2倍の40MHzをI2Sコンポーネントに入力するとI2Sのサンプリングレートは312.5kHz。
I2C LCD(AQM0802)
I2CのPullUpはPSoCの内部プルアップを使用。内部PullUpした場合、抵抗値はおそらく5.6kΩ
http://www.cypress.com/knowledge-base-article/tolerance-internal-gpio-pull-updown-resistance-psoc-135
RST線をHにするのを忘れていて最初動かなかった。AQM1602で動作確認して気づいた。
キーパッド
Row×4、Col×4なのでGPIOのでポート1個でちょうど8個。Port3では動作しなかった。P3[2]があやしい。PSoC 5LP Prototyping Kit、3枚で試したがいずれもP3[2]がおかしいようだ。
Port2に変更したら動作した。
パラレルLCD(HD44780)でテストした時の使えるポートと関係あるかも?
「PSoC 5LP Prototyping KitでChar LCD(HD44780)を使う まとめ 」
キーパッドの入力系のPullDownもPSoCのPinの設定でPullDownしている。
ロータリーエンコーダ
秋月の「ロータリーエンコーダ(24クリックタイプ)」はPanasonicのEVERやaitendoのRE1111とはAB相の遷移の仕様が違ったのでコードを変更。1デテントで2個進む感じ。
2016年2月14日日曜日
PSoC 5LP Prototyping Kit: UARTの使い方 (KitProgを分割した場合)
PSoC 5LP Prototyping Kitのプログラマー部分のKitProgを分割すると、そのままではUSBを使ったUART通信ができなくなる。はまってしまったのメモ。
配線図
KitProgのP12[7](UART TX)、P12[6](UART RX)をPrototyping Kit本体のP12[6]、P12[7]につなぐ。TX同士、RX同士ではなくTXとRX。
KitProgをUSBのVBUSで5V駆動、PrototypingKit本体を別電源で3.3V駆動しても動作する。(ほんとはちょっとまずいかも?)
配線図
KitProgのP12[7](UART TX)、P12[6](UART RX)をPrototyping Kit本体のP12[6]、P12[7]につなぐ。TX同士、RX同士ではなくTXとRX。
KitProgをUSBのVBUSで5V駆動、PrototypingKit本体を別電源で3.3V駆動しても動作する。(ほんとはちょっとまずいかも?)
2016年2月12日金曜日
NUCLEO-F401RE(Cortex-M4)とPSoC 5LP(Cortex-M3)の浮動小数点演算比較
小ネタ実験です。
NUCLEO-F401REに載っているMPUはSTM32F401でCortex-M4ベースでFPUが搭載されている。しかも1,500円@秋月とPSoC 5LP Prototyping Kit(Cortex-M3ベース)と同じ値段だ。
このあいだPSoC 5LPで浮動小数点演算をしてサイン波のテーブルを作成してみたが、FPU付きのNUCLEO-F401REでも同じことをして比較してみた。
NUCLEOはmbedのオンラインコンパイラ使った。
FPU付きだが単精度小数点数しか使えないらしいのでdouble型とfloat型の二通りでサイン波テーブルを生成。
比較すると、floatだとNUCLEO-F401REが圧倒的に速い。
PSoC 5LPのコードは今回のものと少し違うが、double型で計算している。double型(FPUなし)だとM3のPSoC 5LPの方が若干速い結果になった。
動作クロックはPSoC5LPが72MHz、NUCLEO-F401REは84MHz。
double型(FPUなし)での比較はM3もM4も大差ないというぐらいの認識で(^q^;
NucleoというかSTM32はmbed以外にもSTM32ネイティブ(?)のコンパイラがあってオフィシャルではIARとかの有償(企業向)のものが推奨されている。
無償ではCooCox CoIDEというのがある(GCC based IDEと書かれているのはこれかな?)
STM32 Cubeというライブラリもあるみたいで、よくわかりません。
NUCLEO-F401REに載っているMPUはSTM32F401でCortex-M4ベースでFPUが搭載されている。しかも1,500円@秋月とPSoC 5LP Prototyping Kit(Cortex-M3ベース)と同じ値段だ。
このあいだPSoC 5LPで浮動小数点演算をしてサイン波のテーブルを作成してみたが、FPU付きのNUCLEO-F401REでも同じことをして比較してみた。
NUCLEOはmbedのオンラインコンパイラ使った。
#include "mbed.h"
//------------------------------------
// Hyperterminal configuration
// 9600 bauds, 8-bit data, no parity
//------------------------------------
#include <math.h>
#define M_PI (3.14159265358979323846) /* pi double*/
#define M_PI_f (3.1415926f) /* pi float */
#define TABLE_LENGTH (8192)
Serial pc(SERIAL_TX, SERIAL_RX);
Timer timer0;
uint8_t waveTable_0[TABLE_LENGTH];
void genSineTable_double(uint8_t *table, int length)
{
int i;
int16_t v;
int8_t* p8;
for (i = 0; i < length / 2; i++) {
v = (int16_t)(sin(2.0 * M_PI * i * 2 / length) * 32767);
p8 = (int8_t *)&v;
table[i*2] = *(p8+1);
table[i*2+1] = *p8;
}
}
void genSineTable_float(uint8_t *table, int length)
{
int i;
int16_t v;
int8_t* p8;
for (i = 0; i < length / 2; i++) {
v = (int16_t)(sinf(2.0f * M_PI_f * i * 2 / length) * 32767);
p8 = (int8_t *)&v;
table[i*2] = *(p8+1);
table[i*2+1] = *p8;
}
}
int main() {
timer0.start();
// 単精度浮動小数点演算 (with FPU)
pc.printf("start float: TABLE_SIZE:%d\r\n", TABLE_LENGTH);
timer0.reset();
genSineTable_float(waveTable_0, TABLE_LENGTH);
pc.printf("%d\r\n", timer0.read_us());
// 倍精度浮動小数点演算
pc.printf("start double: TABLE_SIZE:%d\r\n", TABLE_LENGTH);
timer0.reset();
genSineTable_double(waveTable_0, TABLE_LENGTH);
pc.printf("%d\r\n", timer0.read_us());
}
FPU付きだが単精度小数点数しか使えないらしいのでdouble型とfloat型の二通りでサイン波テーブルを生成。
TABLE_LENGTH | Nucleo float (us) | Nucleo double (us) | float vs double | PSoC 5LP(us) |
---|---|---|---|---|
512 | 372 | 18125 | 48.72311828 | 15280 |
1024 | 743 | 36255 | 48.79542396 | 29640 |
2048 | 1486 | 72718 | 48.93539704 | 58400 |
4096 | 2972 | 145631 | 49.00100942 | 116000 |
8192 | 5943 | 291349 | 49.02389366 | 230000 |
比較すると、floatだとNUCLEO-F401REが圧倒的に速い。
PSoC 5LPのコードは今回のものと少し違うが、double型で計算している。double型(FPUなし)だとM3のPSoC 5LPの方が若干速い結果になった。
動作クロックはPSoC5LPが72MHz、NUCLEO-F401REは84MHz。
double型(FPUなし)での比較はM3もM4も大差ないというぐらいの認識で(^q^;
メモ:
NucleoというかSTM32はmbed以外にもSTM32ネイティブ(?)のコンパイラがあってオフィシャルではIARとかの有償(企業向)のものが推奨されている。
無償ではCooCox CoIDEというのがある(GCC based IDEと書かれているのはこれかな?)
STM32 Cubeというライブラリもあるみたいで、よくわかりません。
エンディアンの変換 __REV()関数
リトルエンディアンからビッグエンディアンに変換するためにバイト単位で入れ替えていたが、__REV()という(マクロ)関数が用意されていた。Cortex-M用のGCCの関数のようだ。
1バイトずつ入れ替え
__REV()はARMのasmにrevと言う命令があってこれを呼び出していて一発でエンディアンを変換できるようだ。
1バイトずつ入れ替え
(1)PW:1.520us
__REV()
(1)PW:1.070us
※横軸の縮尺が違います。
PWはパルスの+側の時間で、比較すると__REV()を使ったほうがかなり短縮されている。
また、1バイトずつ入れ替えている方は、実行時間より、WSがHiの時間のほうが長い。つまり2ch出力すると間に合っていなかったようだ。
1バイトずつ入れ替え
v = (sineTable[index] >> 0);__REV()を使用
p8 = (uint8 *)(&v);
waveBuffer_0[i] = *(p8 + 3);
waveBuffer_0[i+1] = *(p8 + 2);
waveBuffer_0[i+2] = *(p8 + 1);
waveBuffer_0[i+3] = *p8;
v = (sineTable[index] >> 0);
*((uint32 *)waveBuffer_0) = __REV(v);
__REV()はARMのasmにrevと言う命令があってこれを呼び出していて一発でエンディアンを変換できるようだ。
演算の前後でPinにH/Lを出力して実行時間を比較。
1バイトずつ入れ替え
ch1:実行時間 ch2:I2SのWS
(1)PW:1.520us
__REV()
(1)PW:1.070us
※横軸の縮尺が違います。
PWはパルスの+側の時間で、比較すると__REV()を使ったほうがかなり短縮されている。
また、1バイトずつ入れ替えている方は、実行時間より、WSがHiの時間のほうが長い。つまり2ch出力すると間に合っていなかったようだ。
2016年2月11日木曜日
オーディオ用DACを使ったファンクションジェネレータ ファームウェアを改良
PSoCだけではなくてmbedでもやってみようと思って調べてみたが、I2Sのライブラリがいまいちで、DMAが簡単には使えないようだ。
手持ちのNUCLEO-F401REはCortex-M4なのでもう少し調べてみたいところですが。
というわけで、引き続きPSoC 5LPで。
Github:
https://github.com/ryood/I2S_FG/tree/master/PSoC/I2S_FG
PCM5102aの電源電圧が3.3Vだとフルスケール出ないようなので、波形テーブルの値を0.9倍にしてみた。
フルスケール
0.9倍
振幅が小さくなって波形の頭打ちがなくなった。
10kHz 16bit/1024
10kHz 32bit/32768
20kHz 16bit/1024
20kHz 32bit/32768
50kHz 16bit/1024
50kHz 32bit/32768
100kHz 16bit/1024
100kHz 32bit/32768
192kHz 16bit/1024
192kHz 32bit/32768
理屈で言うと32bit/32768の方がサンプリングポイントがなめらかになるはずだがオシロで波形を見た限りではよくわからない。
100kHzで32bitの方が悪化して見えるのは、ちゃんと波形が出力されていないのが原因のようだ。メモリ転送が間に合っていないのかも。
100kHz
1ch出力にしたら100kHzの波形(ch1)は綺麗になった。LPFを通す前を見ると高い周波数では相当ガタガタなので1次LPFを通すだけでもかなり波形は綺麗になっている方だろう。
シフト0 (1倍)
(1)Vk(RMS):1.889V
シフト1 (1/2倍)
(1)Vk(RMS):954.4mV
1.889V / 2 = 944.5mV
シフト2 (1/4倍)
(1)Vk(RMS):483.0mV
1.889V / 4 = 472.25mV
シフト3 (1/8倍)
(1)Vk(RMS):250.8mV
1.889V / 8 = 236.125mV
シフト4 (1/16倍)
(1)Vk(RMS):142.5mV
1.889V / 16 ≒ 118mV
だいたい想定通りに振幅が小さくなっている。振幅が小さくなると誤差が出ているのはノイズの影響かな。
拡大
周期性がありそうなのでクロックノイズかな?300mV~500mV(p-p)ぐらいなので結構でかい。
テーブルの要素数は増やせば良くなるかと思ってたが、どうだかわからない。出力周波数とサンプリングレートの比率でジッターになる?
1次LPFを通す前の波形も出力できるようにして、外付けで高次のActive LPF(+レベル調整)を入れられるようにする?
手持ちのNUCLEO-F401REはCortex-M4なのでもう少し調べてみたいところですが。
というわけで、引き続きPSoC 5LPで。
Github:
https://github.com/ryood/I2S_FG/tree/master/PSoC/I2S_FG
波形の振幅を小さくする。
PCM5102aの電源電圧が3.3Vだとフルスケール出ないようなので、波形テーブルの値を0.9倍にしてみた。フルスケール
0.9倍
振幅が小さくなって波形の頭打ちがなくなった。
波形テーブルをリッチにする。
間に合わせで、16bit/1024個のテーブルにしていたのを32bit/32768個に拡張した。32bit×32768/8bit=131,072Byteのテーブルになる。PSoC 5LPはFlashメモリが256kBあるのでまだ余裕がある。32bit版も振幅は0.9倍している。10kHz 16bit/1024
10kHz 32bit/32768
20kHz 16bit/1024
20kHz 32bit/32768
50kHz 16bit/1024
50kHz 32bit/32768
100kHz 16bit/1024
100kHz 32bit/32768
192kHz 16bit/1024
192kHz 32bit/32768
理屈で言うと32bit/32768の方がサンプリングポイントがなめらかになるはずだがオシロで波形を見た限りではよくわからない。
100kHzで32bitの方が悪化して見えるのは、ちゃんと波形が出力されていないのが原因のようだ。メモリ転送が間に合っていないのかも。
2ch出力をやめて1ch出力にしてみる。
CPUの処理を短縮するために、32bit/32768のままI2Sコンポーネントの設定を変更してLchのみ出力するようにしてみた。また、PCM5102aからの出力にかけている470Ω/2200pFのLPFの手前での波形も見てみた。100kHz
ch1:LPF通過後 ch2:LPF通過前
1ch出力にしたら100kHzの波形(ch1)は綺麗になった。LPFを通す前を見ると高い周波数では相当ガタガタなので1次LPFを通すだけでもかなり波形は綺麗になっている方だろう。
プログラムで振幅を絞る。
POTによるレベル調整ではなくプログラムで出力振幅を絞る実験もしてみた。出力値(整数)をシフト演算したもの。シフト0 (1倍)
ch1:LPF通過後 ch2:LPF通過前
(1)Vk(RMS):1.889V
シフト1 (1/2倍)
(1)Vk(RMS):954.4mV
1.889V / 2 = 944.5mV
シフト2 (1/4倍)
(1)Vk(RMS):483.0mV
1.889V / 4 = 472.25mV
シフト3 (1/8倍)
(1)Vk(RMS):250.8mV
1.889V / 8 = 236.125mV
シフト4 (1/16倍)
(1)Vk(RMS):142.5mV
1.889V / 16 ≒ 118mV
だいたい想定通りに振幅が小さくなっている。振幅が小さくなると誤差が出ているのはノイズの影響かな。
拡大
周期性がありそうなのでクロックノイズかな?300mV~500mV(p-p)ぐらいなので結構でかい。
メモ:
オシロのFFT機能を使って高調波歪を見てみる。テーブルの要素数は増やせば良くなるかと思ってたが、どうだかわからない。出力周波数とサンプリングレートの比率でジッターになる?
1次LPFを通す前の波形も出力できるようにして、外付けで高次のActive LPF(+レベル調整)を入れられるようにする?
登録:
投稿 (Atom)