製作モジュール一覧

ラベル VCA の投稿を表示しています。 すべての投稿を表示
ラベル VCA の投稿を表示しています。 すべての投稿を表示

2016年6月15日水曜日

MCP4922とNJM13700でSPI制御のDCA(Nucleo編)

Nucleo F401REで動作させてみた。

回路図


ブレッドボード図


Nucleoは3.3V駆動なので、MCP4922も3.3V駆動させた。I-V変換回路とNJM13700は別に±5Vの電源を使用。

mbed Repository:
https://developer.mbed.org/users/ryood/code/Nucleo_MCP4922_DCA_Test/

main.cpp

#include "mbed.h"
#include "rtos.h"
#include "AverageAnalogIn.h"
 
#define SPIM_TIMER_PERIOD   (5)         // 5ms
#define SPIM_RATE           (8000000)   // 8MHz
#define SPIM_WAIT           /*(wait_us(1))*/
 
// ピン・アサイン
#define PIN_CHECK       PA_10
#define PIN_DAC_CS      PA_9
#define PIN_DAC_LDAC    PA_8
 
SPI SpiM(SPI_MOSI, SPI_MISO, SPI_SCK); 
DigitalOut DacCs(PIN_DAC_CS);
DigitalOut DacLdac(PIN_DAC_LDAC);
 
DigitalOut CheckPin(PIN_CHECK);
 
AverageAnalogIn DurationIn(A0);
AverageAnalogIn DecayIn(A1);
AverageAnalogIn SustainIn(A2);
 
int16_t beatLen = 25;
 
int16_t level = 4095;
int16_t duration = 400;
int16_t decay = 100;
int16_t sustain = 2000;
 
int16_t decay_delta;
int16_t release_delta = 1000;
int16_t mod_value;
 
int16_t tick;
 
// DAC A Channelに出力
// parameter: v: 出力値(0 .. 4095)
void writeToDacA(int16_t v)
{
    // Channel A
    DacLdac = 1;
    DacCs = 0;
    SpiM.write((v >> 8) | 0x30);    // 0x30: DAC_A(0) | Vref Unbuffered(0) | Vout 1x(1) | !SHDN(1)
    SpiM.write(v & 0xff);
    SPIM_WAIT;
    DacCs = 1;
    DacLdac = 0;
}
 
// DAC B ChannelにA ChannelのVrefを出力
void outVref()
{
    // Channel B
    DacLdac = 1;
    DacCs = 0;
    SpiM.write(0x08 | 0xB0);    // 0xB0: DAC_B(1) | Vref Unbuffered(0) | Vout 1x(1) | !SHDN(1)
    SpiM.write(0x00);  
    SPIM_WAIT;
    DacCs = 1;
    DacLdac = 0;
}
 
// ADSR波形を出力
void outADSR(void const* arg)
{
    tick++;
 
    if (tick > beatLen) {
        tick = 0;
        // モジュレーション波形を初期化する
        mod_value = level;
        decay_delta = (level - sustain) / decay;
    }
 
    // 出力値補正
    if (mod_value < 0) {
        mod_value = 0;
    }
    writeToDacA(mod_value);
 
    if (tick < decay) {
        mod_value -= decay_delta;
    }
    /*
    if (tick >= duration) {
        mod_value -= release_delta;
    }
    */
    if (tick == duration) {
        mod_value = 0;
    }
}
 
int main()
{
    RtosTimer SpiM_timer(outADSR, osTimerPeriodic);
        
    SpiM.format(8, 0);
    SpiM.frequency(SPIM_RATE);
    
    outVref();
    
    SpiM_timer.start(SPIM_TIMER_PERIOD);
    
    while(true) {
        duration = DurationIn.read() * beatLen;
        decay    = DecayIn.read() * beatLen;
        sustain  = SustainIn.read() * 4095;
        
        printf("%d\t%d\t%d\r\n", duration, decay, sustain);
        
        Thread::wait(10);
    }
}


MCP4922の余っているchannel Bをchannel AのVrefとして使うようにしてみた。0x0800(2048)を出力しているので、channel AのVrefはVDD/2になり、channelAの出力は0V~VDD/2、3.3V駆動させているので0V~1.65Vの振幅になる。

プログラムで後から振幅を調整できるのがメリット。

入出力のようす



ch1:MCP4922の出力 ch2:WaveOut


ch1:WaveIn ch2:WaveOut

拡大

WaveInの振幅

差動入力電圧100mV(p-p)以下

ch1:WaveIn ch2:WaveOut

差動入力電圧100mV(p-p)以上

波形の振幅は±100mV(p-p)以内におさえないと激しく歪む。歪ました方が面白い場合もあるのでトリマーで調節できるようにしようか。

ADSR波形にLPFを入れてみる


MCP4922で出力した波形がカックカクなので、出音がブツブツ言う。なのでLPFを入れてアナログチックな波形にしてみた。

LTSpiceでシミュレーション

過渡解析

125m秒と言うのは、120BPMの四分音符の長さ。これぐらいのなまり方ちょうど良さそう。


ch1:MCP4922の出力 ch2:WaveOut

メモ:


いまだに割と簡単に発振してしまう。意図しない発振なのでつぶす必要がある。デカップリングコンデンサは入れているので、NJM13700の使ってないB側をGND入力のボルテージフォロワーにして安定させてみるとか。オーディオ信号が発振するのでNJM13700の周辺だと思う。

ADSR波形のLPFもなまり方を可変できるようにRを10kΩ程度のトリマーにしてみる?

回路図のR1とR2は兼用できないか?


2016年6月13日月曜日

MCP4922とNJM13700でSPI制御のDCAを作ってみる。

配線図


OPAMPはTL072を使用。両電源が必要なTL072とNJM13700はプラス5VをArduinoから給電、マイナス5Vを自作の5V-3.3V安定化電源Ver.2から給電。

振幅制御用にPOT3個(ぴゅんぴゅんコントローラー1号)を使った。

ブレッドボード図では18kΩになっているV-I変換用のRの値を47kΩにしてV→Iの変換比率を下げ、たまに発振するようなので2.2kΩのRと並列に0.1uFのCを入れた。(気休め)

Arduinoのスケッチ


ArduinoとSPIのDAC(MCP4922)でエンベロープ・ジェネレーターを作る。」のスケッチとほとんど同じだが、5V MAXで出力するとV-I変換でNJM13700に入力する電流が大きくなりすぎるので、2bit右シフトして出力電圧を1/4にして出力するようにした。

MCP4922_NJM13700_DCA_Test

#include <SPI.h>
#include <MsTimer2.h>

#define MOD_RATE  1   // ms

#define PIN_LDAC   9      // MCP4922のラッチ動作出力ピン
#define PIN_DURATION  A0
#define PIN_DECAY     A1
#define PIN_SUSTAIN   A2   

int16_t beatLen = 500;

int16_t level = 4095;
int16_t duration = 400;
int16_t decay = 100;
int16_t sustain = 2000;

int16_t decay_delta;
int16_t mod_value;

int16_t tick;

// DACに出力
// parameter: v: 出力値(0 .. 4095)
void outDAC(int16_t v)
{
  v >>= 2;
  digitalWrite(PIN_LDAC, HIGH) ;
  digitalWrite(SS, LOW) ;
  SPI.transfer((v >> 8)| 0x30) ;
  SPI.transfer(v & 0xff) ;
  digitalWrite(SS, HIGH) ;
  digitalWrite(PIN_LDAC, LOW) ;
}

void outADSR()
{
  tick++;
  
  if (tick > beatLen) {
    tick = 0;    
    // モジュレーション波形を初期化する
    mod_value = level;
    decay_delta = (level - sustain) / decay;
  }
  
  // 出力値補正
  if (mod_value < 0) {
      mod_value = 0;
  }
  outDAC(mod_value);
  
  if (tick < decay) {
    mod_value -= decay_delta;
  }
  if (tick == duration) {
    mod_value = 0;
  }
}

void setup() {
  Serial.begin(9600);
  
  // DAC出力の初期化
  pinMode(PIN_LDAC, OUTPUT);
  SPI.begin();
  SPI.setBitOrder(MSBFIRST);            // ビットオーダー
  SPI.setClockDivider(SPI_CLOCK_DIV8);  // クロック(CLK)をシステムクロックの1/8で使用(16MHz/8)
  SPI.setDataMode(SPI_MODE0) ;          // クロック極性0(LOW) クロック位相0
  
  // Timerの初期化
  MsTimer2::set(MOD_RATE, outADSR);
  MsTimer2::start();
}

void loop() {
  
  duration = map(analogRead(PIN_DURATION), 0, 1023, 0, beatLen);
  decay    = map(analogRead(PIN_DECAY), 0, 1023, 0, beatLen);
  sustain  = analogRead(PIN_SUSTAIN) << 2;
  
  Serial.print(duration);
  Serial.print("\t");
  Serial.print(decay);
  Serial.print("\t");
  Serial.print(sustain);
  Serial.print("\n");
}

入出力のようす


自作のファンクションジェネレータで100Hzのノコギリ波を出力して振幅を変化させてみた。


ch1:Audio Out ch2:MCP4922の出力


ch1:Audio Out ch2:Audio In

入力信号はノイズに埋もれてしまっているが、出力信号はまあまあきれに変調できているようだ。

メモ:


OPAMPとPNP Trの組み合わせでV-I変換の比率をシミュレーションで調べた方がいいかも知れない。TrのhFEが絡んでくるのかどうかよくわからない。

DACへの入力を1/4にすると精度が悪くなるので(12bit精度が10bit精度になる)アナログ回路的にもう少し考える。


2016年5月4日水曜日

OTAのNJM13600、NJM13700をシンプルに使う。

出力バッファにNJM13700の内蔵Trを使って、電圧電流変換を抵抗1本でやっても動作した。

回路図

ブレッドボード図


入力はV+とV-を「CtlIN」のPOTで分圧して、R(33kΩ)に入力すること電流に変換している。

出力バッファはNJM13700の内蔵のTrを使った。バッファのエミッタをGNDではなく、V-に接続してTrを動作させている。

出力はマイナス側に偏るので10uFの電解コンデンサと100kΩのRでACカップリングした。

部品数はかなり少なくなった(^q^/

入出力


電源電圧 +5.06V/-5.09V
R1(V→I変換抵抗) 33.18kΩ


入力電圧(V) P1の電圧(V) 電位差(V) 電流(uA) 出力電圧(mV(p-p)
-5.09 -5.07 -0.02 -0.602772755 24
-4.18 -4.17 -0.01 -0.301386377 78
-3.00 -3.91 0.91 27.42616034 1120
-2.00 -3.88 1.88 56.66063894 2320
-1.00 -3.84 2.84 85.59373116 3480
0.00 -3.84 3.84 115.7323689 4680
1.00 -3.82 4.82 145.177818 5760
2.02 -3.81 5.83 175.708258 6960
3.00 -3.81 6.81 205.244123 7680
5.06 -3.79 8.85 266.7269439 8000

<追記:2017.07.04>

P1とはNJM13700のPin1の増幅率を決める電流入力端子の意味です。←見返しててわからなかったので追記。

</追記>


バイアス入力電圧 vs 波形出力電圧

バイアス入力電流 vs 波形出力電圧

NJM13700のP1(AMP/BIAS)の電位がマイナスなので、バイアス入力電圧はマイナスから必要だが、電圧で波形の増幅率を制御できている。

(バイアス入力電圧 - P1の電圧)とR1の抵抗値から計算した電流は波形の出力電圧とほぼ比例している。

NJM13700のP1の電圧


電源電圧でP1の電圧が変わりそうなので、電源電圧を変化させて調べてみた。


電源+(V) 電源-(V) 電源差分(V) P1(V)
3 -2.99 5.99 -1.772
4 -4 8 -2.77
5 -5 10 -3.75
6.01 -6.01 12.02 -4.74
6.99 -6.99 13.98 -5.72
8 -8 16 -6.7
8.96 -9 17.96 -7.72
10.03 -10.01 20.04 -8.73




メモ:


バイアス電圧を負側から与えられればV→I変換は抵抗1本で済みそう。増幅率は0からでないとVCAとしては使えない。

抵抗値(R1)で電圧→電流の変換の比率は変えられる。

電源電圧でバイアス電流が変化するが、きちんと安定化できれば大丈夫?

OPAMP+PNPトランジスタの方がV-I変換は確実そう。(GNDレベルは気にしないでいい)


以下、オシロのキャプ画です。


2016年5月2日月曜日

メモ: Arduinoでモジュレーション波形生成(Decayのみ)

スケッチ

#include <MsTimer2.h>

#define MOD_RATE  10  // ms

int16_t beatLen = 50;
int16_t decayLen = 20;
int16_t level = 4095;

int16_t decay_delta;
int16_t mod_value;

int16_t tick;

void outADSR()
{
  tick++;
  
  if (tick > beatLen) {
    tick = 0;    
    //モジュレーション波形を初期化する
    mod_value = level;
    decay_delta = level / decayLen;
  }
  
  Serial.println(mod_value);
  
  mod_value -= decay_delta;
  if (mod_value < 0) {
      mod_value = 0;
  }
}

void setup() {
  Serial.begin(9600);
  
  MsTimer2::set(MOD_RATE, outADSR);
  MsTimer2::start();
}

void loop() {
  //Serial.println("a");
}

BPM = 120 → 60s / 120 = 0.5s = 500ms

なので1Beatは500ms

MOD_RATEを10ms、beatLenを50にしているので

10ms * 50 = 500ms

decayLenは減衰の着地(?)地点で0~beatLenを指定。

タイマー割り込みにMsTime2を使用。


OTAのNJM13600、NJM13700のバッファを使わない実験

バッファを外して実験してみた。前回の実験でNJM13600は内蔵バッファを使わないでボルテージフォロワーを使うと出力がリニアにならくて、出力電圧も違ったようなので、内蔵バッファを使わないでOTAの出力を「BUFFER INPUT」に入れてみる場合も試してみた。

ブレッドボード図

OTAの出力(5Pin)からバッファの入力(7Pin)の青色のジャンパ線を抜き差しして比べた。

5PinからGNDに落としている33kΩの抵抗は、これがないとオシロで測定した時出力電圧がかなり上がってしまうので入れている(→ということは電流出力なのかな?)

NJM13600 バッファなし


バイアス電圧(mV) 201 400 602 800 1004
出力電圧(mV(p-p)) 520 968 1400 1820 2220


NJM13600 バッファなし (OTAの出力を内蔵バッファにインプット)


バイアス電圧(mV) 201 400 600 802 1004
出力電圧(mV(p-p)) 320 592 872 1160 1440


NJM13700 バッファなし


バイアス電圧(mV) 201 400 601 800 1003
出力電圧(mV(p-p)) 312 584 864 1128 1420


NJM13700 バッファなし (OTAの出力を内蔵バッファにインプット)


バイアス電圧(mV) 201 400 601 800 1003
出力電圧(mV(p-p)) 312 584 864 1128 1420

グラフ化してみると、NJM13600で内蔵バッファにOTAの出力を入力しない場合(グラフのオレンジの線)だけ出力電圧が異なっている。


また、点線で直線を引いてみて比べる他と比べてカーブしている。

メモ:


NJM13600は内蔵バッファを使わない時でもOTAの「OUTPUT」から内蔵バッファの「BUFFER INPUT」に繋いでおいたほうが無難かもしれない。

前回のオシロのキャプ画を見てみると、内蔵Trでバッファリングした場合は同位相だが、ボルテージフォロワーにした場合はNJM13600もNJM13700も位相が反転している。なぜだ(@@?

<追記:2016.05.07>

OTAの反転入力端子(P4)と非反転入力端子(P3)で、信号を入力するのとGNDに落とす位置を逆に接続してしまっていたのが原因だったようです。

</追記>

以下オシロキャプ画です。

NJM13600 バッファなし


バイアス入力電圧201mV

バイアス入力電圧400mV

バイアス入力電圧602mV

バイアス入力電圧800mV

バイアス入力電圧1004mV

NJM13600 バッファなし (OTAの出力を内蔵バッファにインプット)


バイアス入力電圧201mV

バイアス入力電圧400mV

バイアス入力電圧602mV

バイアス入力電圧800mV

バイアス入力電圧1004mV

NJM13700 バッファなし


バイアス入力電圧200mV

バイアス入力電圧400mV

バイアス入力電圧601mV

バイアス入力電圧800mV

バイアス入力電圧1004mV

NJM13700 バッファなし (OTAの出力を内蔵バッファにインプット)


バイアス入力電圧201mV

バイアス入力電圧400mV

バイアス入力電圧601mV

バイアス入力電圧800mV

バイアス入力電圧1003mV

2016年4月29日金曜日

OTAのNJM13600、NJM13700を使ってみる実験

この間V+の接続を間違えていたのでテストしなおした。

今回はNJM13600、NJM13700で内蔵のTrの出力バッファを使うのとOPAMPのボルテージフォロワーを使う2通りでやってみた。

等価回路図

NJM13600とNJM13700の違いは、NJM13600の方が出力バッファのダーリントン接続の1段目のエミッタから増幅率を決めるバイアス入力回路のあたりにつながっていて、出力バッファとバイアス入力がなんか関係ありそう。と、いうことぐらいしかわからない(^q^;

TIのLM13600とLM13700のDATASHEETはもう少し詳しく書いてありそうだが、英語なので気が向いたら読むかも。(そもそもコンパチなのか?)

ボルテージフォロワーを使う


回路図

回路図の下の方は電圧→電流変換回路でGND~1Vの電圧を電流に変換してNJM13600/13700のAMP BIAS INPUT(1Pin)に入力している。

ブレッドボード図


回路はNJM13600もNJM13700も同じもの。

NJM13700+ボルテージフォロワー


電圧→電流変換回路に入れた電圧とNJM13700→ボルテージフォロワーからの出力電圧をオシロで測定。オシロのキャプ画は記事の最後に掲載。


バイアス電圧(mV) 0 200 401 602 801 989
出力電圧(mV(p-p)) 264 520 784 1020 1240


電圧で入力波形の振幅をほぼリニアに制御できている。

NJM13600+ボルテージフォロワー


NJM13700をNJM13600に差し替えて測定。


バイアス電圧(mV) 0 201 400 601 800 996
出力電圧(mV(p-p)) 13.78 500 920 1340 1720 2060


若干対数カーブになっている感じ。

内蔵Trバッファを使う


回路図

出力バッファのT2、T3はほんとは内蔵だが(IC1Aの7,8Pinにつなぐ)わかりやすいように外に書いておいた。R1、R7の値はLM13700のDATASHEETのApplication Noteに載っていた値を使った。

NPN Trなので入力波形の負側(+VBE*2)では動作しないのでR1とR8でバイアスをかけている。(実測値+2.51V)

ブレッドボード図

電圧→電流変換回路は割愛。


NJM13600+Trバッファ



バイアス電圧(mV) 0 200 401 600 799 999
出力電圧(mV(p-p)) 32 168 296 432 552 69


まあまあリニアに制御できている。

NJM13700+Trバッファ



バイアス電圧(mV) 0 202 399 601 800 999
出力電圧(mV(p-p)) 40 176 336 472 624 776


まあまあリニアに制御できている。(ちょっといびつ?)

電圧→電流変換回路の測定


Trバッファの回路で出力をNJM13700の1Pinにつないだ状態で電圧→電流変換回路の入出力をテスタで測定した。


入力電圧(mV) 202 399 601 802 999
出力電流(uA) 11.1 22.2 33.3 44.5 55.3


電圧→電流変換回路もまあまあリニアに変換できてると思う。

データーシートの特性例を見ると

増幅率を決めるバイアス電流は数uA~数100uAの範囲で制御できそう。

入力波形の振幅


90mV(p-p)程度のサイン波を入力して測定したが、これ以上の振幅で入力すると波形が歪む。

NJM13600+Trバッファ 100mV程度

NJM13600+Trバッファ 150mV程度

データーシートの特性例を見ると

なので入力波形の振幅が100mV(p-p)ともなるとかなり歪むようだ。「ダイオード使用」とは2,15Pinのことだと思うが、使い方がよくわからん。

メモ:


内蔵Tr(エミッタフォロワ-)とボルテージフォロワーで出力を増強したが、バッファを入れない場合も見た方がいいかな?バッファを通すと出力電圧がかなり違うようだし。

ボルテージフォロワーでバッファリングした時NJM13600だと少し線形性が失われるている感じだし、NJM13600とNJM13700で増幅率が倍ぐらい違う。等価回路図から推察すると内蔵Trでバッファリングしない場合も「BUFFER INPUT(7,10Pin)」にOTAからの出力を入れてみるのもありかな?

OPAMPを使うと素子数が増えるがGNDレベルの振幅になる。Trだと出力が正側に寄ってしまうので出力はACカップリングしないとダメそう。あ、TrでもエミッタをGNDではなくてV-に接続すればいいのか(@@?

内蔵Trをバッファとして使うなら、電圧→電流変換もTr一発の回路等、素子数を少なくする方向でやったほうがいいかもしれない。

大筋では動作するようなのでもう少し実験してみる予定。


以下、オシロのキャプ画です。

NJM13700 + ボルテージフォロワー


電圧→電流変換回路への入力電圧:200mV

ch1:OTAへの入力 ch2:バッファからの出力

電圧→電流変換回路への入力電圧:401mV

電圧→電流変換回路への入力電圧:602mV

電圧→電流変換回路への入力電圧:801mV

電圧→電流変換回路への入力電圧:989mV

NJM13600 + ボルテージフォロワー


電圧→電流変換回路への入力電圧: 0mV

電圧→電流変換回路への入力電圧:201mV

電圧→電流変換回路への入力電圧:400mV

電圧→電流変換回路への入力電圧:601mV

電圧→電流変換回路への入力電圧:800mV

電圧→電流変換回路への入力電圧:996mV

NJM13700 + 内蔵Trバッファ


電圧→電流変換回路への入力電圧: 0mV

電圧→電流変換回路への入力電圧:202mV

電圧→電流変換回路への入力電圧:401mV

電圧→電流変換回路への入力電圧:601mV

電圧→電流変換回路への入力電圧:800mV

電圧→電流変換回路への入力電圧:999mV

NJM13600 + 内蔵Trバッファ


電圧→電流変換回路への入力電圧: 0mV

電圧→電流変換回路への入力電圧:200mV

電圧→電流変換回路への入力電圧:401mV

電圧→電流変換回路への入力電圧:600mV

電圧→電流変換回路への入力電圧:799mV

電圧→電流変換回路への入力電圧:999mV