製作モジュール一覧

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

2015年10月6日火曜日

PSoC4のClockとTimerを調べる

PSoC 4 Pioneer Kitでクロック周りをもう少し調べてみた。

システムクロックを取り出したかったがPSoC 4ではcy_clockを単純にcy_pinにつないでも出力させることはできないようだ。


一応作図はできるが、コンパイルするとエラーになる。

PSoC Sensei: Using Clocks with PSoC 4」を参考にして、ちょっと裏ワザっぽい接続にすると、クロック信号を取り出せた。


↑こういう設定する。

クロック

PSoC 4 Pioneer KitはデフォルトではSystem Clockは24MHzになっているが、PSoC CreatorのDWRエディターの「clock」タブでSystem Clockを設定できる。


IMOを48Mhzと24MHzにしてオシロで見てみた。

TopDesign


48MHz

ch1:System Clock ch2:12MHz

12MHzは参考のために出力した。誤差は
(47.91MHz - 48MHz) / 48MHz = -0.1875%
(11.98MHz - 12MHz) / 12MHz = -0.16%
24MHz

誤差
(24.02MHz - 24MHz) / 24MHz = 0.083%
(12.01MHz - 12MHz) / 12MHz = 0.083%
個体差はあるかもしれないが、24MHz駆動にしたほうが若干精度が高そうだ。

Timer/Counter


DDSのサンプリング周波数を想定してTimerを48kHzと96kHzに設定して出力波形を見てみた。(System Clockは24MHz)

TopDesign

DWR

<main.c>
 #include <project.h>  
 CY_ISR(ISR_Timer_48kHz_Handler)  
 {  
   Timer_48kHz_ClearInterrupt(Timer_48kHz_INTR_MASK_TC);  
   Pin_ISR_48kHz_Write(1u);  
   //CyDelayUs(1);  
   Pin_ISR_48kHz_Write(0u);    
 }  
 CY_ISR(ISR_Timer_96kHz_Handler)  
 {  
   Timer_96kHz_ClearInterrupt(Timer_96kHz_INTR_MASK_TC);  
   Pin_ISR_96kHz_Write(1u);  
   Pin_ISR_96kHz_Write(0u);    
 }  
 int main()  
 {  
   CyGlobalIntEnable; /* Enable global interrupts. */  
   /* Place your initialization/startup code here (e.g. MyInst_Start()) */  
   ISR_Timer_48kHz_StartEx(ISR_Timer_48kHz_Handler);  
   ISR_Timer_96kHz_StartEx(ISR_Timer_96kHz_Handler);  
   Timer_48kHz_Start();  
   Timer_96kHz_Start();  
   for(;;)  
   {  
     /* Place your application code here. */  
   }  
 }  

PSoC Creator 3.3のプロジェクト(今回はv3.3を使ってみた)
https://github.com/ryood/PSoC_ClockTest

48kHz出力


ch1:OV(Overflow) ch2:ISR

OV: (47.69kHz - 48kHz) / 48kHz = だいたい -0.646%
ISR: (47.77kHz - 48kHz) / 48kHz = だいたい -0.479%

拡大

左下の「(2)PW」はch2のパルス幅でちょうど1usになっている。「(1)PD」はch1からch2の遅れで2.340us

1usは1MHzなので24MHz駆動しているので割り込みルーチン内のPINのON/OFF処理で24Clockかかってることになるのかな?

また、割り込み発生から割り込みルーチン内の処理までは56Clockぐらい?

DebugモードでBuildしてるのでReleaseモードにすればもう少し変わるかもしれない。

ISR内で1us、Delayをかける

割り込みルーチン内でCyDelayUS(1)という処理を入れた。(1usディレイ)

「(2))PW」が3.300usになっているので、
3.30us - 1us = 2.3us
で、またそれなりのオーバーヘッドがある。

96kHz出力


OV: (95.09kHz - 96kHz) / 96kHz = だいたい -0.948%
ISR: (95.24kHz - 96kHz) / 96kHz = だいたい -0.792%
拡大

(1)PD: 2.330us
(2)PW: 1.000us
オシロ(OWON SDS7102)の精度もよくわからないが、1%ぐらいの精度は出るのかな。PSoC 4のClockの精度は±2%になっているのでこんなもんかな。

メモ:


  • 48kHzと96kHzの割り込みを両方有効化するとけっこう大きいジッターが発生
  • Debugモードで96kHzだと割り込みルーチン内の処理のタイミングがかなりシビア
<追記:2015.10.06>

ReleaseモードにしてRebuildしてみたが、タイミングの変化なし。


メモリーの使用量は
Release Mode: Flash: 2048B SRAM:1436
Debug Mode: Flash 2304B SRAM:1436
</追記>

2015年5月20日水曜日

リズムマシンの構想

「矩形波だけのファンクションジェネレーター」はハンダ付け途中だが
焦ってやってもろくなことがないので、次にやることの構想を練る

というか3日に1回は記事を書くことにしているのでつなぎ(^q^;

リズムマシン


ぴゅんぴゅん3号はぴゅんぴゅんマシンとしてはもうこれ以上やりたいこともないので
他の楽器に流用することを考えた

基本波の周波数(FREQ)とLFOの周波数(LFO)を低くして、LFOの波形をノコギリ波にすると
ドラムのキックのような感じになる

8bitのDACを使っているのでデジタル的な歪がのるが、パラメーターをうまく調節するとこれがなかなか気持ちいい

ゴーストというか裏打ちが入っている感じに聞こえることもある

ファームウェアをいじってリズムマシンとして使えないかやってみたくなった

TR-808やTR-909みたいなUIが割りと使い慣れてるので
今まで作った入力実験用のデバイス(ガラクタ?)を組み合わせて考えてみた

1. ぴゅんぴゅん3号

PSOC 4 Pioneer Kitとシールドを使ったプチ・シンセだ

入力デバイスからの信号を受け取って音声信号を出力する

LCDの表示もここでやる

2. ぴゅんぴゅんコントローラー

POT3個とプッシュスイッチ2個。

ゲーム機のコントローラーみたいに両手に持って使うことを想定している

これで、リズムマシンの音色を変更するつもり

3. ロータリーエンコーダー

TR-808にあやかってロータリーエンコーダーでプログラムする対象(KickとかSnrとか)を切り替える

4. プッシュスイッチ(の列)

8個ならべたプッシュスイッチ。

ここでリズムパターン(シーケンス)を打ち込む

TR-808みたいにON/OFFをスイッチに連動したLEDに表示させたいが
入力ポートが足りないのでとりあえず本体のLCDにパターンを表示することにする

シフトレジスタを使ったり、入力系の面倒をみるマイコンを入れたりすればそれっぽくできるかな?

このへんの実験もしてみたいので後々の楽しみにとっておきたいと思います(^q^/

ディスプレイ

使ってみたいデバイスを少しずつ仕入れている(主にaitendoから)

1. SPLC792-I2C

最初はてこずったが最近はこればっかり使っています

サイズが小さくてI2Cなので信号線を節約できて16桁×2行でバックライト付き
で、375円(税別)
「aitendoのSPLC792-I2CをArduinoで使う方法」
http://dad8893.blogspot.jp/2015/02/aitendosplc792-i2carduino.html
2. VGM12864

パラレル/SPI/I2Cで使える(らしい)OLED

白一色だがこのサイズで128×64のグラフィック表示

値段が高くて壊したらいやなので、まだ実験できてないです(^q^;

3. ノキア液晶5110

SPIのグラフィックLCD
「ArduinoでSPIのグラフィックLCDを使ってみた」
http://dad8893.blogspot.jp/2015/03/arduinospilcd.html
48×84と解像度はあんまり高くないですが
出力中の波形を表示したりできそうなので、そのうちちゃんと使ってみたいと思っています

2015年4月29日水曜日

ぴゅんぴゅん3号 3次VCVS LPF版シールドでけた

はんだ付けは疲れるので、ちょっとずつやって完成(^q^/


いつものようにテスト表を作ってチェックした


テスト表は回路図の配線をもとに作っている

これぐらいの規模の回路でも毎回何かしらミスが見つかる(^q^;

めんどくさいがあんまり神経を使わずに機械的にできる作業なのでやることにしている

いきなり動かして部品を破壊するはめになるのはつらいですし


LPFの特性を決めるCR類は差し替えできるようにピンソケットを使った

あと、I2CのLCDに入れるRST信号をPSoCを5V駆動した時にRの分圧で3.3Vに降圧、
3.3V駆動した時は0Ω抵抗でショートして直接入力できるようにここもピンソケットにしていおいた


はんだ面のジャンパー線はエレキジャックのはんだ付けの記事「ユニバーサル基板のプロになる!」
http://www.eleki-jack.com/KitsandKids2/2009/06/br_1.html)を参考にしてジュンフロン線を使っているが、ELMさんの「プロト基板の配線テクニック」(http://elm-chan.org/docs/wire/wiring.html)などポリウレタン線を使っている方も多いようだ

ポリウレタン線は使ったことがないので今度使ってみたいと思います

ある程度納得できる回路ができたら、近いうちにプリント基板も作ってみたいです

回路図

基板配線図

PSoC Pioneer Kitのソース等はGitHubで公開しています
https://github.com/ryood/PSoC-PyunPyun-3rdLPF

出力波形

LFOをかけない状態で周波数をだいたい1kHzに設定して出力波形を見てみた

Sine

Triangle

Saw1

Saw2

Squre

クソ波形を目指してたわりには綺麗すぎな気もしないではないが(^q^;

PSoCについて

今回はPSoC 4 Pioneer Kit専用のシールドにしたが、PSoCらしい使い方をしたのはIDACぐらいだ

内蔵のOPAMPも使いたかったがPioneer KitとAruduino互換のシールドの仕様上あきらめた
「ぴゅんぴゅん3号 設計の下準備」(http://dad8893.blogspot.jp/2015/02/blog-post_24.html

Pioneer Kitの基板上で物理的にルーティングしたりとかすれば使えるかなぁ・・・?

PSoCのデジタルブロックも全然いじってないし、このシールドを使ってもう少し遊べそうな気がします

今後の予定(メモ)

  • Nucleo版のぴゅんぴゅん4号
  • ぴゅんぴゅん3号を使ってドラムマシン
  • エフェクタ DSP(Blackfin)
  • Resonant LPF
  • Envelope Generator(プログラムで?)→フィルターにかけられるようにできるかな?

夏コミに受かればぴゅんぴゅん3号について、もう少し詳しく製作記をまとめたいと思います

2015年3月21日土曜日

ぴゅんぴゅん3号 ファームウェアのプログラミング

やっとやる気が出たのでファームウェアのプログラミングをした

音出ししてyoutubeにあげました


http://youtu.be/r40BGVstZGs

パラメーターを適当にいじってそれっぽい音を作った

Name FREQ LFO DEPT Wave Shape LFO Shape
Pat Car 504 35 128 SQR SQR
Ame Pat 674 38 124 SQR SW1
Packman 504 35 128 TRI TRI
Invader 612 102 173 SW1 SW1
Psy Trance 157 25 255 SIN SW1
Robo Talk 手動 77 89 SQR SQR

機能的にはぴゅんぴゅん2号とほとんど同じなので目新しさはないですが、
32bit処理しているので音質は向上していると思います

MPUのリソースに余裕があるのでもう少し機能追加するかも

パラメーターを保存できるようにするとか

内蔵のflashメモリーに記録できればいいんだがだめならSDカードかな

3次VCVSローパスフィルタを使ったシールドを完成させれば3号プロジェクトはとりあえず完了とする予定

ファームウェアのPSoC ProjectはGitHubで公開しています

https://github.com/ryood/PSoC-PyunPyun
のPSoC_PyunPyun.cydsn/PSoC_PyunPyun-000.cywrk

いずれ整理して上げなおします

2015年3月14日土曜日

PSoC 4 Pioneer Kit ADCとDebouncerをPollingで使う

Pollingで使うExampleは見つからなかったが
普通にAPIを呼び出すことでPollingはできた

TopDesign


<main.c>

 #include <project.h>  
 #include <stdio.h>  
 #define CH0_N        (0x00u)  
 #define CH1_N        (0x01u)  
 #define CH2_N        (0x02u)  
 #define ADC_LOW_LIMIT  ((int16)0x000)  
 #define ADC_HIGH_LIMIT ((int16)0x7FF)  
 #define ADC_LIMIT(x) \  
   ((x)<ADC_LOW_LIMIT?ADC_LOW_LIMIT:((x)>=ADC_HIGH_LIMIT?ADC_HIGH_LIMIT:(x)))  
 volatile int16 adcResult[ADC_TOTAL_CHANNELS_NUM];  
 volatile uint32 sw1Count = 0;  
 volatile uint32 sw2Count = 0;  
 int main()  
 {  
   char uartLine[250];  
   uint8 sw1, sw2;  
   uint8 prevSw1 = 0u;  
   uint8 prevSw2 = 0u;  
   /* Initialize the UART */  
   UART_Start();  
   UART_PutCRLF();  
   UART_PutCRLF();  
   UART_PutString("Starting Controller measurement...");  
   UART_PutCRLF();  
   /* Init and start sequencing SAR ADC */  
   ADC_Start();  
   CyGlobalIntEnable;  
   for(;;)  
   {  
     // Polling ADC  
     ADC_StartConvert();  
     while (ADC_IsEndConversion(ADC_RETURN_STATUS) == 0u) {  
       // 変換終了を待つ  
       ;  
     }  
     adcResult[CH0_N] = ADC_LIMIT(ADC_GetResult16(CH0_N));  
     adcResult[CH1_N] = ADC_LIMIT(ADC_GetResult16(CH1_N));  
     adcResult[CH2_N] = ADC_LIMIT(ADC_GetResult16(CH2_N));  
     // Polling Debouncer Rising Edgedを検出  
     sw1 = Pin_5_Read();  
     if (sw1 && !prevSw1) {  
       sw1Count++;  
     }  
     sw2 = Pin_7_Read();  
     if (sw2 && !prevSw2) {  
       sw2Count++;  
     }  
     /* Print voltage value to UART */  
     sprintf(  
       uartLine, "ADC: %4d %4d %4d SW1: %d %d %lu SW2: %d %d %lu",  
       adcResult[CH0_N], adcResult[CH1_N], adcResult[CH2_N],   
       sw1, prevSw1, sw1Count, sw2, prevSw2, sw2Count  
       );  
     prevSw1 = sw1;  
     prevSw2 = sw2;  
     UART_PutString(uartLine);  
     UART_PutCRLF();  
     CyDelay(100);  
   }  
 }  

ADC_SAR_SEQ

ハードウェア割込みで使う場合とほとんど同じだが、値が条件の範囲に収まっているかどうかの判定は割込みを通してではないと使えない。
→マイナスの値が出てしまうのでソフトウェアで処理した

読み取り値を平均化するAverage ModeはPollingでも使えるようだ

Sample ModeはFree Runningでも大丈夫だと思うが
Hardware Triggerにしてプログラムで明示的にADC_StartConvert() APIを呼び出して
変換を開始するようにした

Debouncer

ロジック回路で(CPUとは独立に)動作するので使うことにした

入力用のPin_4、Pin_6は設定でPullupモードにしている

NOTコンポーネントで反転してDebouncerのdに入力、
qからPINに出力している


qはチャタリングを除去しただけの出力だ

これをプログラムでPIN_Read() APIを呼び出してPollingしている

SW_Tx_UART

UARTのコンポーネントはいくつかあるが、このコンポーネントが一番リソースが少なくて済むらしい

Txだけしか使えないが、PutString()やPutCRLF()など便利なAPIがある


Pollingでもうまく動いてくれたようですが
波形生成と組み合わせてどうなることやら。。。

2015年3月12日木曜日

PSoC 4 Pioneer Kit DDSの波形生成とADCの同時利用

PSoC 4内蔵のIDACを使ってのDDS波形生成と入力デバイスのテストがうまくいったので
両方合わせてテストしてみた



自作した可変電源のテストみたいに高圧ではないので配線はわりと気楽(^q^/

Arduino Unoほどタフではないと思うが、PSoC 4 Pioneer Kitも多少誤接続しても簡単には壊れない

気を許しすぎると危ないと思うが(^q^;

PSoC 4 Prototyping Kitの方は電源回りに保護回路が入っていないので
ラフな扱いをしたらたぶんすぐ壊れると思う(安いけど)

LCD表示とコントローラーの入力値が一発でうまくいったので喜んでたら
肝心の出力波形がグダグダ(^q^;;;


フィルターを通す前のPSoCのIDACの出力波形からグダグダ波形なのと
周波数が336.1Hzと低下していることから目星をつけた。

ADCの割込みと波形生成の割込みが干渉している

波形生成のISRは48,000Hzで呼び出される
ADCのISRはSAR ADCのConvert処理が終了するたびに呼び出される

ADCの処理が長引いて波形生成の割込みが48,000Hzで行われていないんだろう

PSoC 4 Pioneer Kitのシステムクロックは初期状態では24MHzだ
(設定で48MHzまで上げられる)

ARMベースだと思って油断してたがシステムクロックはArduino Uno(16MHz)の2倍もない

ADCの設定をいじってできるだけ処理時間が短くなるようにして
何とか1kHz付近の波形が出るようにしたが


理屈で考えて波形生成のクロックとADCのコンバート処理のタイミングが重なると波形が揺らぐ

ジッターの強烈なやつだ

面白いと言えば面白いのかもしれないが(^q^;

対応策

入力系はPollingで処理する

波形生成以外の割込みは使わない。
ぴゅんぴゅん2号(Arduino版のピュンピュンマシン)でもこの方法でやった

ADCの処理が終わるまでWaitしていても割込みがかかればそっちに処理が流れるので
遅延は起こらない

CPUで処理しているのでクロック単位の誤差はどうしても出るので
デジタル回路で処理しているオーディオインターフェイスみたいに
めちゃくちゃ正確とは言えないが、まあまあ正確に波形をを出せるだろう

割込みではなくPollingでのADCとDebouncerのテストが必要

Exampleがないかもしれないで真面目にやらないとダメっぽい

DebouncerコンポーネントはDATASHEETを見てみるとUDB(PSoCのデジタルブロック:PLDみたいなやつ)で実装されているみたいだ

UDBをいじることになると、まだ全然使ってないので深みにはまっていく可能性がある(^q^;

多重割込みをかける

ADCの割込みの優先度を上げて、他の割込みは多重割込みさせる

入力系の割込みの処理時間を十分小さくできればいけるかなと思ったが

う~ん

やっぱ、ちょっとでも遅延すると危ないな

Pollingがうまくいかないときの次善策として保留

今日は時間がないので続きは次回

2015年3月9日月曜日

PSoC 4 Pioneer Kit 入力デバイスのテスト(ADCとDebouncer)

入力系のテストはまだやっていなかったのでテストしてみた

ADCのExampleは「ADC_SAR_Seq_DieTemp_PSoC4」だ

ADC SAR Seqコンポーネントを使うが、機能がいろいろある(まあまあ設定が複雑)ので
ADCを使う前にこのExampleはやっておいたほうがいいかな?

ADCのコンバート完了は割込みで通知されるので
ADC_SAR_SEQ_IRQ_StartEx()というマクロ関数で割込みハンドラを指定するが
ADC SAR SeqコンポーネントのDATASHEET(ADC_SAR_SEQ_P4_v2_0.pdf)の後ろの方に書いてあるので
Exampleをやっておかないとなかなか分かりずらい

ぴゅんぴゅん2号のコントローラーでテスト

Arduinoベースのぴゅんぴゅん2号用に作ったコントローラー(http://dad8893.blogspot.jp/2014/08/2.html)を使って
POTの読み取りをADCで、プッシュスイッチはDebuncerというチャタリングを除去するコンポーネントがあったのでこれも使ってテストした


PSoC CreatorのTopDesign


ADC SAR SeqコンポーネントのConfigure


ADCの入力をSingle ended(差動入力ではない普通の入力)にすると
「Single ended result format」がグレイアウトして出力値がSignedでしか出力できなくなった

ということは12bitのうち11bitしか使えないので0 - 2048までの値しかとれない

DATASHEET(ADC_SAR_SEQ_P4_v2_0.pdf)をざっと読んだ感じではunsignedで12bitフルには使えなさそうだ

ADCのChannelの個別の設定はChannelsタブで設定


読み取り値はUARTで出力してPCのTeratermで受信した


まあまあきっちり動いてくれているようだ

<main.c>
 /* ========================================  
  *  
  * Copyright YOUR COMPANY, THE YEAR  
  * All Rights Reserved  
  * UNPUBLISHED, LICENSED SOFTWARE.  
  *  
  * CONFIDENTIAL AND PROPRIETARY INFORMATION  
  * WHICH IS THE PROPERTY OF your company.  
  *  
  * ========================================  
 */  
 #include <project.h>  
 #include <stdio.h>  
 #define CH0_N        (0x00u)  
 #define CH1_N        (0x01u)  
 #define CH2_N        (0x02u)  
 volatile uint32 dataReady = 0u;  
 volatile int16 result[ADC_SAR_SEQ_TOTAL_CHANNELS_NUM];  
 volatile int switchCount1 = 0;  
 volatile int switchCount2 = 0;  
 /******************************************************************************  
 * Function Name: ADC_SAR_SEQ_ISR_LOC  
 *******************************************************************************  
 *  
 * Summary:  
 * Handle Interrupt Service Routine. Source - ADC SAR Seq.  
 *  
 ******************************************************************************/  
 CY_ISR(ADC_SAR_SEQ_ISR_LOC)  
 {  
   uint32 intr_status;  
   uint32 range_status;  
   /* Read interrupt status registers */  
   intr_status = ADC_SAR_SEQ_SAR_INTR_MASKED_REG;  
   /* Check for End of Scan interrupt */  
   if((intr_status & ADC_SAR_SEQ_EOS_MASK) != 0u)  
   {  
     /* Read range detect status */  
     range_status = ADC_SAR_SEQ_SAR_RANGE_INTR_MASKED_REG;  
     /* Verify that the conversion result met the condition Low_Limit <= Result < High_Limit */  
     if((range_status & (uint32)(1ul << CH0_N)) != 0u)   
     {  
       result[CH0_N] = ADC_SAR_SEQ_GetResult16(CH0_N);  
     }    
     if((range_status & (uint32)(1ul << CH1_N)) != 0u)   
     {  
       result[CH1_N] = ADC_SAR_SEQ_GetResult16(CH1_N);  
     }    
     if((range_status & (uint32)(1ul << CH2_N)) != 0u)   
     {  
       result[CH2_N] = ADC_SAR_SEQ_GetResult16(CH2_N);  
     }    
     /* Clear range detect status */  
     ADC_SAR_SEQ_SAR_RANGE_INTR_REG = range_status;  
     dataReady |= ADC_SAR_SEQ_EOS_MASK;  
   }    
   /* Clear handled interrupt */  
   ADC_SAR_SEQ_SAR_INTR_REG = intr_status;  
 }  
 CY_ISR(SW_1_ISR)  
 {  
   switchCount1++;  
 }  
 CY_ISR(SW_2_ISR)  
 {  
   switchCount2++;  
 }  
 int main()  
 {  
   char uartLine[250];  
   /* Initialize the UART */  
   UART_Start();  
   UART_PutCRLF();  
   UART_PutCRLF();  
   UART_PutString("Starting Controller measurement...");  
   UART_PutCRLF();  
   /* Init and start sequencing SAR ADC */  
   ADC_SAR_SEQ_Start();  
   ADC_SAR_SEQ_StartConvert();  
   /* Enable interrupt and set interrupt handler to local routine */  
   ADC_SAR_SEQ_IRQ_StartEx(ADC_SAR_SEQ_ISR_LOC);  
   SW_1_Int_StartEx(SW_1_ISR);  
   SW_2_Int_StartEx(SW_2_ISR);  
   CyGlobalIntEnable;  
   for(;;)  
   {  
     /* When conversion of sequencing channels has completed */  
     if((dataReady & ADC_SAR_SEQ_EOS_MASK) != 0u)  
     {  
       /* Get voltage, measured by ADC */  
       dataReady &= ~ADC_SAR_SEQ_EOS_MASK;  
       //res = ADC_SAR_SEQ_CountsTo_mVolts(CH0_N, result[CH0_N]);  
       /* Print voltage value to UART */  
       sprintf(  
         uartLine, "ADC: %4d %4d %4d SW: %d %d",  
         result[CH0_N], result[CH1_N], result[CH2_N], switchCount1, switchCount2  
         );  
       UART_PutString(uartLine);  
       UART_PutCRLF();  
       //CyDelay(100);  
     }    
   }  
 }  
 /* [] END OF FILE */  

一瞬はまったのでメモ

PSoC 4 Pionner KitでUARTを使ってPCとシリアル通信させるときは
UART:TXとして指定したPINとJ8 pin 9 (PSoC 5LP P12[6])を
ジャンプワイヤで物理的に接続しないと動かない

2015年2月27日金曜日

ぴゅんぴゅん3号 回路設計

Eagleでざっと部品を並べてみたが
OPAMP2個使いだと配線がちょっとしんどそうだ


使うIDACを1系統だけにして、2回路入りのOPAMP1つでLPFと仮想GNDのボルテージフォロワーを使うことにする

回路図


ブレッドボードの配線図


これぐらいの部品数ならArduinoのシールド用基板1枚に収められそうだし
はんだ付けも楽そうだ(^q^/

OPAMPを差し替えて出力波形を確認


100Ωの負荷をつないでテスターで電圧をチェック
+5V 実測値:4.73V
仮想GND 実測値:2.36V
4.73V / 2 = 2.365V
なので仮想GNDはちょうど中点に来ている

LM358


黄色がIDACの電流出力を電圧変換したもの 赤が出力

例によってGND付近で波形が崩れている

どうしてもLM358を使わないといけないこともないので、今回は不採用

NJM2732


フルスイングのNJM2732に差し替えるとまずまずの波形

NJM4580


NJM4580は±2Vから使えるオーディオ用の4558系のOPAMPだ

これもちゃんと波形が出ている

WaveSpectraで波形を確認

NJM2732


THD+Nは0.42355%、周波数特性を見ると高調波歪が-60dB程度でかなり出ているが
まあこんなもんでいいだろう

NJM4580


正弦波の上側が頭打ちになってしまった(^q^;

オーディオインターフェイスの入力インピーダンスは1MΩ(Guitarモード)なので
オシロの10MΩより低いが、負荷の100ΩのRを取り去ってオープンにしても変わらない

オーディオインターフェイスの負荷容量が影響してるんだろうか?
ちょっとわかりません(^q^;

測定ミスしているのかもしれないので、基本的にNJM2732を使う方向で
ICソケットを使って組んで、後でもうちょっとテストするかも

基板図


ジャンパーがちょっと多くなってしまったが、とりあずこんなもんで

仮想GNDをCRだけにする

仮想GNDのボルテージフォロワーを取り去ってCRだけにすれば
OPAMP1個でも2系統のIDAC用のLPFを使えるのでこれもテストしてみた

回路図


ブレッドボードの配線図


分圧用のRを10kΩにすると仮想GNDがかなり中点からずれるので1kΩにした

仮想GNDから出力しないとき
+5V 実測値: 4.72V
仮想GND 実測値: 2.36V
回路図通りに接続して仮想GNDから出力したとき
+5V 実測値: 4.73V
仮想GND 実測値: 2.43V
仮想GNDの電位は若干ずれた

出力波形


100Ωの負荷をつないで測定したが波形はちゃんと出ている

WaveSpectra


THD+N 2.29443%
仮想GNDにボルテージフォロワーを使った時よりもTHD+Nが悪化している

高調波歪のレベルが若干大きくなっているのとハムノイズがかなり増加

測定ミスとか誤差かもしれないが

今日は疲れたのでこの辺で

<2015.02.27追記>

CRだけで仮想GNDを作る場合の基板図を書こうと思ったが
これもネットリストが複雑でArduinoのシールド基板に実装するのはしんどそうだ


今回はパス