Post Go back to editing

is there any way to change frequency in AD9959 without reset to phase accumulator, or, only update az zero phase?

Category: Hardware
Product Number: AD9959

Hello,

I'm working on a new version of my 3 phase generator. The reason to use DDS is that I need to fine tune the phase shifts, what are not exactly 120 degrees(due to mechanical imperfections), but close. Frequency is low. From about 10Hz to 100Hz max.

Now, I try to work out a slow frequency ramp from 0 to 50Hz, in about 7 second: i would not do that with linear sweep, as I see it is way too fast (clock is 20MHz, but still). To have about a hundred discrete step instead of continuous ramp would not be a problem, if, I could find a way to avoid that glitch when I issue I/O update, after updating FTW. I guess it resets phase accumulator no matter where I am in the sinusoidal wave.

If I could sense digitally (I mean, without measuring back the generated analog signal) the zero phase, I would issue I/O update there, but I find no way to do that. Or, is there a function maybe that it only gets updated at certain phase?

How would you solve this?

Thanks!

JG

  • Any idea please?

    I did tried to update frequency only through FTW, but when I write frequency only, it looses the phase difference and at i/o update. All channels restarting with zero phase and are in sync.

  • Hi  ,

    Have you tried activating either Autoclear phase accumulator or Clear phase accumulator. Not sure which one fits perfectly for your application. 

    Autoclear phase accumulator: 

    0 = the current state of the phase accumulator is not impacted by receipt of an I/O_UPDATE signal (default)

    1 = the phase accumulator is automatically and synchronously cleared for one cycle upon receipt of an I/O_UPDATE signal.  

    Clear phase accumulator: 

    0 = the phase accumulator functions as normal (default)

    1 = the phase accumulator memory elements are asynchronously cleared. 

    Let me know if this works for you. 

    All the best,

    Jules

  • It doesn't help :-(

    Both are 1 by default. In that case, with each FTW update I have to rewrite the POW also, because if I do not do it, both will be in the same phase. :

    If I set bit 12, "All channels clear phase accumulator" to one, I have no signal output a all: 

    If I set bit 13, "All channels autoclear phase accumulator" to one, I have all output in the same phase and at IO update it jumps:

    If I set both bit 13 and 12 to 1, I get no output:

    Still the best option is to update POW with the frequency update, but, the problem is that I get these "glitches" at changes. The channel one here starts with 0 phase, channel 2 with 90 degrees shifted.

    Unfortunately, I can not allow these "glitches". Is there any other option to try?

    Thanks a lot!

    JG

  • Hi, any other suggestion please?

    Or, it is not possible with the AD9959?

    Thanks,

    JG

  • Hi  ,

    Just a question, are you planning to synchronize 2 outputs of AD9959 that they have the same frequency and same phase? Probably when changing POW, you might have to issue an IO_Update for both at the same time. 

    All the best,

    Jules 

  • Hi Jules,

    Thank You for your reply!

    No, I use 3 output, same frequency but not the same phase. It is roughly 0 - 120 - 240 degrees, but finetuned in the application.

    At initialization, I write FTW into all the 4 channels once, than I select channels one by one and write POW. At the end I issue an I/O Update. It works fine.

    The problem is, when I change frequency, if I only write the FTW into all channels and issue I/O Update, it "forgets" the phase offset and after I/O Update all channels are starting with the new frequency and all with zero phase. All are in the same phase.

    When I update frequency (once for the 4), I have to rewrite POW also (selecting one by one) and than issue an I/O update. That way, the frequency is correct, the phase is correct, but, at I/O update the channel 0 restarts az 0 degrees, channel one at 120 degrees, channel 3 at 240 degrees, no matter what the phase was before the I/O update. With other words, it resets phase to what is written in POW.

    With other words, is there a way to update frequency without resetting phase accumulator and maintaining the offset between the channels? This is to avoid the glitch the phase reset causes.

    As I described above, I did played with bit 12, "All channels clear phase accumulator" and bit 13, "All channels autoclear phase accumulator" but the result is not what I need. Which is not a surprise since the default setting is zero, which is NOT to reset phase accumulator at I/O Update, but it still does reset it.

    :-(

    Thanks for your help!

    JG

  • ... one more note, it did work with AD9954. There I was struggling a bit too :-), but realized I did set autoclear that time. Now I do not set it for sure. I've checked multiple times :-)

    and, with the 9959 I also loose the phase offset.

    I thought with the 9959 it will be much easier since I do not need to sync the chips, but due to this issue I'm facing now it is actually more problematic and I do not know what is happening.

    This is how I update the frequency now. If I remove the section between the stars, all channels are restarting with 0 phase.

    void update_frequency_DDS(void)
    {
        HAL_GPIO_WritePin(led_blue_GPIO_Port, led_blue_Pin, GPIO_PIN_RESET);
        HAL_GPIO_WritePin(DDS_reset_GPIO_Port, DDS_reset_Pin, GPIO_PIN_SET);
        __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
        HAL_GPIO_WritePin(DDS_reset_GPIO_Port, DDS_reset_Pin, GPIO_PIN_RESET);
        __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();

        writeBuf[0] = 0x04; // address frequency tuning word
        writeBuf[1] = uFTW.bFTW.b0;    // MSB of FTW
        writeBuf[2] = uFTW.bFTW.b1;
        writeBuf[3] = uFTW.bFTW.b2;
        writeBuf[4] = uFTW.bFTW.b3;    // LSB of FTW
        HAL_GPIO_WritePin(DDS_CS_GPIO_Port, DDS_CS_Pin, GPIO_PIN_RESET);
        HAL_SPI_Transmit (&hspi1, writeBuf, 5, 100);
        HAL_GPIO_WritePin(DDS_CS_GPIO_Port, DDS_CS_Pin, GPIO_PIN_SET);
        __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();


        writeBuf[0] = 0b00000000; // address channel select register
        writeBuf[1] = 0b00010000; // select channel 0
        HAL_GPIO_WritePin(DDS_CS_GPIO_Port, DDS_CS_Pin, GPIO_PIN_RESET);
        HAL_SPI_Transmit (&hspi1, writeBuf, 2, 100);
        HAL_GPIO_WritePin(DDS_CS_GPIO_Port, DDS_CS_Pin, GPIO_PIN_SET);
        __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
        writeBuf[0] = 0x05; // select phase offset word
        writeBuf[1] = uPOW0.bPOW0.b0;
        writeBuf[2] = uPOW0.bPOW0.b1;
        HAL_GPIO_WritePin(DDS_CS_GPIO_Port, DDS_CS_Pin, GPIO_PIN_RESET);
        HAL_SPI_Transmit (&hspi1, writeBuf, 3, 100);
        HAL_GPIO_WritePin(DDS_CS_GPIO_Port, DDS_CS_Pin, GPIO_PIN_SET);
        __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();

        writeBuf[0] = 0b00000000; // address channel select register
        writeBuf[1] = 0b00100000; // select channel 1
        HAL_GPIO_WritePin(DDS_CS_GPIO_Port, DDS_CS_Pin, GPIO_PIN_RESET);
        HAL_SPI_Transmit (&hspi1, writeBuf, 2, 100);
        HAL_GPIO_WritePin(DDS_CS_GPIO_Port, DDS_CS_Pin, GPIO_PIN_SET);
        __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
        writeBuf[0] = 0x05; // select phase offset word
        writeBuf[1] = uPOW1.bPOW1.b0;
        writeBuf[2] = uPOW1.bPOW1.b1;
        HAL_GPIO_WritePin(DDS_CS_GPIO_Port, DDS_CS_Pin, GPIO_PIN_RESET);
        HAL_SPI_Transmit (&hspi1, writeBuf, 3, 100);
        HAL_GPIO_WritePin(DDS_CS_GPIO_Port, DDS_CS_Pin, GPIO_PIN_SET);
        __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();

        writeBuf[0] = 0b00000000; // address channel select register
        writeBuf[1] = 0b01000000; // select channel 2
        HAL_GPIO_WritePin(DDS_CS_GPIO_Port, DDS_CS_Pin, GPIO_PIN_RESET);
        HAL_SPI_Transmit (&hspi1, writeBuf, 2, 100);
        HAL_GPIO_WritePin(DDS_CS_GPIO_Port, DDS_CS_Pin, GPIO_PIN_SET);
        __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
        writeBuf[0] = 0x05; // select phase offset word
        writeBuf[1] = uPOW2.bPOW2.b0;
        writeBuf[2] = uPOW2.bPOW2.b1;
        HAL_GPIO_WritePin(DDS_CS_GPIO_Port, DDS_CS_Pin, GPIO_PIN_RESET);
        HAL_SPI_Transmit (&hspi1, writeBuf, 3, 100);
        HAL_GPIO_WritePin(DDS_CS_GPIO_Port, DDS_CS_Pin, GPIO_PIN_SET);
        __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();

        writeBuf[0] = 0b00000000; // address channel select register
        writeBuf[1] = 0b10000000; // select channel 3
        HAL_GPIO_WritePin(DDS_CS_GPIO_Port, DDS_CS_Pin, GPIO_PIN_RESET);
        HAL_SPI_Transmit (&hspi1, writeBuf, 2, 100);
        HAL_GPIO_WritePin(DDS_CS_GPIO_Port, DDS_CS_Pin, GPIO_PIN_SET);
        __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
        writeBuf[0] = 0x05; // select phase offset word
        writeBuf[1] = uPOW3.bPOW3.b0;
        writeBuf[2] = uPOW3.bPOW3.b1;
        HAL_GPIO_WritePin(DDS_CS_GPIO_Port, DDS_CS_Pin, GPIO_PIN_RESET);
        HAL_SPI_Transmit (&hspi1, writeBuf, 3, 100);
        HAL_GPIO_WritePin(DDS_CS_GPIO_Port, DDS_CS_Pin, GPIO_PIN_SET);
        __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();

        HAL_GPIO_WritePin(IO_update_GPIO_Port, IO_update_Pin, GPIO_PIN_SET);
        __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
        HAL_GPIO_WritePin(IO_update_GPIO_Port, IO_update_Pin, GPIO_PIN_RESET);

    }