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

2022年2月23日水曜日

AS3340(CEM3340互換) 動作確認

CEM3340互換のAS3340を入手したので動作確認を行いました。


AS3340はALFAというラトビアのメーカーの製品です。テストはLMNCさん及びElectric Druidさんの記事を参考にしました。

参考
Electric Druid: CEM3340 VCO (Voltage Controlled Oscillator) designs: https://electricdruid.net/cem3340-vco-voltage-controlled-oscillator-designs/

テスト回路図

ブレッドボード配線

CEM3340でも同様だと思いますが、データシートから注意点を抜粋します。

電源について。VEEは-5Vが推奨されます。VEEに7.4Vのツェナーダイオードが内蔵されているので、VEEに-12Vを接続する場合は電流制限抵抗を入れる必要があります。
REE = (VEE - 7.4) / .008
-12Vの場合、REE = 575Ωとなります。今回のテストでは680Ωとしています。

CV入力PINの絶対定格は±6Vとなっており±5V程度で使うのが良いと思います。

PWM入力の0%設定が0V/typ.100%設定5.0V/typ.となっており0V~5Vで使うのが良いと思います。-1V~+6Vの範囲外では電流がかなり大きくなるそうです。※今回のテストでは+4V付近でパルス幅100%になりました。

RV1(100kΩのPOT)でCVの基準値を設定します。RV2(10kΩのトリム)でScale Factorを調整します。Scale1とScaleに同じ電流が流れるようにしますが、CVに電圧を加えて出力の周波数を見てScaleを調整するのが良いと思います。

Hard Sync、Soft Sync、LinearFM、High Frequency Trackは今回は使用していません。

出力波形


簡単にRV1、RV2を調整して出力の様子を観測しました。CV=1Vとしています。

Triangle

C1:Triangle(10Pin) C2:CV

Sawtooth

C1:Sawtooth(8Pin) C2:CV

Pulse

C1:Pulse(4Pin) C2:CV

PWM(5Pin)=2Vです。ここをオープンにしたままだとパルス幅が0になるので矩形波を出力する場合は適当な電圧を与えておきます。

V/Oct


CVの値を変えて出力周波数を測定しました。

CV(V) 期待周波数(Hz) 実測周波数(Hz) 誤差(Hz) 誤差(%)
-5 6.875 7.0411 0.1661 2.42%
-4 13.75 14.068 0.318 2.31%
-3 27.5 28.04 0.54 1.96%
-2 55 55.879 0.879 1.60%
-1 110 110.93 0.93 0.85%
0 220 220.76 0.76 0.35%
1 440 439.3 -0.7 -0.16%
2 880 874.28 -5.72 -0.65%
3 1760 1738.3 -21.7 -1.23%
4 3520 3451.9 -68.1 -1.93%
5 7040 6860 -180 -2.56%


誤差は-2Vぐらいまでは線形ぽいので、もう少し調律できるかもしれません。

メモ


-5V電源を用意したほうが入力保護に使いやすそう。

Scaleの調整用のRV2は多回転タイプが良さそう。

波形によって振幅が異なるので後段のアンプで合わせる必要あり。

Electric Druidさんの記事によると実機でLinear FMが使われている例は少ない。Hard Sync / Soft Syncはちょっと怪しい?

2019年6月17日月曜日

Wave Shaper のこぎり波から三角波への変換

プログラムで波形のバリエーションを増やすのは割と簡単ですが、アナログ回路で実現するにはそれなりの技が必要です。

今まで検証したVCOは、矩形波・三角波発生回路、のこぎり波発生回路の2つです。WaveShaperを使って、これを元に波形のバリエーションを増やします。

今回は、のこぎり波を三角波に変換するWaveShaperをシミュレートします。方法はいろいろありそうですが、Analog2.0で使われているトランジスタの特性を利用したものと、反転・非反転波形をダイオードで整流するものを検証します。

参考
Analog2.0
「Music From Outer Space」さんの「Sawtooth To Triangle Wave Converter


トランジスタの特性を利用


シミュレーション回路図

過渡解析

±5Vp-pののこぎり波を入力して、VREFの電圧値を変化させてのこぎり波→三角波変換を行っています。「達人と作る アナログシンセサイザー自作入門」に回路の動作の説明がありますが、正直よくわかってません。

この回路は、Moogによって設計されたそうです。またもやMoogの恐ろしさを痛感しました。

参考
「CIRCUIT LAB」さんの「Moog sawtooth to triangle converter 01

基本的にはトランジスタ1個で済むので節約できてありがたいのですが、デメリットもあります。入力の振幅や電源/VREFの電圧にシビアで、調整が必須です。

ダイオードで整流


シミュレーション回路図

過渡解析

こちらは、入力波形の振幅が±1Vp-pでも三角波に変換できます。OPAMPを使っているので記事を読めば回路の動作はわかりやすいと思います。波形にギャップが発生していますが、これはダイオードのスイッチング速度によるようです。

2019年6月11日火曜日

Dフリップフロップを使った矩形波の分周(CD4013)

Dフリップフロップを使った分周器で、矩形波のサブオシレーターとして使います。入出力の振幅を稼ぐために4000シリーズのCD4013を使いました。

参考:トランジスタ技術2015年8月号 74p



シミュレーション回路図

過渡解析

入力した矩形波に対して、1/2、1/4に分周された矩形波が出力されます。

ブレッドボード図


信号源: SQR_FG
電源: 5V

1/2

ch1:IN ch2:1/2

1/4

ch1:IN ch2:1/4

2019年6月9日日曜日

Analog VCO のこぎり波編 ブレッドボードで実験

前回シミュレーションしたのこぎり波出力のVCOをブレッドボードで実験しました。

回路図

基準電圧VREFは抵抗の分圧をボルテージフォロアで補強、電流源はJFETを使った可変電流源にして使いました。

VREFの点の電位は+5Vになります。

JFET J1の電流を制限する抵抗R8の値は5kΩです。J1のドレインが負電位になると電流が流れなくなるため、J1のソースはGNDではなくVEEに接続しました。

過渡解析

出力は±5Vp-pののこぎり波、J1(定電流源)のドレイン電流(Id(J1))は100uA弱で、のこぎり波リセット時に短いパルス電流が流れています。

ブレッドボード図


J1のドレインとQ1のコレクタの間にテスタ(OWON B35:DC/mAモード)を挿入して、出力波形の周波数を設定する電流を測定しました。

電源: 電流/電圧計付可変両電源
電源電圧: +11.46V / -11.14V
OPAMP: NJM4580DD
Q1: 2SA1050-GR
J1: 2SK170-BL
VREF: 5.0V ±0.2V (変動あり)

Ic=101.2uA

出力振幅は±5Vp-p程度、周波数は1kHz程度です。シミュレーションでは500Hz程度なので約2倍。誤差が大きい?

定電流源のPOTを調節して、吸い込み電流を変えて電流対周波数のグラフをとってみました。


まずまず直線的に比例していると思います。

測定データ

Ic(uA) Frequency(Hz)
4.9 49.42
10 101.4
20.05 207.2
30.2 306.3
51 517
101.2 1017
203 2003
299 2878
499 4658

メモ:


JFETを使った可変定電流源は、抵抗値に対してリニアに出力電流が変わるものだとばかり思っていましたが、どうも指数関数的な変化のようです。

JFETのドレイン電流(ID)対ゲート・ソース電圧(VGS)のカーブに沿っている?(検証はしていません。)

2019年6月6日木曜日

Analog VCOの構想 のこぎり波編

前回やったVCOは三角波と矩形波を発生させるものでしたが、「達人と作る アナログシンセサイザー自作入門」のAnalog 2.0のVCOはのこぎり波を発生させるものです。



「Sawtooth VCO」で検索するといろいろ出てきますが、回路の説明としては「kassu2000」さんのがわかりやすい。

参考
「Kassu2000」さんの「VCO part 1: core

シミュレーション回路図

過渡解析

VREFは基準電位で、5Vに設定しています。

C1が電荷を貯め込む発振の源です。電流源のI1に引っ張られてVc1の電位が徐々に下がっていきます。

このVc1の電位は、U2の非反転増幅器を通してSAW_OUTからのこぎり波として出力されます。

SAW_OUTの電位とGNDをU1周りのコンパレーターで比較して、Q1をONすることによって一瞬C1の両端が短絡されます。

C1の両端が短絡することで貯め込んだ電荷が開放され、Vc1の電位がVREFに戻ります。

過渡解析

Vb1(青色の線)がLowになったときQ1がONして、Vc1(緑色の線)がVREFに戻ります。

この回路はよく設計されていて、OPAMP U2が

  • Vc1の電位のバッファリング
  • 波形の振幅を決める増幅
  • 波形の中点を決めるバイアス

の役割を担っています。その結果GNDを中心とした±5Vp-pののこぎり波がSAW_OUTから出力されます。

U1のプラス側に入力される波形はこんな感じです。(GNDと比較される)

過渡解析

C2はU1まわりのコンパレーターが素早く切り替わって発振してしまうのを抑止します。

C2を取り去った場合

過渡解析

コンパレーターの出力(青色の線)が激しく切り替わって、まともな出力(緑色の線)になりません。

「Kassu2000」さんのVCO


シミュレーション回路図

過渡解析

こちらも同じように電流源I1でC1を充電し、Vs1の電位を徐々にさげていき、U2のボルテージフォロアでバッファリングし、SAW_OUTに出力します。

SAW_OUTがU1まわりのコンパレーターの非反転入力に入力し、反転入力のGNDと比較してQ1をOFFします。Q1がOFFした瞬間J1がONし、C1が放電されます。

この回路では、GNDから+1.4V程度ののこぎり波が出力されます。

2019年5月23日木曜日

Analog VCO ブレッドボードで実験

前回シミュレートした回路をブレッドボードで実験しました。

ヒステリシス付きコンパレーター


回路図

ブレッドボード図


左側のOPAMP周りがヒステリシス付きコンパレーター本体です。右側はファンクション・ジェネレーターの三角波出力に+5VのDC成分を重畳させるための非反転加算回路です。

OPAMP: NJM4580DD
電源: +11.64V / -11.43V
信号源: AD9833-FG

入出力

ch1:IN ch2:OUT

シミュレーション時と同じく、三角波から矩形波を生成できました。

Analgo VCO


回路図

ブレッドボード図


左側のOPAMP周りがヒステリシス付きコンパレーター、右側が積分器です。周波数を決めるCVは電源をPOTで分圧して使いました。

OPAMP: NJM4580DD
電源: +11.61V / -11.33V

CV=2.00V

Ch1:TRI_OUT ch2:SQR_OUT

CV=2.00V (三角波出力・AC結合)

Ch1:TRI_OUT

きれいな三角波が出力できています。

CVを1V~10Vまで1V刻みで変化させて、出力周波数をプロットしました。


測定データ

CV(V) Frequency(Hz)
1.01 57.55
2.02 115.9
2.98 171.9
3.99 230.1
5.03 288.6
6 345.8
7 402.7
7.99 460.1
9.01 517.8
9.97 569.8

CVの電圧と出力の周波数はいい感じで比例しています。前段にアンチログ回路をつけて、Oct/Vの特性を持たせようと思います。

2019年5月21日火曜日

Analog VCOの構想

DASS01に組み込むAnalog VCOを作りたいと思います。例によって一番簡単そうな回路を使います。OPAMPを使ったヒステリシス付きコンパレーターと積分器の組み合わせで、入力電圧(CV)に比例した周波数の矩形波と三角波を出力するものです。

参考
新日本無線の「オペアンプの応用回路例集」の「電圧制御発振器(VCO)」
トランジスタ技術2015年8月号 特集・第4章「ラックマウント型モジュラ・アナログ・シンセサイザ」のVCO
「Melodic Testbench」さんの「VCO Theory



シミューレーション回路図

U1周りが積分器、U2周りがヒステリシス付きコンパレーターです。U2まわりはコンパレーターなので、出力はHまたはLになり、Q1をスイッチングします。Q1のOn/OffでU1周りの積分器の充放電をコントロールします。

過渡解析

CVを1V~5Vで1V刻みでパラメータ解析しました。出力周波数は100Hz~245Hz程度になっています。

三角波出力(TRI_OUT)は5.1V~6.3V程度の振幅ですが、矩形波出力は電源レールいっぱいの振幅なので、音源として使う場合はDC成分の除去やレベル合わせが必要になりそうです。

このVCOの動作の詳細や数学的な検証は「Melodic Testbench」さんの「VCO Theory」で詳しく述べられています。数式が出てきますが、キルヒホッフの法則と「Q=It」「Q=CV」あたりがわかれば大丈夫です。

ヒステリシス付きコンパレーターと積分器をそれぞれ単体でシミューレーションしました。

ヒステリシス付きコンパレーター


シミューレーション回路図

過渡解析

入力は積分器から出力される三角波です。

ヒステリシス付きコンパレーター(反転回路)なので、入力の三角波(V(in))がH→LのときとL→Hのときで閾値が異なっていて、矩形波が出力されます(V(sqr))。入力と出力では位相が反転しています。

積分器(Q1 off時)


シミューレーション回路図

Q1がOffのときVCOの回路図のR4より下は無視できます。Q1がOffのときC1は放電され出力電圧は低下します。

過渡解析

放電は直線的に行われます。

積分器(Q1 on時)


シミューレーション回路図

Q1がOnのときVCOの回路図のR4はGNDに接地しているのと同等です。Q1がOnのときC1は充電され出力電圧は上昇します。

過渡解析

充電も直線的に行われます。

Q1のベースに矩形波が入力されるのでOn/Offが繰り返され、出力は三角波となります。

メモ:


理屈ではそうだろうと思いますが、連結すると発振器としてちゃんと動作するところがすごいですね。

過渡解析の「.tran」コマンドに「startup」オプションをつけていますが、つけなくても発振をシミューレートできるようです。


2015年11月27日金曜日

ATtiny13でDDS波形出力 ちょっと修正

PWM出力のあたりを少し改良した。

 /*  
  * ATtinyVCO.c  
  *  
  * Created: 2015/11/25 14:07:46  
  * Author: gizmo  
  *  
  * PB1: PWM out  
  * PB2: check pin  
  *  
  * 2015.11.27 PWM出力を6bit精度に変更  
  *  
  */   
   
 #define F_CPU    9600000ul  
   
 #include <avr/io.h>  
 #include <avr/pgmspace.h>  
 #include <util/delay.h>  
 #include <stdint.h>  
   
 #define SAMPLE_CLOCK    (8000.0f)  
 #define POW_2_16        (65536ul)  
   
 #define FREQUENCY_MAX    (2000.0f)  
   
 // Saw dawn wave up table  
 const PROGMEM uint8_t sawUpTable[] = {  
     0,    1,    2,    3,    4,    5,    6,    7,    8,    9,    10,    11,    12,    13,    14,    15,  
     16,    17,    18,    19,    20,    21,    22,    23,    24,    25,    26,    27,    28,    29,    30,    31,  
     32,    33,    34,    35,    36,    37,    38,    39,    40,    41,    42,    43,    44,    45,    46,    47,  
     48,    49,    50,    51,    52,    53,    54,    55,    56,    57,    58,    59,    60,    61,    62,    63  
 };  
   
 volatile uint16_t phaseAccumlator;  
 volatile uint16_t tuningWord;  
 volatile uint8_t amp;  
   
 //=============================================================================  
 // 波形生成  
 //  
 // ----------------------------------------------------------------------------  
 // setDDSParameter()  
 // parameter: frequency: 生成する周波数  
 //  
 void setDDSParameter(float frequency)  
 {  
     tuningWord = (int16_t)(frequency * POW_2_16 / SAMPLE_CLOCK);  
 }  
   
 // ----------------------------------------------------------------------------  
 // generateWave()  
 // return: 出力値(0..255)  
 //  
 uint8_t generateSawWave()  
 {  
     uint8_t index;  
       
     phaseAccumlator += tuningWord;  
       
     // 右へシフト: 16bit -> 6bit(64個)  
     index = phaseAccumlator >> 10;  
     return pgm_read_byte(&sawUpTable[index]);  
 }  
   
 //=============================================================================  
 // 波形生成  
 //  
 // ----------------------------------------------------------------------------  
 // setPWMDuty()  
 // parameter: value: 設定するDuty(0 .. OCR0A)  
 //  
 void setPWMDuty(uint8_t value)  
 {  
     // PWMのデューティー比を設定  
     OCR0B = value;  
 }  
   
 //=============================================================================  
 // ADC  
 //  
 // ----------------------------------------------------------------------------  
 // getCV()  
 // return: CV値(0..4095)  
 //  
 uint16_t getCV() {  
     // ADC_CVの値を取得  
      return 901;    // 440Hz  
     //return 4095;    // 2000Hz  
 }  
   
 // ----------------------------------------------------------------------------  
 // getGate()  
 // return: Gate値(0..255)  
 //  
 uint8_t getGate() {  
     // ADC_GATEの値を取得  
     return 255;  
 }  
   
 //=============================================================================  
 // ラッチ割込み  
 //  
 //ISR()  
 //    generateSawWave()を呼び出し  
 //    amp値を乗算  
 //    PWM DACに出力値を設定  
   
 //=============================================================================  
 // メイン・ルーチン  
 //  
 int main()  
 {  
     uint16_t cv;  
     uint8_t v;  
       
     //-------------------------------------------------------------------------  
     // PORT設定  
     //-------------------------------------------------------------------------  
     // DDRB = 0;  
     DDRB |= (1 << DDB1);    // PB1(OC0B): PWM out  
     // Debug用  
     //  
     DDRB |= (1 << DDB2);    // PB2: output  
       
     //-------------------------------------------------------------------------  
     // PWM設定  
     //-------------------------------------------------------------------------  
     // TCCR0A = 0;  
     // TCCR0B = 0;  
     //-------------------------------------------------------------------------  
     // 波形生成モード: WGM0: 1:1:1  
     // 高速PWM(モード7)  
     TCCR0A |= (1 << WGM01) | (1 << WGM00);  
     TCCR0B |= (1 << WGM02);  
     //-------------------------------------------------------------------------  
     // コンペア・アウトプットB: COM0B: 1:0  
     // コンペア・マッチでOC0Bクリア、TOPでOC0Bセット  
     TCCR0A |= (1 << COM0B1) | (0 << COM0B0);  
     //-------------------------------------------------------------------------  
     // クロック設定: CS0: 0:0:1  
     // 分周なし  
     TCCR0B |= (0 << CS02) | (0 << CS01) | (1 << CS00);  
       
     // TCCR0A = 0b00100011;  
     // TCCR0B = 0B00001001;  
       
     //-------------------------------------------------------------------------  
     // 分解能 6bit(0 .. 63)   
     OCR0A = 64;  
       
     for (;;) {  
         // Debug用: PB2  
         PORTB |= (1 << PORTB2);  
           
         cv = getCV();  
         setDDSParameter(cv * FREQUENCY_MAX / 4096.0f);  
         amp = getGate();  
         v = generateSawWave();  
         setPWMDuty(v);  
           
         // Debug用: PB2  
         PORTB &= ~(1 << PORTB2);  
           
         _delay_us(125);    // 8,000Hz          
     }  
 }  
 // EOF  

AVRのTimer0はWGMをFast PWMのモード7にすると周期を可変にできるようだ。OCR0Aで周期を設定、OCR0BでDuty比を設定する。

ちゃんと確認したわけではないがモード7の場合PWM出力はOC0A(PB0)は使えなくて、OC0B(PB1)に限定されるみたいだ。

矩形波だけのファンクションジェネレーターを作るとき「ATMega328PのTimer1でPWMを使ってみる」でFast PWMがうまく使えなかった原因はこれかな?

16bitのTimer1より8bitのTimer0の方が設定するレジスタが少なくて多少わかりやすいかも。

波形テーブルの要素数と分解能


OCR0Aを64に設定した。こうすると周期が64になってOCR0Bを0..63に設定してDuty比を設定できる。64段階なのでbit数にすると6bit。6bitのなんちゃってDACだ。

周期が64なので、9.6MHz駆動させた場合
9.6MHz / 64 = 150kHz
と、波形をのせる基本のパルス波の周波数を上げられた。

オシロで波形をみると


※オシロ画面のキャプチャーだと横幅が狭くて見づらいのでUSB経由でPCのオシロに付属していたユーティリティ・ソフトで表示させた。(このソフトあんまり使い勝手がよくないのでほとんど使っていない(^q^;)

ch1(赤)がOC0Bの出力波形、ch2(黄色)がプログラムで波形計算の前後でH/Lさせたもの

ch1は143.799kHzとなっていて粗密がノコギリ波的な感じになっている。

ch2はHiの区間が波形を計算するのに使った時間でだいたい100uSぐらいだ。本当は外部割り込み(ラッチ)でサンプリング周期を与えようと思っているが、今回は単純にメインループで順次処理している。

出力波形をオーディオインタフェース経由でPCのWaveSpectraで見てみた。



無事ノコギリ波が出力されている(^q^/

パルス波が150kHzで可聴帯域外なのでLPFをいれなくてもパルス波は除去されているようだ(オーディオインタフェースがLPF)

6bitなのでガタガタだが。

メモ:


  • スレーブをいっぱい並べると駆動クロックは同期させておかないとやっぱりマズそう。スレーブごとに内部クロックで動かすと波形がずれてジッターみたいになりそう。→それはそれで面白いかもしれない(^q^;
  • tuningWordを求めるときに浮動小数点演算をしているのでメモリを90%以上使ってしまっている。これを整数演算にしないと後はもう何もできない。
  • 振幅も可変にできるようにしたいが、和音とかSuperSawなら別にスレーブごとに音量を変えなくてもいいかのか?う~ん。

PSoC1


Tiny85とLPC810を代替案に考えていたが、PSoC1に8pinのものがあったのを思い出した。
CY8C24123A-24PXI 240円@秋月
I2CありSPIあり9bitDACあり14bitADCあり

いっぱいならべるとまあまあ高いが5個なら1,200円か。