製作モジュール一覧

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

2017年9月16日土曜日

AD8402 Wien Bridge DCO はんだ付け完了

回路図

基板図

部品面

ハンダ面

消費電流 3mA
10kΩ負荷、100Hz出力時。

Github:
https://github.com/ryood/SPI_Wein_Bridge_Osc

メモ:


増幅率を決める5kΩのトリムPOTは調整がちょっとむずかしいので、多回転タイプの方が良かったかも。



2017年9月10日日曜日

AD8402 Wien Bridge DCO 基板設計

回路図

基板図

部品並べ

はんだ付けは2日ぐらいでしょうか。

発振周波数と振幅


前回かんたんにデータをとってみたがちょっと変なので、もう一度測定してみた。


抵抗設定値はAD8402に設定した値で0~255の8bit値。


多少ガチャガチャしているが、おおむね周波数が高くなると振幅が小さくなる。なんでそうなるのかはよくわからないです(^q^;

測定値

Vr 発振周波数(Hz) 振幅(Vp-p)
0 6677 1.14
1 3828 1.69
2 2703 1.88
3 2089 2.05
4 1698 2.16
5 1433 2.26
6 1238 2.38
7 1089 2.5
8 972.8 2.62
9 878.7 2.74
10 801.3 2.84
11 736.4 2.86
12 681.2 2.98
13 632.9 3.02
14 592.4 3.06
15 555.6 3.08
23 375.2 3.12
31 282.1 3.34
39 226.2 3.38
47 188.7 3.48
55 162.1 3.42
63 141.8 3.48
71 125.9 3.6
79 113.6 3.64
95 94.6 3.6
104 86.6 3.72
111 81.1 3.76
127 71 3.78
143 63 3.74
159 56.8 3.76
191 47.3 3.84
223 40.6 3.84
255 35.5 3.8

2017年9月3日日曜日

AD8402 Wien Bridge DCOの構想


以前「ウィーンブリッジ回路をAD8403で制御する。」でウィーンブリッジ正弦波発振器の実験をしたが、可変抵抗は2個でいいので2回路入りのAD8402/10kでやってみた。

回路図

AD8402も電源電圧は2.7V~5.5Vなので、発振回路のOPAMPには低電圧フルスイングのNJM2732を使い、5V単電源で、レールスプリッターのTLE2426を使ってVCC/2の仮想GNDを作っている。

出力はGNDに対する振幅にするためにACカップリングした。

発振周波数foscは、AD8402で生成する抵抗値をR、C=C1、C2とすると、

fosc = 1 / (2 * π * R * C)

で、AD8402の最小抵抗値は約50Ωなので、約33.9Hz~6776Hzになる。

ブレッドボードで実験


配線図

電源はUSB経由でArduinoの電源を使い、実測値+4.89V、仮想GNDは+2.44V。負荷には1kΩの抵抗を入れた。

R1の5kΩのトリムPOTを出力があまり歪まない程度にできるだけ大きくなるように調整した。

Arduinoのスケッチ
<AD8402_WeinBridge.ino>

/*
  Wein Bridge Control

  AD8402

  POTの出力電圧を読み取って
  Digi-Potのチャンネル1, 2の抵抗値を可変

  Pinの接続
  A0 POT1
  10 CS
  11 MOSI
  13 SCK
*/

// inslude the SPI library:
#include <SPI.h>

// set pin 10 as the slave select for the digital pot:
const int slaveSelectPin = 10;

byte v0;

void setup() {
  // set the slaveSelectPin as an output:
  pinMode (slaveSelectPin, OUTPUT);
  digitalWrite(slaveSelectPin, HIGH);
  // initialize SPI:
  SPI.begin();
  delay(1);

  Serial.begin(9600);  
  Serial.println("Wein Bridge Test.");
}

void loop() {
  int v = analogRead(0) / 4;
  if (v != v0) {
    v0 = v;
  
    Serial.print(v0);
    Serial.print("\n");
    
    digitalPotWrite(0, v0);
    digitalPotWrite(1, v0);
  }
}

void digitalPotWrite(int address, int value) {
  // take the SS pin low to select the chip:
  digitalWrite(slaveSelectPin, LOW);
  //  send in the address and value via SPI:
  SPI.transfer(address);
  SPI.transfer(value);
  // take the SS pin high to de-select the chip:
  digitalWrite(slaveSelectPin, HIGH);
}

AD8402の抵抗値を変化させて正弦波出力を見てみた。電源を入れた状態でAD8402のch1とch2の抵抗値も測定してみた。

v0=255

AD8402 Ch1: 9.30kΩ
AD8402 Ch2: 9.32kΩ

F:35.46Hz
Vp-p: 4.280V

v0=163

AD8402 Ch1: 5.97kΩ
AD8402 Ch2: 5.97kΩ

F:55.33Hz
Vp-p:3.80V

v0=89

AD8402 Ch1: 3.28kΩ
AD8402 Ch2: 3.28kΩ

F:100.6Hz
Vp-p: 3.720V

v0=20

AD8402 Ch1: 773Ω
AD8402 Ch2: 774Ω

F:426.7Hz
Vp-p:3.88V

v0=15

AD8402 Ch1: 594Ω
AD8402 Ch2: 596Ω

F:554.8Hz
Vp-p:3.84V

v0=10

AD8402 Ch1: 413Ω
AD8402 Ch2: 415Ω

F:798.7Hz
Vp-p: 3.520V

v0=5

AD8402 Ch1: 231Ω
AD8402 Ch2: 232Ω

F:1.427kHz
Vp-p: 2.640V

v0=2

AD8402 Ch1: 123.2Ω
AD8402 Ch2: 122.2Ω

F:2.692kHz
Vp-p: 2.080V

v0=1

AD8402 Ch1: 86.0Ω
AD8402 Ch2: 87.2Ω

F:3.799kHz
Vp-p:1.800V

v0=0

AD8402 Ch1: 49.5Ω
AD8402 Ch2: 49.3Ω

F:6.618kHz
Vp-p:1.270V


1kHz以下の出力振幅が何か変な感じだが、AD8402の抵抗値を測定するためにケーブルを抜き差ししたのが原因かもしれない?もう一度計り直したほうがいいかも。

また、AD8402に設定値v0が0と1のときは振幅が小さいだけでなく波形が歪んでいる。

ACカップリングのCの容量


低周波数も出力できるように出力のACカップリング用のコンデンサの容量は少し大きめの100uFにした。

最低周波数に設定して、10uFと100uFに差し替えて、負荷を1kΩにして比較してみた。

100uF(無負荷)

Vp-p:4.960V

10uF(無負荷)

Vp-p:4.920V

100uF(1kΩ負荷)

Vp-p:4.440V

10uF(1kΩ負荷)

Vp-p:4.040V

無負荷時はどちらも出力レベルが同等だが、1kΩ負荷時は10uFの方が出力レベルが下がっている。

周波数が50Hzのときインピーダンスは10uFで約318Ω、100uFで約31.8Ωになるので、10uFでカップリングすると出力先によっては音痩せするかもしれない。

FFT


55.1Hz出力

2.5kHz/div (全幅で25kHz)

500kHz/div (全幅で5MHz)

SPI通信由来のノイズが心配だったが、出力振幅が4Vp-p程度と大きいので目立ったノイズは乗っていない。

WaveSpectraで測定

高調波歪はまあまあ多い。特に奇数次の歪が出ている。奇数次が多いのは矩形波っぽい歪でしたっけ(^q^?

2017年7月15日土曜日

ウィーンブリッジ回路をAD8403で制御する。

ウィーンブリッジ正弦波発振器の発振周波数を決めるRの値を、デジタルポテンショメータのAD8403で変化させて周波数可変にしてみた。

ブレッドボード図
<追記:2017.07.17>ブレッドボード図を修正</追記>


下のブレッドボードでArduino UnoとAD8403/10kΩを使って2本の可変抵抗を作っている。抵抗値はArduinoにつないだPOTで設定。

AD8403のデータシートによると、レオスタット(可変抵抗)として使うよりもポテンショメータ(可変電圧分圧器)として使ったほうが精度が出るようだが、ウィーンブリッジ回路はレオスタットとして使う必要がある。

AD8403のデータシートの10kΩバージョンの仕様によると


となっていて誤差が大きい。

最小値と最大値を設定してテスタで測定すると、

channel 最小(Ω) 最大(Ω)
RDAC1 50.9 8750
RDAC3 51.9 8720

だった。

上左のブレッドボードは、TLE2426を使って5V単電源から±2.5Vの仮想GNDを作っている。

上中のブレッドボードはNJM2732を使ったウィーンブリッジ回路。

上右のブレッドボードはACカップリング回路。

注意点として、オシロやオーディオインターフェイスなど測定機器をつなぐ場合、仮想GNDに測定機器のGNDをつなぐとUSB経由でArduinoに過電流が流れ込む。このため出力をACカップリングして真のGNDから見たDC成分を除去している。(参考:「SVF DCF 出力のGNDを修正 仮想GNDの扱いには注意するべし」)

また、ノイズ対策に0.01uFのEMIフィル(DSS1NB32A103)を入れている。

EMIフィルあり

EMIフィルなし

気持ち効果があるようなないような。

Arduinoのスケッチ

<AD8403_WeinBridge.ino>

/*
  Wein Bridge Control

  AD8403

  POTの出力電圧を読み取って
  Digi-Potのチャンネル1, 3の抵抗値を可変

  Pinの接続
  A0 POT1
  10 CS
  11 MOSI
  13 SCK
*/

// inslude the SPI library:
#include <SPI.h>

// set pin 10 as the slave select for the digital pot:
const int slaveSelectPin = 10;

byte cnt;
byte v0, v1;

void setup() {
  // set the slaveSelectPin as an output:
  pinMode (slaveSelectPin, OUTPUT);
  digitalWrite(slaveSelectPin, HIGH);
  // initialize SPI:
  SPI.begin();
  delay(1);

  Serial.begin(9600);  
  Serial.println("Wein Bridge Test.");
}

void loop() {
  v0 = analogRead(0) / 4;
  
  Serial.print(v0);
  Serial.print("\n");
  
  digitalPotWrite(0, v0);
  digitalPotWrite(2, v0);
  delay(1);
}

void digitalPotWrite(int address, int value) {
  // take the SS pin low to select the chip:
  digitalWrite(slaveSelectPin, LOW);
  //  send in the address and value via SPI:
  SPI.transfer(address);
  SPI.transfer(value);
  // take the SS pin high to de-select the chip:
  digitalWrite(slaveSelectPin, HIGH);
}

電源によるノイズの差


Arduinoの電源をPCのUSB経由でとった場合

Arduinoの電源を電池(単3×6)からとった場合

ノイズが相当違うので、以下電池電源にして測定した。

POTを右いっぱい(周波数最小)

周波数:39.22Hz
Vp-p: 1.1432V
Vrms: 490.1mV

約100Hz

周波数:100.0Hz
Vp-p: 1.1432V
Vrms:484.4mV

POTを左いっぱい(周波数最大)

周波数: 6680Hz(WaveSpectraで読み取り)
Vp-p: 112.0mV
Vrms: 24.3mV

出力レベルは小さくなるが、Rの値をAD8403の最小抵抗値(上述の通り約50Ω)にしても発振はする。

一つ上の値

周波数: 3.906kHz
Vp-p: 480.0mV
Vrms: 151.8mV

発振はするが、デジタルポテンショメータだと周波数が飛び飛びになるので端っこのほうは使わないほうが無難か?

WaveSpectraで測定


USB電源

THD: 0.16848%
THD+N: 0.98915%

電池電源

THD: 0.28599%
THD+N: 1.04803%

FFTのグラフは電池電源の方が良さそうだが、表示値はUSB電源のほうが良く出ている(@@?

メモ:


オシロの波形にヒゲが出ているが、おそらくSPI通信が行われている時のノイズだと思う。


ch1:波形出力 ch2:SPI_SCK

オシロのch2をSPI_SCKにつないでみると、ch1にもはっきりとノイズが乗る。ch2:SPI_SCKは1本の線状になっているが、1本の線がHの区間でSPI通信が行われている。

SPI通信を行うサンプリングレートは可聴帯域外に追い出したいところだ。

2017年6月29日木曜日

SPI Digital PotのAD8403の処理速度を調べてみた。

KIK01で使うかもしれないので、Analog DevicesのSPI接続のデジタル・ポテンショメータのAD8403の処理速度をArduinoとNucleoで調べてみた。

Arduino Uno


配線は「Arduinoでデジタル・ポテンショメータメーター(AD8403)を使ってみた」のものと同じ。

スケッチ
<AD8403_Control.ino>

// inslude the SPI library:
#include <SPI.h>

// set pin 10 as the slave select for the digital pot:
const int slaveSelectPin = 10;

void setup() {
  // set the slaveSelectPin as an output:
  pinMode(slaveSelectPin, OUTPUT);
  // initialize SPI:
  SPI.begin();
}

void loop() {
  // go through the four channels of the digital pot:
  for (int channel = 0; channel < 4; channel++) {
    // change the resistance on this channel from min to max:
    digitalPotWrite(channel, 255);
    digitalPotWrite(channel, 0);
  }
}

void digitalPotWrite(int address, int value) {
  // take the SS pin low to select the chip:
  digitalWrite(slaveSelectPin, LOW);
  //  send in the address and value via SPI:
  SPI.transfer(address);
  SPI.transfer(value);
  // take the SS pin high to de-select the chip:
  digitalWrite(slaveSelectPin, HIGH);
}


AD8403への出力はノーウェイトで0と255を切り替えている。slaveSelectPin(CS)がアクティブ(L)の時間を見ればAD8403に値を送るのにかかった時間がわかる。

CS

ch1:CS ch2:SCK

CSがアクティブな時間は9.680us。SPIクロック(SCK)は3.538MHzとなっているが、拡大してオシロのカーソルで測ると約4MHzだった。

2回目のSPI.transfer()の後、CSをHiにするまでに結構時間がかかっているようだ。

W1

ch1:CS ch2:W1

W1はAD8403のchannel 1のWiperの出力電圧で、プログラムでここの電圧値を制御している。CSがL->H、つまりSPI通信が終了したタイミングでほぼ遅延なく送った設定値が反映されている。

Nucleo F446RE


配線はArduinoと同じ。(NucleoのArduino Headerで配線した)

プログラム

/*
 * Digital Potentiometer AD8304のテスト
 *
 * 2017.06.28
 *
 */

#include "mbed.h"

#define SPI_CLOCK   (16000000)

SPI SpiM(SPI_MOSI, SPI_MISO, SPI_SCK);  // mosi, miso, sclk
DigitalOut Cs(D10, 1);

// address: 0..4
// value:   0..255
void outDigiPot(uint8_t address, uint8_t value)
{
    Cs = 0;
    SpiM.write(address);
    SpiM.write(value);
    Cs = 1;
}

int main()
{
    SpiM.format(8, 0);
    SpiM.frequency(SPI_CLOCK);

    for (;;) {
        for (int channel = 0; channel < 4; channel++) {
            outDigiPot(channel, 255);
            wait_us(1);
            outDigiPot(channel, 0);
            wait_us(1);
        }
    }
}

メインループ内でwait_us(1)を入れているが、これは処理が速すぎてオシロで信号が見辛かったため。

AD8403の最大クロックは10MHzなので、SPI_CLOCKを1MHz、6MHz、12MHzにして測定してみた。

1MHz CS

ch1:CS ch2:SCK

CSがアクティブな時間は26.240us。SPIクロックは597.0kHz

1MHz W1

ch1:CS ch2:W1

Arduinoと同じくCSがインアクティブになってからほぼ遅延なく設定した値が出力されている。

6MHz CS

CS:7.820us。SCKは拡大して測ると5.627MHz。

12MHz CS

CS:6.220us。SCKは拡大して測ると11.25MHz。(AD8403の仕様外)

Nucleo F303K8


F303K8はSPIクロックを1MHz、8MHz、16MHzにして測定。


1MHz CS

CS:34.6us。SCKは拡大して測ると約1MHz。

8MHz CS

CS:20.8us。SCKは拡大して測ると約8MHz。

16MHz CS

CS:20.84us。SCKは拡大して測ると約16MHz。(AD8403)

比較表


Device SCK(設定値) SCK(実測値) CS
Arduino 4MHz 4MHz 9.680us
F446RE 1MHz 597.0kHz 26.24us
F446RE 6MHz 5.627MHz 7.820us
F446RE 12MHz 11.25MHz 6.22us
F303K8 1MHz 1MHz 34.6us
F303K8 8MHz 8MHz 20.8us
F303K8 16MHz 16MHz 20.84us

比較してみると、Arduino Unoがかなり健闘している。SPIクロックが同程度ならNucleoF446REと同じぐらいかもしれない。NucleoF303K8はSPI通信前後のオーバーヘッドが大きく、SPIクロックを上げてもArduino Unoよりも悪い結果となってしまった。

F446もF303もコアは同じCortex-M4だが処理能力はかなり差がある。

Interface2016年12月号に「定番ARMマイコンSTM32便利帳2016」 という付録がついているので見てみると、F3はADC、DACなどのアナログ機能やPWMなどのタイマ機能が充実しているそうだ。



使いこなすにはもう少し慣れる必要がありそう。