SPI interfacing with AD5791 DAC via Raspberry Pi? - Page 1
Forum section: electronics / beginners

author: imisaac
author_rank: Regular Contributor
timestamp: April 17, 2019, 09:14:09 pm
content: The SPI pins on the AD5791 evaluation board is connected to a Raspberry Pi 3 Model B. In order to set some DAC output voltages, I tried to follow the guide here:https://wiki.analog.com/resources/quick-start/ad5791In that guide, the DAC is supposed to output a midrange voltage (0V? I used +/-10V voltage references) after issuing the following string of binary bits to the DAC (0001 1000 0000 0000 0000 0000).However, nothing happened....Does the ordering of the bit stream need to be reversed (i.e. MSB first) in order to set the DAC register or I am missing another step in setting the /LDAC or /Clr bits? Or Raspberry Pi is not suitable for SPI with AD5791 for more subtle reasons?As a complementary info, I used a loop-back test (i.e. connecting MOSI to MOSO) to confirm that I am indeed outputing something already.Any tips would be extremely useful and thanks in advance!

author: LateLesley
author_rank: Frequent Contributor
timestamp: April 18, 2019, 02:27:07 am
content: I think we need more information to be able to help you. You've told us that the reference voltages are +/-10V, but we don't know how the rest of it is connected.First, supply voltages. What are you feeding in to :-VddVssVccIOVccI think we can assume that VREFPSand VREFPFare at +10V, and that VREFNSand VREFNFare at -10V ??when sending data, what are you setting the control pins to? (/LDAC, /CLR, /RESET)These pins will need set for it to work, as these set the output from the register values.You may be loading the value into the register, but you then need to set the control pins to set the output to the DAC register value.EDIT : Just noticed, you can set the LDAC, CLR, RESET with data sent to the device, it's further down the datasheet, under "Writing to the Software Control Register". So try writing the DAC register, then sending to the software control register afterwards to latch the data in to the output.

author: Dave
author_rank: Super Contributor
timestamp: April 18, 2019, 06:48:02 am
content: You need to write to the control register first and disable the output tristate mode.All of this is described in the guide you linked to in your post.

author: imisaac
author_rank: Regular Contributor
timestamp: April 19, 2019, 07:23:08 pm
content: Thanks all. I have not got the Pi set up working with AD5791 yet, but here is what I have tried.To make sure the AD5791 evaluation board was functional, I connected a SDP board (also from AD) to it. Then, I ran the evaluation software on a Windows PC. In this set up, the DAC output could be manipulated. This implied that the DAC hardware was fine.The evaluation board was powered by a single power supply of 4 V. There was no need to have a separate voltage reference. Nevertheless, I checked the Vref pins directly on AD5791 and got +/-10 volts from them.On the software side, I was using Matlab to talk to Pi. Here is the code I was testing.Code:clear rpi; clear spidevice;rpi = raspi('192.168.178.49','xx','xxxx');enableSPI(rpi);spidevice = spidev(rpi,'CE0',2);wdata = ['110011001100110011001100'];writeAD5791(spidevice,wdata);function  = writeAD5791(spidevice,wdata)wdata = flip(wdata);readdata = writeRead(spidevice,[bin2dec(wdata(1:8)) bin2dec(wdata(9:16)) bin2dec(wdata(17:end))],'uint8');pause(1);endTo make sure that the code was spitting out the bits, I connected the SPI outputs on the Pi to a ADALM20000 based logic analyser. The result from the first SPI write is attached. The guide to use SCOPY software to debug SPI is given here:https://ez.analog.com/university-program/b/blogs/posts/adalm2000-spi-debugIt looks like the output bit stream is different from the one I intended. In the SPI write function I created, the intended bit stream was flipped in the order such that the MSB is spit out first. Looking at the logic analyser plot, however, the second bit counting from the left turns out to be wrong!Does anyone know why this is happening? I guess this could be one of the reasons that the AD5791 was not responding...Thanks in advance.

author: imisaac
author_rank: Regular Contributor
timestamp: April 19, 2019, 08:22:11 pm
content: This is a short follow-up. It seems that the wrong bit stream was due to the logic analyser configuration in SCOPY. If the transition edges of each of the four SPI pins were meeting some "condition", the right bit stream could be observed.I am not sure why it worked though....In particular, for each of the SPI pin, how do I know it is rising edge or falling edge detection?The present edge detection characteristics are attached in case someone knows the reason.Update:In the Matlab program attached in the previous message, I used "mode 2" for the SPI communication. According to the wiki page of SPI,https://en.wikipedia.org/wiki/Serial_Peripheral_Interfacemode 2 means that CPOL=1 and CPHA=0. That is, the SPI clock is 1 when idle. The data bits are spit out on the leading edge of the clock pulses. Therefore, in the logic analyser, I should set the MOSI an MISO pins for the rising edge detections as well.Attached is the timing diagram for AD5791. The confusing part is that it is unclear the CPOL is 1 or 0 when idle for AD5791. Anyone knows the SPI mode for AD5791?

author: mikerj
author_rank: Super Contributor
timestamp: April 21, 2019, 09:54:55 am
content: That looks like a Mode 1 device to me, though it's not the clearest timing diagram I've seen. The clock pulses are numbered in the center, and the incoming data bit is being latched on the trailing edge of the clock pulse (CPHA=1) and the leading edge is positive going (CPOL=0).

author: MarkF
author_rank: Super Contributor
timestamp: April 21, 2019, 05:57:01 pm
content: I think you would be better off with the FULL datasheet.https://www.analog.com/media/en/technical-documentation/data-sheets/ad5791.pdf

author: imisaac
author_rank: Regular Contributor
timestamp: April 23, 2019, 03:46:15 pm
content: Thanks mikerj!I used the SPI mode 1, and the DAC output actually did something (went to -10 V) before it went back to zero instead of the voltage that I intended to. The following Matlab code was used.Code:clear rpi; clear spidevice;rpi = raspi('192.168.178.49','xx,'xxx');enableSPI(rpi);spidevice = spidev(rpi,'CE0',1,500000);%% Write to the "software control register" to reset the DAC to power-on statewdata = ['010000000000000000000100'];writeAD5791(spidevice,wdata);%% Write to the "control register" to initialize the DAC to normal statewdata = ['001000000000000000010010'];writeAD5791(spidevice,wdata);%% Write to the "DAC register" to place some non-zero voltage value at the registerwdata = ['000111000000000000000000'];writeAD5791(spidevice,wdata);%% Write to the "software control register" to enable the DAC outputwdata = ['010000000000000000000001'];writeAD5791(spidevice,wdata);function  = writeAD5791(spidevice,wdata)wdata = flip(wdata);readdata = writeRead(spidevice,[bin2dec(wdata(1:8)) bin2dec(wdata(9:16)) bin2dec(wdata(17:end))],'uint8');pause(2);endI again verified the bit patterns with a logic analyser (picture attached), and the bit patterns seemed to be as expected.I am running out of debugging ideas to have this AD5791 output some voltages using a Matlab/Raspberry Pi combo setup. Can someone advice?Thanks in advance.Meanwhile, I am planning to switch to the Arduino system to try out next......

author: mikerj
author_rank: Super Contributor
timestamp: April 23, 2019, 07:56:59 pm
content: What is the order of the above sequence? Looking at the data you are sending, I think you may have the first two swapped?reset.jpg: Bits23:20 = 0010 = Write to the config register to disable output ground clamp and take DAC out of tri-stateinitialize.jpg: Bits23:20 = 0100 = Write to the software control register to reset the device, returning all registers to power-on defaultssetdacout.jpg: Bits23:20 = 0000 Write to No-Operation register. This will do nothing.enabledact.jpg: Bits23:20 = 1000 Read to No=Operation register. This will do nothing.Performing a software reset is fine to ensure the chip is in it's default state, but obviously must be the first thing you do other wise you lose all the operations performed before it.The last two are clearly wrong, the top four bits should be 0001 to write to the DAC register, and 1001 to read the DAC register. Additionally if the LDAC pin is not held low during the write then you will either need to toggle LDAC after the SYNC (chip select) pin has gone high, or write to the software control register to perform an LDAC operation. Easiest to just tie LDAC low, so the DAC gets updated when SYNC is de-asserted.

author: imisaac
author_rank: Regular Contributor
timestamp: April 23, 2019, 09:41:39 pm
content: Thanks, mikerj. The bit pattern observed by the logic analyzer was reversed by purpose in order to follow the passage given in the datasheet:QuoteIn the subroutine where the bits were spit out (e.g. see the code below), I reversed the binary bit pattern such that the MSB is sent to the SPI slave (AD5791 in this case) first.Code:function  = writeAD5791(spidevice,wdata)wdata = flip(wdata);readdata = writeRead(spidevice,[bin2dec(wdata(1:8)) bin2dec(wdata(9:16)) bin2dec(wdata(17:end))],'uint8');pause(2);endTherefore, in the reset.jpg, the MSB is the right most digit. That is, I was attempting to write ('0') to the '100' register address with '100' values for the RESET, CLR, and LDAC bits.In the initialize.jpg, similarly, I was attempting to write ('0') to the '010' register address with '000001001' values for the LIN COMP, SDODIS, BIN/2sC, DACTRI, OPGND, RBUF bits.However, your observation is very interesting because it suggests that I actually did not have to reverse the bit pattern at all before writing it to the SPI slave device. I will give non-reversal pattern a try to see what happens.Last but not least, you mentioned to tie the LDAC low all the time. Does it mean I short the physical LDAC pin to the DGND pin on the evaluation board? Thanks.

author: imisaac
author_rank: Regular Contributor
timestamp: April 24, 2019, 08:27:39 am
content: This is a follow-up test. The working solution is given below:1. The bit pattern to be sent to the SPI slave device (i.e. AD5791) does not need to be reversed in order.2. The SPI mode of AD5791 can be either mode 1 (thanks to mikerj) and mode 3 (thanks to rrosario from this threadhttps://ez.analog.com/data_converters/precision_dacs/f/q-a/110156/spi-mode-of-ad5791/326300#326300). Both work equally well in my test program.3. The LDAC bit should be set to 1 right after writing a value to the DAC register to “trigger” the output. This creates a square pulse on the LDAC pin. This is software triggering using the SPI bus.4. An alternative way to trigger the output without writing to the LDAC bit is to physically short the LDAC pin and the DGND pin on the AD5791 evaluation board. The DAC output is updated automatically right after writing a value to the DAC register.5. The interconnection between the AD5791 evaluation board and the Raspberry Pi are 5 wires. They include SCLK, SYNC, SDO, SDIN, and DGND on the evaluation board connecting to SPI0_CLK, SPI0_CE0, SPI0_MISO, SPI0_MOSI, and Ground respectively on the Pi.6. The jumper settings on the AD5791 evaluation board are as follows: LK1=A, LK2=inserted, LK3=removed, LK4=removed, LK5=inserted, LK6=removed, LK7=removed, LK8=B, LK9=B, LK10=B, LK11=removed.7. An working test program written in Matlab to drive the AD5791 is shared below (the physical pin of LDAC does not need to be grounded in this case):Code:clear rpi; clear spidevice;rpi = raspi('192.168.2.2','xx,'xxx');enableSPI(rpi);spidevice = spidev(rpi,'CE0',1,500000);%% Write to the "software control register" to reset the DAC to power-on statewdata = ['010000000000000000000100'];writeAD5791(spidevice,wdata);%% Write to the "control register" to initialize the DAC to normal statewdata = ['001000000000000000010010'];writeAD5791(spidevice,wdata);%% Write to the "DAC register" to place some non-zero voltage value at the registerwdata = ['000111000000000000000000'];writeAD5791(spidevice,wdata);%% Write to the "software control register" to enable the DAC outputwdata = ['010000000000000000000001'];writeAD5791(spidevice,wdata);%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%function  = writeAD5791(spidevice,wdata)readdata = writeRead(spidevice,[bin2dec(wdata(1:8)) bin2dec(wdata(9:16)) bin2dec(wdata(17:end))],'uint8');pause(0.5);endThanks all!

author: mikerj
author_rank: Super Contributor
timestamp: April 24, 2019, 11:03:47 am
content: Glad you got it working, and thanks for letting us know.

author: imisaac
author_rank: Regular Contributor
timestamp: April 29, 2019, 02:13:22 pm
content: Just a short update.I added a ground isolator for the SPI bus (LTM2887 evaluation board) such that the ground of the USB is not connected to the digital ground of the AD5791 DAC.Attached is a picture of the current setup.

author: imisaac
author_rank: Regular Contributor
timestamp: April 30, 2019, 03:27:58 pm
content: Just another short update.In the datasheet of AD5791, the voltage output noise floor is specified at ~8 nV/√Hz (see the attached figure).Using the setup presented here (unboxed, not carefully shielded yet), I measured the noise floor to be ~20 nV/√Hz (see the measurement plot).Has anyone managed to reproduce the noise floor of AD5791 in the datasheet?Thanks in advance.

author: RandallMcRee
author_rank: Frequent Contributor
timestamp: April 30, 2019, 04:36:15 pm
content: Quote from: imisaac on April 30, 2019, 03:27:58 pmI have not tried, yet, but there would be no way without proper shielding at those low levels. The spuriae in your plot look like unshielded interference problems, as well. In addition, air drafts become important (although not at 1khz!).What frequency range are you really interested in? You ought to first verify that you can get reliable noise measurements with a grounded output. Especially when using ground isolation, you could be measuring some artifacts unrelated to the 5791. Your measurement noise floor should be measured, first.

author: imisaac
author_rank: Regular Contributor
timestamp: April 30, 2019, 09:49:18 pm
content: Thanks RandallMcRee for the grounding suggestion.I am interested in the white noise floor (the flat part of the noise spectrum) of the AD5791.By "grounding" the DAC output, you meant to short the DAC output to the earth ground when it's on OR you meant to set the DAC output to zero volt?

author: imisaac
author_rank: Regular Contributor
timestamp: May 09, 2019, 04:58:34 pm
content: Ok, I wrapped the enclosure all over with aluminum foil (see picture). The noise of the AD5791 evaluation board gets improved significantly (see plot).However, it is still somewhat worse than the AD5791 datasheet spec. Maybe i am now limited by my noise measuring device.Anyways, there are strange interference peaks on top of the white noise floor.Does anyone know how to remove these peaks?Thanks in advance.