AD9833でファンクションジェネレータを作る14 ライブラリ利用

published_with_changes 更新日: event_note 公開日:

labelAD9833 labelESP32 labelファンクションジェネレータ

AD9833を動かすのに、今までは周波数の値をビット変換してレジスタ書き込む等の作業を一から行っていました。

期することがあって、ライブラリを利用しようと思います。AD9833で検索すると”Billwilliams1952/AD9833-Library-Arduino”がまず出てきます。しかし、これはESP32が未サポートなのかもしれませんが、私の環境では動きませんでした。(FNC_PIN以外のSPI接続先は既定のPINに接続するようにソフトで行っている模様)

Arduino AD9833 GPIO-only library

ESP32が動くライブラリとして、GitHubに公開されているArduino AD9833 GPIO-only libraryを利用します。ただ、このライブラリは使用例が少ないので使い方を整理しておこうと思います。

このライブラリは最初にESP32で使えると紹介されていました。また、SPIの接続先は比較的自由にユーザが決めれるようです。AD9833はSPI_MODE2なのですが、それを意識しないで使えました。

AD9833用の小さなCPPライブラリです。これはESP-32で使用されるArduinoベースのライブラリですが、他のArduinoプラットフォームでも機能するはずです。このライブラリは、いくつかのメソッドを含む1つの大きなクラスオブジェクトです。このライブラリは、SPIハードウェアピンとして、SCK、FSYNC(CS)、およびDATA(MOSI)の3つのIOピンを使用します。

詳細については、https://daumemo.com/diy-generator-ad9833-library-and-further-output-noise-reduction-part-13/をご覧ください。

 

使い方:Function

class objectは使用例に倣って、generatorとしています。

10数種の関数がありますが、利用したのは次項のスケッチで使っているgenerator.setFrequencyをはじめとした青で色付けした7種です。

AD9833_IC generator(int pinSCK, int pinFSYNC, int pinDATA);

  object generatorを作成する

   

    generator.setFrequency(double hz, uint8_t reg);

      Sets Frequency(Hz) in selected frequency register (0 or 1)

       選択した周波数レジスタ(0または1)に周波数(Hz)のデータを書き込みます

      hz frquency value in Hz

      reg selected register value, 0 or 1

   

    generator.setPhase(double phase, uint8_t reg);

      Sets phase in a selected phase register (0 or 1)

       選択した位相レジスタ(0または1)に位相のデータを書き込みます

      phase phase value in degrees

      reg selected register value, 0 or 1

  

    generator.setFrequencyRegister(uint8_t reg);

      Sets frquency register which value is used for output

       周波数レジスタ0または1をICの周波数出力レジスタとして設定します

      reg selected register value, 0 or 1

  

    generator.setPhaseRegister(uint8_t reg);

      Sets phase register which value is used for output

       位相レジスタ0または1をICの位相出力レジスタとして設定します

      reg selected register value, 0 or 1

  

    generator.setWaveForm(uint8_t waveform);

      Sets output signal's waveform

       出力波形を設定します

      waveform 0-sine, 1-triangle, 2-square, 3-square/2


    generator.start(uint8_t waveform, uint8_t freqRegist, uint8_t phaseRegist);

      Start waveform generation

       引数パラメータで波形生成を開始します

      waveform 0-sine, 1-triangle, 2-square, 3-square/2

      freqRegist used frequency register, 0 or 1

      phaseRegist used phase register, 0 or 1

  

    generator.start();

      Start waveform generation with predefined values 

    事前に定義されたレジスタを使って波形生成を開始します


    generator.stop();

      Stops signal generation (puts IC to sleep and reset states) 

      波形生成を停止します(ICをスリープ状態にして状態をリセットします)

  

    generator.reset(bool status);

      Enables or disables chip's reset, puts IC to sleep

       チップのリセットを有効または無効にし、ICをスリープ状態にします

      status enables(true) or disables(false) reset

  

    generator.directRegWrite(uint16_t data);

      Writes 16 bit of data directly to the AD9833 chip - it is up to the user to write a correct value

       16ビットのデータをAD9833チップに直接書き込みます-正しい値を書き込むのはユーザーの責任です

      data 16bit of RAW data

  

    generator.getPhase(uint8_t reg);

      reg from which phase register to return the value, 0 or 1

    0または1の位相レジスタの値を返します

      return phase value which was written by the user 

    返される値はユーザーが書き込んだ値です

   

    generator.getFrequency(uint8_t reg);

     reg from which frequency register to return the value, 0 or 1 

    0または1の周波数レジスタの値を返します

      return frequency value which was written by the user 

    返される値はユーザーが書き込んだ値です

  

    generator.getPhaseRaw(uint8_t reg);

      reg from which phase register to return the value, 0 or 1

    0または1の位相レジスタの値を返します

      return RAW integer phase value which was written to IC 

    返される値はICに書き込まれたRAW型の整数値(バイナリーデータ?)です

   

    generator.getFreqRaw(uint8_t reg);

      reg from which frequency register to return the value, 0 or 1 

    0または1の周波数レジスタの値を返します

      @return RAW integer frequency value which was written to IC 

    返される値はICに書き込まれたRAW型の整数値(バイナリーデータ?)です

  

    generator.getControlRegister();

      return RAW integer control register value which was written to IC 

    ICに書き込まれたコントロールレジスタのRAW型の整数値(バイナリーデータ?)を返します

 

(スクロールバーつきのボックスを使っています)

スケッチ例

スケッチは引用元ライブラリの使用例スケッチを元にしてモディファイしています。IncrementFrequencyTest()関数は本記事の冒頭で挙げた”Billwilliams1952/AD9833-Library-Arduino”の使用例を参考にしています。オリジナルは消さないで、コメントアウトする形で残しました。

最初にインクルードしている"ad9833.h"は、Arduino IDEのライブラリフォルダから呼び出すやり方では、私の場合コンパイルエラーとなりました。当スケッチと同じフォルダにad9833.hとad9833.cppを置いてコンパイルすると問題なく書き込みまでできました。

AD9833の動かし方は、

generator.setFrequency(1000, REG0); // 周波数レジスタREG0へ、1000(Hz)を書き込む
generator.start(SINE_WAVE, REG0, REG0); // サイン波、REG0の周波数、REG0の位相で波形を作り出力をスタート

の2行で波形生成できます。周波数を変えるときにはこの状態のまま、

generator.setFrequency(2000, REG0); 

などと、周波数レジスタへ書き込む値を変えれば、新たな周波数で波形生成するようです。

位相レジスタへのゼロ値書き込みは行っていません。ライブラリがデフォルトでゼロ位相で設定されているのかもしれませんし、AD9833を今まで使ってきましたのでAD9833のレジスタが覚えているのかもしれません。

#include <Arduino.h>
#include "ad9833.h"

#define REG0 			0
#define REG1 			1

#define SINE_WAVE 		0
#define TRIANGLE_WAVE 		1
#define SQUARE_WAVE 		2
#define HALF_SQUARE_WAVE 	3

  AD9833_IC generator(14, 17, 13); // creates new object with pins 14,17,13 as SCK, FSYNC, DATA
                                // and initialises IC with stopped state 
                                // (reset and sleep states are ON);
void setup(){
  
  generator.setFrequency(1000, REG0); // sets 4kHz frequency in the register 0;
  generator.start(SINE_WAVE, REG0, REG0); // starts generation with sine wave with 
                          // selected frequency and phase registers (0 and 0).
	delay(1000); 
}
void loop(){
    generator.stop(); // stops generation;
    delay(2000); 
    generator.start(); // starts generation again;
    delay(5000); 
    IncrementFrequencyTest();
    delay(5000); 
    generator.start(TRIANGLE_WAVE,REG0,REG0); // starts generation with sine wave with 
    delay(2000); 
}
/*
 * Setup a manual ramp from a Start frequency to a Stop frequency in some increment
 * over a ramp time. 
 */
void IncrementFrequencyTest () {
    float startHz = 1000, stopHz = 10000, incHz = 1, sweepTimeSec = 10.0;
    // Calculate the delay between each increment.
    uint16_t numMsecPerStep = (sweepTimeSec * 1000.0) / ((uint16_t)((stopHz - startHz) / incHz) + 1);
    if ( numMsecPerStep == 0 ) numMsecPerStep = 1;
    // Apply a signal to the output. If phaseReg is not supplied, then
    // a phase of 0.0 is applied to the same register as freqReg
    // gen.ApplySignal(SINE_WAVE,REG1,startHz);
    generator.setFrequency(startHz, REG1); // Sets Frequency(Hz) in selected frequency register (0 or 1)
    generator.setWaveForm(SINE_WAVE); // Set param waveform 0-sine, 1-triangle, 2-square, 3-square/2
    //while ( true ) {   
        //gen.SetFrequency(REG1,startHz-incHz);
        generator.setFrequency(startHz-incHz, REG1);// Sets Frequency(Hz) in selected register value, 1
        generator.start(SINE_WAVE, REG1, REG1);          
        for ( float i = startHz ; i <= stopHz; i += incHz ) {
            //YIELD_ON_CHAR
            //gen.IncrementFrequency(REG1,incHz);
   	    // Add/subtract a value from the current frequency programmed in freqReg by the amount given
	    // freqRegでプログラムされた現在の周波数から指定された量だけ値を加算/減算します
	    // float frequency = (freqReg == REG0) ? frequency0 : frequency1;
            // SetFrequency(freqReg,frequency+freqIncHz);

	    generator.setFrequency( i + incHz, REG1);// Sets Frequency(Hz) in selected register value, 1
            //generator.start(SINE_WAVE, REG1, REG1);          
            delay(numMsecPerStep); 
        }
    //}
}

Powered by Blogger | Designed by QooQ

keyboard_double_arrow_down

keyboard_double_arrow_down