2015年10月6日火曜日

PSoC 4 Pioneer KitでMCP4922を使う(メモ)

MCP4922はせっかく2chあるので使ってみたが、2ch同時ではちゃんと動かせなかった。
1chずつなら動作した。

ブレッドボード図

Pin接続


SPIのクロックは8MHzまであげられるが、安全のためには4MHzぐらいで考えたほうがよさそうだ。

PSoC Creatorのプロジェクト
https://github.com/ryood/PSoC-DDS-MCP4922

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年10月4日日曜日

小ネタ実験: 電圧検知できるLEDのパイロットランプ AVRを使う

デジタルノイズが乗りそうで気が進まないので保留していたが、AVRの周辺機能にアナログ・コンパレータがあるので、これを使って電圧検知のテストをしてみた。

使ったのはATtiny13で、たった8Pinだがアナログ・コンパレータもADCも付いている。

ブレッドボード図
AVRのコンパレータは1入力で内蔵のリファレンス電圧(1.1V)と比較できるので、これを使ってみた。

Pin3(PB4)がLED出力、Pin6(AIN1)が検知する電圧入力だ。

 #define F_CPU 9600000  
 #include <avr/io.h>  
 #include <avr/interrupt.h>  
 #include <util/delay.h>  
 ISR (ANA_COMP_vect)  
 {  
      if (ACSR & (1 << ACO))  
      {  
           PORTB |= (1 << PB4);  
      }  
      else  
      {  
           PORTB &= ~(1 << PB4);  
      }  
 }  
 int main(void)  
 {  
      DDRB = 0x00;  
      // LED output  
      DDRB |= (1 << PB4);  
      // AIN1をバンドギャップ・リファレンス、割込み有効化  
      ACSR = (1 << ACBG) | (1 << ACIE);  
      sei();  
   while(1)  
   {       
   }  
 }  

Atmel Studioのプロジェクト
https://github.com/ryood/AVR_Analog_Comparator_Test

トリマーPOTで電圧を調整したのでかなりアバウトだが、LEDの点灯/消灯時の電圧をテスターで計ってみた。
LED点灯時: 1.171V
LED消灯時: 0.951V
まあまあ1Vあたりで切り替わるようだ。

ノイズ

VCCの波形をオシロで見てみた。

AVRをブレッドボードに乗せている時

AVRをブレッドボードから外した時

拡大

18.4MHzぐらいのノイズが乗っている。

ATtiny13の内蔵RCで9.6MHz駆動しているので、このクロック由来のノイズのようだ。
(なんで2倍になるのかよくわからないですが)

これだけ盛大にノイズが乗るとアナログ回路には使いづらいが、電圧の閾値をRで分圧して入力してやるとかいっそのことADCをつかうとかすればマイコンを使った回路には使えそうだ。

PINが空いていればわざわざATtiny13を用意する必要もないかな。

メモ:

ATtiny13の逆刺し(上下左右間違え)は危険。かなり発熱した(^q^;