Continue to Site

# Rasp Pi pico and AD9834 DDS chip

Status
Not open for further replies.
I am experimenting with a AD9834 freq generator chip and a Raspberry pi pico chip, communicating via SPI. I can get a waveform to show on my scope but it doesnt seem
to correspond correctly with my calculated freq word. I am using the AD9834 with 75 mhz clock. So my freq calcs are: 7 mhz desired, so 7e6 * 2^28/75e6=0x17E4B18. When I chop the result up into two 14 bit values, and OR the freq reg 0 bits (01) on the end, I end up with MSB=0x45F9 and LSB=0x4b18. I load this into my micropython program, run the program, load the LSB first into the AD9834, then MSB it starts OK but my actual freq is 13 mHz. I get a nice sine wave, 200 mV peak to peak, but wrong freq. I am pulling my hair out trying to figure this out, I checked and rechecked my LSB MSB calculation several times , I know those are right. Its almost like the MCLK is not really running at 75 mHZ, but my scope confirmed it was (74.9ish mhz). ANyone run into this?

#### KlausST

##### Super Moderator
Staff member
Hi,

I guess there is a misunderstanding in the ORed bits. They need to be on the left side

For self checking what's the problem you could do the math in reverse: calculate the value for the shown 13MHz and compare the bitvsequence with the uploaded bit sequence. It's one of the first things I do when things don't work as I expect.

****

Some recommendations for future forum postings:
You give some information, but not much that we can verify.
You could show us scope pictures of the SPI communication and the output frequency.

Please mind that there is a big difference between 75mHz and 75MHz. I've worked with both.

Klaus

If the frequency reg value is:0x017E4B18 = 0b 0000 0001 0111 1110 0100 1011 0001 1000
Then control register should be 0x2000
LSB register: f_value AND 0x3FFF OR 0x4000 = 0x4B18
MSB register: f_value >> 14 bits, 0x05F9
then AND 0x3FFF OR 0x4000 = 0x45F9
...so your values seem to be O.K.

Last edited:

#### barry

I am experimenting with a AD9834 freq generator chip and a Raspberry pi pico chip, communicating via SPI. I can get a waveform to show on my scope but it doesnt seem
to correspond correctly with my calculated freq word. I am using the AD9834 with 75 mhz clock. So my freq calcs are: 7 mhz desired, so 7e6 * 2^28/75e6=0x17E4B18. When I chop the result up into two 14 bit values, and OR the freq reg 0 bits (01) on the end, I end up with MSB=0x45F9 and LSB=0x4b18. I load this into my micropython program, run the program, load the LSB first into the AD9834, then MSB it starts OK but my actual freq is 13 mHz. I get a nice sine wave, 200 mV peak to peak, but wrong freq. I am pulling my hair out trying to figure this out, I checked and rechecked my LSB MSB calculation several times , I know those are right. Its almost like the MCLK is not really running at 75 mHZ, but my scope confirmed it was (74.9ish mhz). ANyone run into this?
17e4b18=>
LSB=4b1b
MSB=>85f9 NOT 45f9

for the LSB register you append 01. For the MSB you append 10:

#### mjrx

##### Junior Member level 1
Yes the ORed bits are on the left, upper end. This can be seen by seeing the MSB=0x45F9 and LSB=0x4b18 from the first calc'd val of 0x17E4B18.

#### Attachments

• IMG_2369.jpg
600.9 KB · Views: 58
• Python9834.txt
1.3 KB · Views: 53

#### mjrx

##### Junior Member level 1
That doesn't jive with the AD9834 datasheet. To load freq0 reg, you need 01at DB15 & DB14. Appending 10 to the 14 bits writes to freq 1 reg. I just tried it to confirm.

#### KlausST

##### Super Moderator
Staff member
Hi

When I calculate back the loaded frequency MSB is 0x0B16 .. so close to 0x0B18 which is close to your 0x4B18 (including the ORed 0x4000).
It seems your LSB value is used as MSB...

--> show your code, or show the complete SPI communication.

Klaus

#### mjrx

##### Junior Member level 1
The 0x0B18 is the LSB. Or'd with 0x4000 it becomes 0x4B18. Its the LSB, not the MSB. I have code attached in an earlier post, (go up 3), along with a oscope screenshot, but I am just entering the calc'd values into the SPI.write(). I havent calc'd them yet in my code, I'm doing it with right now on paper and calculator to understand it better. Eventually I will do it on the pico in Python. This is what I am thinking:

freq = 7000000
MCLK = 75000000
word = hex(int(round((freq*2**28)/MCLK)))

MSB = (int(word, 16) & 0xFFFC000) >> 14
LSB = int(word, 16) & 0x3FFF

MSB |= 0x4000
LSB |= 0x4000

#### mjrx

##### Junior Member level 1
D0 you think I got this wrong? RIght now for 7 mhz with a 75 mhz clock I have:

MSB = 0x40BF
LSB = 0x4B18

Painfully calc'd on paper with binary written out. It yields 13 mhz (see scope shot).

Id like to say thanks for responding on this, and so quickly !

#### mjrx

##### Junior Member level 1
Swapping the MSB (40BF) with LSB (4B18) yields 800 khz

#### barry

That doesn't jive with the AD9834 datasheet. To load freq0 reg, you need 01at DB15 & DB14. Appending 10 to the 14 bits writes to freq 1 reg. I just tried it to confirm.
Yes, it jibes with the data sheet. Look at table 10.

#### mjrx

##### Junior Member level 1
Correct, that's where I got it from. I am not using FREQ1, I am using FREQ0. There are two registers you can store frequency, FREQ0 to FREQ1, and select which register you use with the control register. See table 6 bit DB11, and table 7 & 8. By default DB11 is 0, and this selects FREQ0. This I tested and I know this for sure. If you write a word with 01 appended to the 14 bit word, you are writing that value to FREQ0 register. If you write a word with 10 appended to it, you are writing to FREQ1 register, and with 00 on it, to the control register. FREQ0 does not mean LSB and FREQ1 does not mean MSB, these are two seperate 16 bit registers. This is used, say in a VFO for a transceiver, to quickly change freqs, say if you were operating in split mode. Both registers need the full 16 bit write, you don't write your LSB to FREQ0 and your MSB to FREQ1, I can say for sure you wont get what you want. In fact your MSB would never make it to FREQ1, it would be received into the LSB space for FREQ1, because the AD9834 expects the LSB to come in first. You can either switch registers by having your uP set bit FSEL, DB22, or by setting pin 9, FSELECT. LSB and MSB are what needs to be sent on each freq change, you are sending 16 bits to either FREQ0 or FREQ1 register, well technically 14 bits with upper 2 bits set to point to the register, FREQ0 or FREQ1 or CNTRL, not LSB and MSB. Anyone else want to comment on this?

Thanks for the replies. I appreciate any comments. Not an authority on this, but I am not a rank newbie with this stuff either, just stuck on a few things. I can almost recite that data sheet, and AN-1070 appnote verbatim I've read them so many times!

Anyone else want to comment on this?

#### KlausST

##### Super Moderator
Staff member
Hi,
Painfully calc'd on paper with binary written out. It yields 13 mhz (see scope shot).
I did this too. And I guess you will have to do as long as you do digital electronics. Nothing special.

But you also may use Excel:

So as written, your values of post#1 seem to be O.K.

In post#8 and post#9 you used different (wrong) MSB value.

****
13millihertz is not possible.
****

In your code, after transmitting the LSB you set CS = HIGH, but not LOW to transmit the MSB. This won´t work properly.

****

When transferring 28 bit values, ... according datasheet one should send 2x 16 bits. I wonder how this is synchronized. Without synchronizing there is a risk of swapping MSB with LSB.
This is what I already suspected in post#6.

Klaus

#### barry

Ah, I got it wrong. After reading the data sheet 10 times. I thought FREQ0 was LSB and FREQ1 was MSB. So you write two consecutive 16 bit word, with the upper two bits set appropriately, as I think you have. BUT, you also have to set the control register correctly, particularly DB13 and DB12. See table 6.

#### mjrx

##### Junior Member level 1
Right on. In my code, to init the AD9834, I write 0x2100 to control register (00), which sets DB13 and DB8, the reset bit. After a write to FREQ0 (01), I write 0x2000 to control register (00), which takes the part out of reset, and at that point a waveform appears on my scope. I think DB12, (HLB) is optional, as it looks like it allows writing only to one or the other, MSB or LSB, to allow fine freq adjustment or course freq adjustment, avoiding at least one write. I'll probably use this in the end, the project is a superhet SDR HF receiver. The AD9834's sine wave is applied to a balanced RF mixer to produce an IF frequency. Thanks for the help.

#### barry

So, is it working?

#### mjrx

##### Junior Member level 1
Thanks Klaus,
I meant 13 megahertz, see scope shot in post #6. I don't know what you mean by "I wonder how this is synchronized." Each write a 2 byte array (16 bits) is sent. MSB = bytearray([0x45, 0xF9]). And my CS,

CS.low() <-------------------------------------- Low set
time.sleep_ms(10)
spi.write(LSB) #LSB is first to get written
time.sleep_ms(10)
CS.high()
#time.sleep_ms(500)

CS.low() <-------------------------------------- Low set
time.sleep_ms(10)
spi.write(MSB) #MSB is last to get written
time.sleep_ms(10)
CS.high()
time.sleep_ms(500)

Those sleeps a probably aren't needed, I just didn't know if I should have the slave select on for awhile before the SPI clock went out. I built a test script to get my values:

freq = 7000000
MCLK = 75000000
word = hex(int(round((freq*2**28)/MCLK)))
print(freq)
print(word)

MSB = (int(word, 16) >> 14)
LSB = int(word, 16) & 0x3FFF
print(hex(MSB))
print(hex(LSB))
MSB |= 0x4000
LSB |= 0x4000

print('MSB =',hex(MSB))
print('LSB =',hex(LSB))

reg = int(freq * 3.57914)
print('With constant', hex(reg))

Output:

7000000
0x17e4b18
0x5f9
0xb18
MSB = 0x45f9
LSB = 0x4b18
With constant 0x17e4b1c

I will incorporate this into the code.

#### barry

For SPI you can't just hold CSn low for an arbitrary time, e.g. 10mS, if the clock is running. I'm not sure what your spi.write routine does, but when CSn goes low, the next clock will start latching in the data. Verify your timing.

#### mjrx

##### Junior Member level 1
Hi Barry,
I seem to be on the write track, more testing needed. I'm not too happy with the resolution of the chip though. And accuracy of the freq according to the calc'd and entered LSB/MSB combo seems to off a bit, maybe +- 100 hz? The other thing that was unexpected was the amplitude change in the output waveform at increasing frequencies. At 10 Mhz its 250 mV, at 15 mHz its 180mV, and down from there. It won't work for me like that. Possibly connect one of the ucontroller's DAC's to the FS adjust, Pin1, but that adds alot of complexity to the whole thing, especially if the change in amplitude is not linear. Yikes! I have to test throughout my desired freq range and plot the results. Chip is promising, but not quite as accurate as I had hoped.
--- Updated ---

I think the clock idles high, and starts when the CS goes low.

Last edited:

#### barry

Your accuracy sounds way off, based on the fact that you’ve got a 28 bit phase accumulator. Probably a calculation issue. The frequency rolloff is not the chip, it’s your external circuitry.
--- Updated ---

Again: If your SPI clock starts after CS goes low, and the you start sending data 1ms later, you’re going to have problems. Clock, data and CS need to meet the SPI requirements, which it sounds like you’re not doing. Look at figure 5.

Last edited:

#### mjrx

##### Junior Member level 1
Yep, makes sense. I took out the delays. What about the amplitude issue? Is that normal for it to diminish with increasing frequency? Searches I have done on that seem to say so, but wonder your experience.

Status
Not open for further replies.